l2c_utils.cc revision b8a477e9ac51898b05cb328eda897d95f1ef3d02
15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 1999-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  This file contains L2CAP utility functions
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <stdio.h>
265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h>
275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
29258c2538e3b62a8cdb403f2730c45d721e5292b4Pavlin Radoslavov#include "bt_common.h"
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h"
31911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_utils.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_api.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btm_int.h"
34911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "btu.h"
35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "device/include/controller.h"
365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcidefs.h"
37911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "hcimsgs.h"
38911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2c_int.h"
39911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2cdefs.h"
40a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#include "osi/include/allocator.h"
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
42911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonextern fixed_queue_t* btu_general_alarm_queue;
4378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
45ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
468451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Function         l2cu_can_allocate_lcb
478451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
488451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Description      Look for an unused LCB
498451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
508451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren * Returns          true if there is space for one more lcb
518451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
528451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren ******************************************************************************/
538451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngrenbool l2cu_can_allocate_lcb(void) {
548451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  for (int i = 0; i < MAX_L2CAP_LINKS; i++) {
558451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren    if (!l2cb.lcb_pool[i].in_use) return true;
568451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  }
578451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren  return false;
588451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren}
598451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren
608451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren/*******************************************************************************
618451ad010e26562d4a4c7d0d135c70c4325ee6b5Emil Lenngren *
62ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_lcb
63ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
64ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look for an unused LCB
65ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
66ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          LCB address or NULL if none found
67ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
68ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
69c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskitL2C_LCB* l2cu_allocate_lcb(const bt_bdaddr_t& p_bd_addr, bool is_bonding,
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            tBT_TRANSPORT transport) {
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->in_use) {
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->l2c_lcb_timer);
77911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      alarm_free(p_lcb->info_resp_timer);
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(p_lcb, 0, sizeof(tL2C_LCB));
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
80c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski      p_lcb->remote_bd_addr = p_bd_addr;
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->in_use = true;
83911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTED;
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->handle = HCI_INVALID_HANDLE;
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_flush_tout = 0xFFFF;
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->l2c_lcb_timer = alarm_new("l2c_lcb.l2c_lcb_timer");
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->info_resp_timer = alarm_new("l2c_lcb.info_resp_timer");
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->idle_timeout = l2cb.idle_timeout;
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->id = 1; /* spec does not allow '0' */
90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->is_bonding = is_bonding;
91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->transport = transport;
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->tx_data_len =
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          controller_get_interface()->get_ble_default_data_packet_length();
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->le_sec_pending_q = fixed_queue_new(SIZE_MAX);
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (transport == BT_TRANSPORT_LE) {
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_ble_links_active++;
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_ble_link_adjust_allocation();
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.num_links_active++;
101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_link_adjust_allocation();
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1031a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#if (L2CAP_UCD_INCLUDED == TRUE)
104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_out_sec_pending_q = fixed_queue_new(SIZE_MAX);
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->ucd_in_sec_pending_q = fixed_queue_new(SIZE_MAX);
1061a3844f933bd63c8a381371dabfb35c6a0249e3ePavlin Radoslavov#endif
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_xmit_data_q = list_new(NULL);
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free LCB found */
113911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
1145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_update_lcb_4_bonding
119ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
120ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark the lcb for bonding. Used when bonding takes place on
121ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  an existing ACL connection.  (Pre-Lisbon devices)
122ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
123ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Nothing
124ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
125ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
126c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskivoid l2cu_update_lcb_4_bonding(const bt_bdaddr_t& p_bd_addr, bool is_bonding) {
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
1285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) {
130c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    VLOG(1) << __func__ << " BDA: " << p_bd_addr
131c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski            << " is_bonding: " << is_bonding;
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->is_bonding = is_bonding;
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_lcb
139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Release an LCB. All timers will be stopped and freed,
141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  channels dropped, buffers returned etc.
142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_lcb(tL2C_LCB* p_lcb) {
147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->in_use = false;
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Stop and free timers */
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->l2c_lcb_timer);
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->l2c_lcb_timer = NULL;
155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_lcb->info_resp_timer);
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->info_resp_timer = NULL;
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any unfinished L2CAP packet on this link */
159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  osi_free_and_reset((void**)&p_lcb->p_hcit_rcv_acl);
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
161d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */
163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_remove_sco_links(p_lcb->remote_bd_addr);
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->sent_not_acked > 0) {
167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_le_xmit_window += p_lcb->sent_not_acked;
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_le_xmit_window > l2cb.num_lm_ble_bufs) {
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.controller_xmit_window += p_lcb->sent_not_acked;
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (l2cb.controller_xmit_window > l2cb.num_lm_acl_bufs) {
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
17798657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach    }
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17998657a365c7230b84a005c63ce5bcf036d69f6ebAndre Eisenbach
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Reset BLE connecting flag only if the address matches
181c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  if (l2cb.ble_connecting_bda == p_lcb->remote_bd_addr)
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.is_ble_connecting = false;
1835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_process_fixed_disc_cback(p_lcb);
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ensure no CCBs left on this LCB */
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       p_ccb = p_lcb->ccb_queue.p_first_ccb) {
191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell BTM Acl management the link was removed */
195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING))
197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport);
198ef92b534112a5df57de11ef45f5174f75d44b355Andre Eisenbach
199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release any held buffers */
200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_xmit_data_q) {
201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!list_is_empty(p_lcb->link_xmit_data_q)) {
202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BT_HDR* p_buf = static_cast<BT_HDR*>(list_front(p_lcb->link_xmit_data_q));
203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      list_remove(p_lcb->link_xmit_data_q, p_buf);
204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
2056c303aeca25783453333172d0b29e5472f1b1c93Chris Manton    }
206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    list_free(p_lcb->link_xmit_data_q);
207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->link_xmit_data_q = NULL;
208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clean up any security pending UCD */
212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_ucd_delete_sec_pending_q(p_lcb);
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Re-adjust flow control windows make sure it does not go negative */
216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_ble_links_active >= 1) l2cb.num_ble_links_active--;
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_ble_link_adjust_allocation();
220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.num_links_active >= 1) l2cb.num_links_active--;
22292ac2d8919f8e38a091903270eb5500073d67d4bMudumba Ananth
223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_link_adjust_allocation();
224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check for ping outstanding */
227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_echo_rsp_cb) {
228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_ECHO_RSP_CB* p_cb = p_lcb->p_echo_rsp_cb;
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Zero out the callback in case app immediately calls us again */
231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_echo_rsp_cb = NULL;
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_cb)(L2CAP_PING_RESULT_NO_LINK);
234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2355e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar
236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check and release all the LE COC connections waiting for security */
237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->le_sec_pending_q) {
238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q)) {
239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      tL2CAP_SEC_DATA* p_buf =
240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (tL2CAP_SEC_DATA*)fixed_queue_try_dequeue(p_lcb->le_sec_pending_q);
241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf->p_callback)
242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf->p_callback(p_lcb->remote_bd_addr, p_lcb->transport,
243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          p_buf->p_ref_data, BTM_DEV_RESET);
244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
2455e8a3d7790e8c0e744173dfa8bb76a567160cbfaNavin Kochar    }
246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    fixed_queue_free(p_lcb->le_sec_pending_q, NULL);
247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->le_sec_pending_q = NULL;
248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_bd_addr
254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  remote BD address.
257ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
258ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
259ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
260ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
261c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskitL2C_LCB* l2cu_find_lcb_by_bd_addr(const bt_bdaddr_t& p_bd_addr,
262c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                                   tBT_TRANSPORT transport) {
263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
2655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && p_lcb->transport == transport &&
268c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski        (p_lcb->remote_bd_addr == p_bd_addr)) {
269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
2705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
278ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
279ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_conn_role
280ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
281ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Determine the desired role (master or slave) of a link.
282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If already got a slave link, this one must be a master. If
2839ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  already got at least 1 link where we are the master, make
2849ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this also a master.
285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          HCI_ROLE_MASTER or HCI_ROLE_SLAVE
287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_conn_role(tL2C_LCB* p_this_lcb) { return l2cb.desire_role; }
2905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2c_is_cmd_rejected
294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
295ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks if cmd_code is command or response
296ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If a command it will be rejected per spec.
2979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  This function is used when a illegal packet length is
2989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  detected.
299ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
300ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if cmd_code is a command and it is rejected,
301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if response code. (command not rejected)
302ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
303ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2c_is_cmd_rejected(uint8_t cmd_code, uint8_t id, tL2C_LCB* p_lcb) {
305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  switch (cmd_code) {
3068fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONN_REQ:
3078fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_CONFIG_REQ:
3088fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_DISC_REQ:
3098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_ECHO_REQ:
3108fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_INFO_REQ:
3118fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_CONN_REQ:
3128fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_AMP_MOVE_REQ:
3138fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta    case L2CAP_CMD_BLE_UPDATE_REQ:
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_send_peer_cmd_reject(p_lcb, L2CAP_CMD_REJ_MTU_EXCEEDED, id,
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                L2CAP_DEFAULT_MTU, 0);
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("Dumping first Command (%d)", cmd_code);
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return true;
3188fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    default: /* Otherwise a response */
320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3228fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
3238fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
3248fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
325ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
326ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_build_header
327ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
328ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Builds the L2CAP command packet header
329ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
330ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to allocated packet or NULL if no resources
331ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
332ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
333911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsonBT_HDR* l2cu_build_header(tL2C_LCB* p_lcb, uint16_t len, uint8_t cmd,
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          uint8_t id) {
335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(L2CAP_CMD_BUF_SIZE);
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
3375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len =
340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      len + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in HCI header - handle + pkt boundary */
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                          << L2CAP_PKT_TYPE_SHIFT)));
347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_lcb->handle | l2cb.non_flushable_pbf);
3505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
3535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD);
357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len + L2CAP_CMD_OVERHEAD);
358cccf02fadb2dd4dceb22f2d58ed5840b0ef1860eChris Manton
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) {
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_BLE_SIGNALLING_CID);
361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, cmd);
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, id);
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, len);
3695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
374ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
375ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adj_id
376ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Checks for valid ID based on specified mask
378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and adjusts the id if invalid.
379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adj_id(tL2C_LCB* p_lcb, uint8_t adj_mask) {
384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id) {
385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->id++;
386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
391ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_cmd_reject
392ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "command reject" message
394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
397ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
398ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_cmd_reject(tL2C_LCB* p_lcb, uint16_t reason, uint8_t rem_id,
400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t p1, uint16_t p2) {
401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t param_len;
402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (reason == L2CAP_CMD_REJ_MTU_EXCEEDED)
407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 2;
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (reason == L2CAP_CMD_REJ_INVALID_CID)
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 4;
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    param_len = 0;
4125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_CMD_REJECT_LEN + param_len),
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_REJECT, rem_id);
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer cmd_rej");
417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
4245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 2) UINT16_TO_STREAM(p, p1);
4265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (param_len >= 4) UINT16_TO_STREAM(p, p2);
4285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
4305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
433ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
434ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_req
435ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
436ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection request" message
437ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
439ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
440ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
441ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_req(tL2C_CCB* p_ccb) {
443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
4515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_REQ_LEN,
453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_REQ, p_ccb->local_id);
454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
4615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
4665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_connect_rsp
471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response" message
473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_connect_rsp(tL2C_CCB* p_ccb, uint16_t result,
479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t status) {
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (result == L2CAP_CONN_PENDING) {
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if we already sent pending response */
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->flags & CCB_FLAG_SENT_PENDING)
486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return;
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->flags |= CCB_FLAG_SENT_PENDING;
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_CONN_RSP_LEN,
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONN_RSP, p_ccb->remote_id);
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_rsp");
495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
5005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, status);
5055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
5075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_connection
512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "connection response neg" message
514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. This function is called when there is no peer
515ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB (non-existant PSM or no resources).
516ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
517ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
518ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
519ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_connection(tL2C_LCB* p_lcb, uint16_t remote_cid,
521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            uint8_t rem_id, uint16_t result) {
522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
5245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_lcb, L2CAP_CONN_RSP_LEN, L2CAP_CMD_CONN_RSP, rem_id);
527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
5345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Status of 0      */
5395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
540911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
5425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_req
546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration request" message
548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
549ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
550ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
551ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
552ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present)
573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_REQ_LEN + cfg_len),
579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_REQ, p_ccb->local_id);
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->flags); /* Flags (continuation) */
590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
597911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
599911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
603911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.rtrans_tout);
620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mon_tout);
621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcs_present) {
625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCS);
626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCS_OPTION_LEN);
627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcs);
628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
6425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
645ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
646ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rsp
647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration response" message
649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t cfg_len = 0;
657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
658911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present)
661911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_MTU_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present)
663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FLUSH_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
664911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present)
665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_QOS_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present)
667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_FCR_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present)
669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len += L2CAP_CFG_EXT_FLOW_OPTION_LEN + L2CAP_CFG_OPTION_OVERHEAD;
670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb,
672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            (uint16_t)(L2CAP_CONFIG_RSP_LEN + cfg_len),
673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_CONFIG_RSP, p_ccb->remote_id);
674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for conn_req");
676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p,
684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                   p_cfg->flags); /* Flags (continuation) Must match request */
685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_cfg->result);
686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the options */
688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_MTU);
690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_MTU_OPTION_LEN);
691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->mtu);
692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FLUSH_TOUT);
695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FLUSH_OPTION_LEN);
696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->flush_to);
697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_QOS);
700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_QOS_OPTION_LEN);
701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.qos_flags);
702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->qos.service_type);
703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_rate);
704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.token_bucket_size);
705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.peak_bandwidth);
706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.latency);
707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->qos.delay_variation);
708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_FCR);
711911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_FCR_OPTION_LEN);
712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.mode);
713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.tx_win_sz);
714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->fcr.max_transmit);
715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.rtrans_tout);
716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->our_cfg.fcr.mon_tout);
717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->fcr.mps);
718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->ext_flow_spec_present) {
721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_TYPE_EXT_FLOW);
722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, L2CAP_CFG_EXT_FLOW_OPTION_LEN);
723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.id);
724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT8_TO_STREAM(p, p_cfg->ext_flow_spec.stype);
725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_cfg->ext_flow_spec.max_sdu_size);
726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.sdu_inter_time);
727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.access_latency);
728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT32_TO_STREAM(p, p_cfg->ext_flow_spec.flush_timeout);
729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_config_rej
737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "configuration reject" message
739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_config_rej(tL2C_CCB* p_ccb, uint8_t* p_data,
745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               uint16_t data_len, uint16_t rej_len) {
746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len, cfg_len, buf_space, len1;
747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t *p, *p_hci_len, *p_data_end;
748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t cfg_code;
7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_config_rej: data_len=%d, rej_len=%d",
751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    data_len, rej_len);
7528fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN;
755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len1 = 0xFFFF - len;
756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (rej_len > len1) {
757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CAP - cfg_rej pkt size exceeds buffer design max limit.");
759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7618fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf = (BT_HDR*)osi_malloc(len + rej_len);
763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset = L2CAP_SEND_CMD_OFFSET;
764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET;
7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Put in HCI header - handle + pkt boundary */
7675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) {
769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 << L2CAP_PKT_TYPE_SHIFT)));
771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
7725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, (p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT)));
776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Remember the HCI header length position, and save space for it */
779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_hci_len = p;
780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p += 2;
781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP packet header */
783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len);
784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_SIGNALLING_CID);
785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in L2CAP command header */
787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, L2CAP_CMD_CONFIG_RSP);
788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT8_TO_STREAM(p, p_ccb->remote_id);
789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CONFIG_RSP_LEN + rej_len);
791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Flags = 0 (no continuation) */
794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, L2CAP_CFG_UNKNOWN_OPTIONS);
795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  buf_space = rej_len;
797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, put the rejected options */
799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_data_end = p_data + data_len;
800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (p_data < p_data_end) {
801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_code = *p_data;
802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    cfg_len = *(p_data + 1);
803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    switch (cfg_code & 0x7F) {
805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* skip known options */
806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_MTU:
807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_FLUSH_TOUT:
808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      case L2CAP_CFG_TYPE_QOS:
809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* unknown options; copy into rsp if not hints */
813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      default:
814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* sanity check option length */
815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if ((cfg_code & 0x80) == 0) {
817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            } else {
822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_data = p_data_end; /* force loop exit */
824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            }
826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* bad length; force loop exit */
830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_data = p_data_end;
8325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
8345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  len = (uint16_t)(p - p_hci_len - 2);
838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p_hci_len, len);
8395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len = len + 4;
8415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("L2CAP - cfg_rej pkt hci_len=%d, l2cap_len=%d", len,
843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    (L2CAP_CMD_OVERHEAD + L2CAP_CONFIG_RSP_LEN + rej_len));
8448fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
849ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
850ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_req
851ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
852ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect request" message
853ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
854ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
855ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
856ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
857ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_req(tL2C_CCB* p_ccb) {
859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR *p_buf, *p_buf2;
860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
8615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb) || (p_ccb->p_lcb == NULL)) {
863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s L2CAP - ccb or lcb invalid", __func__);
864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
866bf955cb7e50e1047452e741effa504c8aefc8a4fvenkata Jagadeesh
867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
8705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
8725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_ccb->p_lcb, L2CAP_DISC_REQ_LEN,
874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_DISC_REQ, p_ccb->local_id);
875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_req");
877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
8825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
8855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Move all queued data packets to the LCB. In FCR mode, assume the higher
887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     layer checks that all buffers are sent before disconnecting.
888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) {
890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while ((p_buf2 = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q)) !=
891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           NULL) {
892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_set_acl_hci_header(p_buf2, p_ccb);
893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_check_send_pkts(p_ccb->p_lcb, p_ccb, p_buf2);
8945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
8985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
901ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
902ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_disc_rsp
903ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "disconnect response" message
905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
906ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This function is passed the parameters for the disconnect
908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  response instead of the CCB address, as it may be called
909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to send a disconnect response when there is no CCB.
910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
912ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_disc_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t local_cid, uint16_t remote_cid) {
916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_RSP_LEN, L2CAP_CMD_DISC_RSP,
920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            remote_id);
921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for disc_rsp");
923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, local_cid);
930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, remote_cid);
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_req
938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo request" message
940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer. Note that we do not currently allow
941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data in the echo request.
942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_req(tL2C_LCB* p_lcb, uint8_t* p_data,
947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
9505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ZERO_ID); /* check for wrap to '0' */
9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_REQ_LEN + data_len),
955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_REQ, p_lcb->id);
956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_req");
958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
9635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
9695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
972ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
973ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_echo_rsp
974ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
975ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "echo response" message
976ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
977ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
978ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
979ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
980ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_echo_rsp(tL2C_LCB* p_lcb, uint8_t id, uint8_t* p_data,
982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t data_len) {
983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
984911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t maxlen;
986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Filter out duplicate IDs or if available buffers are low (intruder
987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * checking) */
988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!id || id == p_lcb->cur_echo_id) {
989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Dump this request since it is illegal */
990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP ignoring duplicate echo request (%d)", id);
991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->cur_echo_id = id;
994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_data_size =
996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_data_size_classic();
997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t acl_packet_size =
998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      controller_get_interface()->get_acl_packet_size_classic();
999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Don't return data if it does not fit in ACL and L2CAP MTU */
1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen = (L2CAP_CMD_BUF_SIZE > acl_packet_size)
1001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               ? acl_data_size
1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               : (uint16_t)L2CAP_CMD_BUF_SIZE;
1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  maxlen -=
1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (uint16_t)(BT_HDR_SIZE + HCI_DATA_PREAMBLE_SIZE + L2CAP_PKT_OVERHEAD +
1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 L2CAP_CMD_OVERHEAD + L2CAP_ECHO_RSP_LEN);
1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len > maxlen) data_len = 0;
1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, (uint16_t)(L2CAP_ECHO_RSP_LEN + data_len),
1010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_ECHO_RSP, id);
1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for echo_rsp");
1013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
1018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (data_len) {
1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    ARRAY_TO_STREAM(p, p_data, data_len);
1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1028ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_req
1029ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info request" message
1031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_req(tL2C_LCB* p_lcb, uint16_t info_type) {
1036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
10385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* check for wrap and/or BRCM ID */
1040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
1041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
10425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, 2, L2CAP_CMD_INFO_REQ, p_lcb->id);
1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_req");
1046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_EVENT("l2cu_send_peer_info_req: type 0x%04x", info_type);
10505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1051911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
10535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
10555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->w4_info_rsp = true;
1057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_set_on_queue(p_lcb->info_resp_timer, L2CAP_WAIT_INFO_RSP_TIMEOUT_MS,
1058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     l2c_info_resp_timer_timeout, p_lcb,
1059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     btu_general_alarm_queue);
10605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
10625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_info_rsp
1067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send an L2CAP "info response" message
1069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
1070ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1071ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1072ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_info_rsp(tL2C_LCB* p_lcb, uint8_t remote_id,
1075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             uint16_t info_type) {
1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
1077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
1078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t len = L2CAP_INFO_RSP_LEN;
10795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_EXT_FLOW_SPEC |
1085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_FIXED_CHNLS | L2CAP_EXTFEA_EXT_WINDOW |
1086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
10875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_NO_CRC | L2CAP_EXTFEA_FIXED_CHNLS |
1092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
10935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_EXTENDED_FEATURES_ARRAY_SIZE;
1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_FIXED_CHNL_ARRAY_SIZE;
1098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    len += L2CAP_CONNLESS_MTU_INFO_SIZE;
1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, len, L2CAP_CMD_INFO_RSP, remote_id);
1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no buffer for info_rsp");
1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
1109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
11105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, info_type);
11125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1114911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.test_info_resp &
1116911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)))
11185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((info_type == L2CAP_EXTENDED_FEATURES_INFO_TYPE) &&
1120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (L2CAP_EXTFEA_SUPPORTED_MASK &
1121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (L2CAP_EXTFEA_ENH_RETRANS | L2CAP_EXTFEA_STREAM_MODE |
1122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_EXTFEA_UCD_RECEPTION)) != 0)
11235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  {
1125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_LE) {
1127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* optional data are not added for now */
1128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_BLE_EXTFEA_MASK);
1129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1130d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
1131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, l2cb.test_info_resp);
11325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
11335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
1134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p,
1135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       L2CAP_EXTFEA_SUPPORTED_MASK | L2CAP_EXTFEA_FIXED_CHNLS);
11365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT32_TO_STREAM(p, L2CAP_EXTFEA_SUPPORTED_MASK);
11385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
11405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
1142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memset(p, 0, L2CAP_FIXED_CHNL_ARRAY_SIZE);
11445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p[0] = L2CAP_FIXED_CHNL_SIG_BIT;
11465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (L2CAP_EXTFEA_SUPPORTED_MASK & L2CAP_EXTFEA_UCD_RECEPTION)
1148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p[0] |= L2CAP_FIXED_CHNL_CNCTLESS_BIT;
11495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
11515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      int xx;
1153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Skip fixed channels not used on BR/EDR-ACL link */
1156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((xx >= L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL) &&
1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (xx <= L2CAP_SMP_CID - L2CAP_FIRST_FIXED_CHNL))
1158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL)
1161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] |=
1162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8);
1163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
11645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (info_type == L2CAP_CONNLESS_MTU_INFO_TYPE) {
1167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_INFO_RESP_RESULT_SUCCESS);
1168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, L2CAP_UCD_MTU);
1169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
1171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, L2CAP_INFO_RESP_RESULT_NOT_SUPPORTED); /* 'not supported' */
1172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
11755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_enqueue_ccb
1180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      queue CCB by priority. The first CCB is highest priority and
1182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is served at first. The CCB is queued to an LLCB or an LCB.
1183ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1184ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
1185ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1186ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_enqueue_ccb(tL2C_CCB* p_ccb) {
1188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb1;
1189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
11905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
11945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL)) {
1196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_enqueue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x",
1198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb);
1199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_enqueue_ccb CID: 0x%04x  priority: %d",
1203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->ccb_priority);
12045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the queue is empty, we go at the front */
1206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_q->p_first_ccb) {
1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_q->p_last_ccb = p_ccb;
1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb1 = p_q->p_first_ccb;
1211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    while (p_ccb1 != NULL) {
1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Insert new ccb at the end of the same priority. Lower number, higher
1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * priority */
1215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->ccb_priority < p_ccb1->ccb_priority) {
1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Are we at the head of the queue ? */
1217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb1 == p_q->p_first_ccb)
1218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_q->p_first_ccb = p_ccb;
1219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else
1220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_ccb1->p_prev_ccb->p_next_ccb = p_ccb;
12215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_next_ccb = p_ccb1;
1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_prev_ccb = p_ccb1->p_prev_ccb;
1224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb1->p_prev_ccb = p_ccb;
1225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
1226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb1 = p_ccb1->p_next_ccb;
1229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
12305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we are lower then anyone in the list, we go at the end */
1232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb1) {
1233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* add new ccb at the end of the list */
1234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb->p_next_ccb = p_ccb;
12355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_next_ccb = NULL;
1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_prev_ccb = p_q->p_last_ccb;
1238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = p_ccb;
12395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Adding CCB into round robin service table of its LCB */
1244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if this is the first channel in this priority group */
1246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the first channel to this CCB */
1248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Set the next serving channel in this group to this CCB */
1250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Initialize quota of this priority group based on its priority */
1252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* increase number of channels in this group */
1256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb++;
1257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
12595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1262ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1263ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_dequeue_ccb
1264ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1265ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      dequeue CCB from a queue
1266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1268ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1269ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_dequeue_ccb(tL2C_CCB* p_ccb) {
1271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB_Q* p_q = NULL;
12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_dequeue_ccb  CID: 0x%04x", p_ccb->local_cid);
12745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find out which queue the channel is on
1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) p_q = &p_ccb->p_lcb->ccb_queue;
12785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_ccb->in_use) || (p_q == NULL) || (p_q->p_first_ccb == NULL)) {
1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_dequeue_ccb  CID: 0x%04x ERROR in_use: %u  p_lcb: 0x%08x  p_q: "
1282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "0x%08x  p_q->p_first_ccb: 0x%08x",
1283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->local_cid, p_ccb->in_use, p_ccb->p_lcb, p_q,
1284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_q ? p_q->p_first_ccb : 0);
1285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
1286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Removing CCB from round robin service table of its LCB */
1290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb != NULL) {
1291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* decrease number of channels in this priority group */
1292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb--;
1293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if it was the last channel in the priority group */
1295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb == 0) {
1296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the first channel of this group */
1300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb == p_ccb) {
1301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb =
1302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_next_ccb;
1303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* if it is the next serving channel of this group */
1305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb == p_ccb) {
1306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* simply, start serving from the first channel */
1307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb =
1308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb;
1309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
13135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == p_q->p_first_ccb) {
1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the first in a queue */
1316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_first_ccb = p_ccb->p_next_ccb;
13175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_q->p_first_ccb)
1319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_first_ccb->p_prev_ccb = NULL;
13205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
1321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_q->p_last_ccb = NULL;
1322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else if (p_ccb == p_q->p_last_ccb) {
1323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We are removing the last in a queue */
1324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb = p_ccb->p_prev_ccb;
1325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_q->p_last_ccb->p_next_ccb = NULL;
1326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* In the middle of a chain. */
1328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb->p_next_ccb = p_ccb->p_next_ccb;
1329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb->p_prev_ccb = p_ccb->p_prev_ccb;
1330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
13335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
1336ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1337ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_change_pri_ccb
1338ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1339ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description
1340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          -
1342ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1343ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_change_pri_ccb(tL2C_CCB* p_ccb, tL2CAP_CHNL_PRIORITY priority) {
1345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->ccb_priority != priority) {
1346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If CCB is not the only guy on the queue */
1347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->p_next_ccb != NULL) || (p_ccb->p_prev_ccb != NULL)) {
1348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("Update CCB list in logical link");
13495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Remove CCB from queue and re-queue it at new priority */
1351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_dequeue_ccb(p_ccb);
13525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_enqueue_ccb(p_ccb);
1355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
13565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
1357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If CCB is the only guy on the queue, no need to re-enqueue */
1359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* update only round robin service data */
1360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 0;
1361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = NULL;
1362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = NULL;
1363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ccb_priority = priority;
1365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_first_ccb = p_ccb;
1367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].p_serve_ccb = p_ccb;
1368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].quota =
1369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_ccb->ccb_priority);
1370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_lcb->rr_serv[p_ccb->ccb_priority].num_ccb = 1;
13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
1373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1377ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1378ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ccb
1379ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1380ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allocates a Channel Control Block and
1381ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  attaches it to a link control block. The local CID
1382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is also assigned.
1383ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1384ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
1385ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1387911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_allocate_ccb(tL2C_LCB* p_lcb, uint16_t cid) {
1388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_prev;
13905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x", cid);
13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) return (NULL);
13945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If a CID was passed in, use that, else take the first free one */
1396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0) {
1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.p_free_ccb_first;
1398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_prev = NULL;
14015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = &l2cb.ccb_pool[cid - L2CAP_BASE_APPL_CID];
14035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == l2cb.p_free_ccb_first)
1405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.p_free_ccb_first = p_ccb->p_next_ccb;
1406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
1407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_prev = l2cb.p_free_ccb_first; p_prev != NULL;
1408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           p_prev = p_prev->p_next_ccb) {
1409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_prev->p_next_ccb == p_ccb) {
1410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_prev->p_next_ccb = p_ccb->p_next_ccb;
14115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb == l2cb.p_free_ccb_last) l2cb.p_free_ccb_last = p_prev;
14135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
1415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
1416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_prev == NULL) {
1418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR(
1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "l2cu_allocate_ccb: could not find CCB for CID 0x%04x in the free "
1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            "list",
1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            cid);
1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_next_ccb = p_ccb->p_prev_ccb = NULL;
1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = true;
1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get a CID for the connection */
1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = L2CAP_BASE_APPL_CID + (uint16_t)(p_ccb - l2cb.ccb_pool);
1433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = NULL;
1436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->should_free_rcb = false;
1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set priority then insert ccb into LCB queue (if we have an LCB) */
1439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ccb_priority = L2CAP_CHNL_PRIORITY_LOW;
1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) l2cu_enqueue_ccb(p_ccb);
1442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* clear what peer wants to configure */
1444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_bits = 0;
1445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for configuration */
1447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->our_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->peer_cfg, 0, sizeof(tL2CAP_CFG_INFO));
1449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put in default values for local/peer configurations */
1451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.flush_to = p_ccb->peer_cfg.flush_to = L2CAP_DEFAULT_FLUSH_TO;
1452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.mtu = p_ccb->peer_cfg.mtu = L2CAP_DEFAULT_MTU;
1453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.service_type = p_ccb->peer_cfg.qos.service_type =
1454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_SERV_TYPE;
1455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_rate = p_ccb->peer_cfg.qos.token_rate =
1456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_TOKEN_RATE;
1457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.token_bucket_size = p_ccb->peer_cfg.qos.token_bucket_size =
1458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_BUCKET_SIZE;
1459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.peak_bandwidth = p_ccb->peer_cfg.qos.peak_bandwidth =
1460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_PEAK_BANDWIDTH;
1461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.latency = p_ccb->peer_cfg.qos.latency =
1462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_LATENCY;
1463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.qos.delay_variation = p_ccb->peer_cfg.qos.delay_variation =
1464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_DEFAULT_DELAY;
1465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->bypass_fcs = 0;
1467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memset(&p_ccb->ertm_info, 0, sizeof(tL2CAP_ERTM_INFO));
1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->peer_cfg_already_rejected = false;
1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcr_cfg_tries = L2CAP_MAX_FCR_CFG_TRIES;
1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.ack_timer);
1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.ack_timer = alarm_new("l2c_fcrb.ack_timer");
1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /*  CSP408639 Fix: When L2CAP send amp move channel request or receive
1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * L2CEVT_AMP_MOVE_REQ do following sequence. Send channel move
1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    * request -> Stop retrans/monitor timer -> Change channel state to
1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * CST_AMP_MOVING. */
1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->fcrb.mon_retrans_timer);
1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.mon_retrans_timer = alarm_new("l2c_fcrb.mon_retrans_timer");
1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.preferred_mode =
1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_BASIC_MODE; /* Default mode for channel is basic mode */
1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.allowed_modes =
1484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_FCR_CHAN_OPT_BASIC; /* Default mode for channel is basic mode */
1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
1487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->max_rx_mtu = L2CAP_MTU_SIZE;
1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_mps = L2CAP_FCR_TX_BUF_SIZE - 32;
1491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = fixed_queue_new(SIZE_MAX);
1493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.srej_rcv_hold_q = fixed_queue_new(SIZE_MAX);
1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.retrans_q = fixed_queue_new(SIZE_MAX);
1495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.waiting_for_ack_q = fixed_queue_new(SIZE_MAX);
1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->cong_sent = false;
1498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->buff_quota = 2; /* This gets set after config */
1499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If CCB was reserved Config_Done can already have some value */
1501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (cid == 0)
1502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->config_done = 0;
1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
1504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("l2cu_allocate_ccb: cid 0x%04x config_done:0x%x", cid,
1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_ccb->config_done);
1506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->chnl_state = CST_CLOSED;
1509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->flags = 0;
1510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
1511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->rx_data_rate = L2CAP_CHNL_DATA_RATE_LOW;
15125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
1514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
15155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
15165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = alarm_new("l2c.l2c_ccb_timer");
15195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_adjust_chnl_allocation();
15215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
15235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_start_post_bond_timer
1528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function starts the ACL Link inactivity timer after
1530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  dedicated bonding
1531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  This timer can be longer than the normal link inactivity
1532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  timer for some platforms.
1533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
15349ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns          bool  - true if idle timer started or disconnect initiated
15359ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                          false if there's one or more pending CCB's exist
1536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_start_post_bond_timer(uint16_t handle) {
1539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_handle(handle);
15405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) return (true);
15425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->is_bonding = false;
15445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Only start timer if no control blocks allocated */
1546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->ccb_queue.p_first_ccb != NULL) return (false);
15475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb->link_state == LST_CONNECTED) ||
1550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_CONNECTING) ||
1551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_lcb->link_state == LST_DISCONNECTING)) {
1552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    period_ms_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
155378bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov
1554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->idle_timeout == 0) {
1555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
1556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
1557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
15585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
1560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb, btu_general_alarm_queue);
1561911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
1562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (false);
15655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1568ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1569ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_ccb
1570ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1571ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function releases a Channel Control Block. The timer
15729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  is stopped, any attached buffers freed, and the CCB is
15739ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  removed from the link control block.
1574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1575ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1576ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1577ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_ccb(tL2C_CCB* p_ccb) {
1579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = p_ccb->p_lcb;
1580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = p_ccb->p_rcb;
15815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_release_ccb: cid 0x%04x  in_use: %u",
1583911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->local_cid, p_ccb->in_use);
15845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If already released, could be race condition */
1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb->in_use) return;
15875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    btm_sec_clr_service_by_psm(p_rcb->psm);
1590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1591ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->should_free_rcb) {
1593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_rcb);
1594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_rcb = NULL;
1595911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->should_free_rcb = false;
1596911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1597a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
1598911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_sec_clr_temp_auth_service(p_lcb->remote_bd_addr);
1599ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
1600911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Free the timer */
1601911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_free(p_ccb->l2c_ccb_timer);
1602911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->l2c_ccb_timer = NULL;
16035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fixed_queue_free(p_ccb->xmit_hold_q, osi_free);
1605911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->xmit_hold_q = NULL;
16065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_cleanup(p_ccb);
16085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Channel may not be assigned to any LCB if it was just pre-reserved */
1610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID)
16115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  || (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID)
16135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      )) {
1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_dequeue_ccb(p_ccb);
1616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Delink the CCB from the LCB */
1618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_lcb = NULL;
1619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Put the CCB back on the free pool */
1622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cb.p_free_ccb_first) {
1623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_first = p_ccb;
1624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = NULL;
1627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_next_ccb = NULL;
1629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->p_prev_ccb = l2cb.p_free_ccb_last;
1630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last->p_next_ccb = p_ccb;
1631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.p_free_ccb_last = p_ccb;
1632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Flag as not in use */
1635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->in_use = false;
1636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no channels on the connection, start idle timeout */
1638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_lcb) && p_lcb->in_use && (p_lcb->link_state == LST_CONNECTED)) {
1639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->ccb_queue.p_first_ccb) {
16407c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // Closing a security channel on LE device should not start connection
16417c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      // timeout
16427c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski      if (p_lcb->transport == BT_TRANSPORT_LE &&
16437c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski          p_ccb->local_cid == L2CAP_SMP_CID)
16447c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski        return;
16457c8bab231328956d3b7569280cb162be4e345422Jakub Pawlowski
1646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_no_dynamic_ccbs(p_lcb);
1647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1648911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Link is still active, adjust channel quotas. */
1649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_adjust_chnl_allocation();
16505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_remote_cid
1657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
1659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the remote CID.
1660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1661ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
1662ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1663ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1664911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_remote_cid(tL2C_LCB* p_lcb, uint16_t remote_cid) {
1665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
16665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If LCB is NULL, look through all active links */
1668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) {
1669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return NULL;
1670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
1672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->in_use) && (p_ccb->remote_cid == remote_cid)) return (p_ccb);
1673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
16775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1680ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1681ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_rcb
1682ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1683ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks for a free
1684ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1685ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1686ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1687ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1688ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1689911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_rcb(uint16_t psm) {
1690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
16925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
16975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
1698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
16995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
17015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17086721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1709ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_allocate_ble_rcb
1711ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks for a free
1713ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  one.
1714ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1715ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1716ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1717ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1718911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_allocate_ble_rcb(uint16_t psm) {
1719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_rcb->in_use) {
1724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->in_use = true;
1725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->psm = psm;
17266721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#if (L2CAP_UCD_INCLUDED == TRUE)
1727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb->ucd.state = L2C_UCD_STATE_UNUSED;
17286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar#endif
1729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_rcb);
17306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
1731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17326721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no free RCB found */
1734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
17356721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
17365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_release_rcb
1740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Mark an RCB as no longet in use
1742ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1743ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1744ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1745ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_release_rcb(tL2C_RCB* p_rcb) {
1747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->in_use = false;
1748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->psm = 0;
17495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1753ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_disconnect_chnl
1754ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1755ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Disconnect a channel. Typically, this is due to either
17569ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  receiving a bad configuration,  bad packet or max_retries
17579ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  expiring.
1758ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1759ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_disconnect_chnl(tL2C_CCB* p_ccb) {
1761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t local_cid = p_ccb->local_cid;
17625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
1764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2CA_DISCONNECT_IND_CB* p_disc_cb =
1765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->p_rcb->api.pL2CA_DisconnectInd_Cb;
17665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - disconnect_chnl CID: 0x%04x", local_cid);
17685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_send_peer_disc_req(p_ccb);
17705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_ccb(p_ccb);
17725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_disc_cb)(local_cid, false);
1774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* failure on the AMP channel, probably need to disconnect ACL */
1776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CAP - disconnect_chnl CID: 0x%04x Ignored", local_cid);
1777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
17795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1781ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1782ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_rcb_by_psm
1783ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1784ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the Registration Control Blocks to see if
1785ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1786ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1787ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the RCB or NULL if not found
1788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1790911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_rcb_by_psm(uint16_t psm) {
1791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.rcb_pool[0];
1792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
17935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
18005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
18015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
1803ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ble_rcb_by_psm
1805ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1806ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through the BLE Registration Control Blocks to see if
1807ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  anyone registered to handle the PSM in question
1808ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1809ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          Pointer to the BLE RCB or NULL if not found
1810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1811ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1812911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_RCB* l2cu_find_ble_rcb_by_psm(uint16_t psm) {
1813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = &l2cb.ble_rcb_pool[0];
1814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t xx;
18156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < BLE_MAX_L2CAP_CLIENTS; xx++, p_rcb++) {
1817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_rcb->in_use) && (p_rcb->psm == psm)) return (p_rcb);
1818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18196721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
1820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
1821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
18226721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
18235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1825ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1826ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_req
1827ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18289ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
18299ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  request" message. It extracts the configuration of interest
18309ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1831ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
18329ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  Note:  Negotiation of the FCR channel type is handled
18339ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                         internally, all others are passed to the upper layer.
1834ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1835ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          uint8_t - L2CAP_PEER_CFG_OK if passed to upper layer,
18369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_UNACCEPTABLE if automatically
18379ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      responded to because parameters are
18389ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      unnacceptable from a specification point
18399ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      of view.
18409ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                            L2CAP_PEER_CFG_DISCONNECT if no compatible channel
18419ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      modes between the two devices, and shall
18429ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      be closed.
1843ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1844ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_process_peer_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool mtu_ok = true;
1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool qos_type_ok = true;
1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool flush_to_ok = true;
1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool fcr_ok = true;
1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t fcr_status;
1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Ignore FCR parameters for basic mode */
1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_cfg->fcr_present) p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the MTU that our peer can receive */
1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->mtu_present) {
1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure MTU is at least the minimum */
1858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->mtu >= L2CAP_MIN_MTU) {
1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* In basic mode, limit the MTU to our buffer size */
1860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_cfg->fcr_present == false) && (p_cfg->mtu > L2CAP_MTU_SIZE))
1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->mtu = L2CAP_MTU_SIZE;
1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Save the accepted value in case of renegotiation */
1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu = p_cfg->mtu;
1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.mtu_present = true;
1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
1867911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal MTU value */
1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->mtu = L2CAP_MIN_MTU;
1870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      mtu_ok = false;
1871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload mtu from a previously accepted config request */
1874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.mtu_present) {
1875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = true;
1876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu = p_ccb->peer_cfg.mtu;
1877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify that the flush timeout is a valid value (0 is illegal) */
1880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
1881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_cfg->flush_to) {
1882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to = 0xFFFF; /* Infinite retransmissions (spec default) */
1883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      flush_to_ok = false;
1884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Save the accepted value in case of renegotiation */
1885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    {
1886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to_present = true;
1887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.flush_to = p_cfg->flush_to;
1888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
1889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload flush_to from a previously accepted config request */
1892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.flush_to_present) {
1893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to_present = true;
1894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->flush_to = p_ccb->peer_cfg.flush_to;
1895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings the the peer is using */
1898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
1899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Make sure service type is not a reserved value; otherwise let upper
1900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       layer decide if acceptable
1901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    */
1902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->qos.service_type <= GUARANTEED) {
1903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos = p_cfg->qos;
1904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.qos_present = true;
1905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
1906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else /* Illegal service type value */
19075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    {
1908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->qos.service_type = BEST_EFFORT;
1909911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      qos_type_ok = false;
19105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Reload QOS from a previously accepted config request */
1913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_ccb->peer_cfg.qos_present) {
1914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = true;
1915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos = p_ccb->peer_cfg.qos;
1916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_status = l2c_fcr_process_peer_cfg_req(p_ccb, p_cfg);
1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fcr_status == L2CAP_PEER_CFG_DISCONNECT) {
1920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Notify caller to disconnect the channel (incompatible modes) */
1921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_FAILED_NO_REASON;
1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->mtu_present = p_cfg->qos_present = p_cfg->flush_to_present = 0;
19235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_DISCONNECT);
1925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  fcr_ok = (fcr_status == L2CAP_PEER_CFG_OK);
19285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return any unacceptable parameters */
1930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (mtu_ok && flush_to_ok && qos_type_ok && fcr_ok) {
1931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_adjust_out_mps(p_ccb);
1932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_OK);
1933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
19355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (mtu_ok) p_cfg->mtu_present = false;
1937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (flush_to_ok) p_cfg->flush_to_present = false;
1938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (qos_type_ok) p_cfg->qos_present = false;
1939911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fcr_ok) p_cfg->fcr_present = false;
19405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1941911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_PEER_CFG_UNACCEPTABLE);
1942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_peer_cfg_rsp
1948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
19499ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when the peer sends us a "config
19509ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
19519ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
1952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1953ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1954ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1955ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_peer_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we wanted QoS and the peer sends us a positive response with QoS, use
1958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * his values */
1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->our_cfg.qos_present))
1960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
19615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Save the retransmission and monitor timeout values */
1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_ERTM_MODE) {
1965911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.rtrans_tout = p_cfg->fcr.rtrans_tout;
1966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->peer_cfg.fcr.mon_tout = p_cfg->fcr.mon_tout;
1967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
19685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Calculate the max number of packets for which we can delay sending an ack
1970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
1971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.tx_win_sz < p_ccb->our_cfg.fcr.tx_win_sz)
1972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
1973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
1974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->fcrb.max_held_acks = p_ccb->our_cfg.fcr.tx_win_sz / 3;
19755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
1977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_process_peer_cfg_rsp(): peer tx_win_sz: %d, our tx_win_sz: %d, "
1978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "max_held_acks: %d",
1979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.tx_win_sz, p_ccb->our_cfg.fcr.tx_win_sz,
1980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->fcrb.max_held_acks);
1981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1985ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_req
1987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1988ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when we send a "config request"
1989ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  message. It extracts the configuration of interest and saves
1990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  it in the CCB.
1991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1992ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
1993ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1994ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_req(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
1996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t hci_flush_to;
1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the QOS settings we are using for transmit */
2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->qos_present) {
2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos_present = true;
2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.qos = p_cfg->qos;
2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->fcr_present) {
2006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Override FCR options if attempting streaming or basic */
2007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)
2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      memset(&p_cfg->fcr, 0, sizeof(tL2CAP_FCR_OPTS));
2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else {
2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On BR/EDR, timer values are zero in config request */
2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* On class 2 AMP, timer value in config request shall be non-0 processing
2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * time */
2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*                 timer value in config response shall be greater than
2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * received processing time */
2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcr.mon_tout = p_cfg->fcr.rtrans_tout = 0;
2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcr.mode == L2CAP_FCR_STREAM_MODE)
2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_cfg->fcr.max_transmit = p_cfg->fcr.tx_win_sz = 0;
2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the threshold to send acks (may be updated in the cfg response) */
2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_cfg->fcr.tx_win_sz / 3;
2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Include FCS option only if peer can handle it */
2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->peer_ext_fea & L2CAP_EXTFEA_NO_CRC) {
2026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* FCS check can be bypassed if peer also desires to bypass */
2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->fcs_present && p_cfg->fcs == L2CAP_CFG_FCS_BYPASS)
2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->bypass_fcs |= L2CAP_CFG_FCS_OUR;
2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else
2030911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcs_present = false;
2031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE;
2033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2034911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2035911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr.mode = p_cfg->fcr.mode;
2036911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg.fcr_present = p_cfg->fcr_present;
2037911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check the flush timeout. If it is lower than the current one used */
2039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* then we need to adjust the flush timeout sent to the controller   */
2040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_cfg->flush_to_present) {
2041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_cfg->flush_to == 0) ||
2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_cfg->flush_to == L2CAP_NO_AUTOMATIC_FLUSH)) {
2043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* don't send invalid flush timeout */
2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* SPEC: The sender of the Request shall specify its flush timeout value
2045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
2046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*       if it differs from the default value of 0xFFFF */
2047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->flush_to_present = false;
2048911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->our_cfg.flush_to = p_cfg->flush_to;
2050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb = p_ccb->p_lcb;
20515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_cfg->flush_to < p_lcb->link_flush_tout) {
2053911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_flush_tout = p_cfg->flush_to;
20545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If the timeout is within range of HCI, set the flush timeout */
2056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_cfg->flush_to <= ((HCI_MAX_AUTO_FLUSH_TOUT * 5) / 8)) {
2057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Convert flush timeout to 0.625 ms units, with round */
2058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          hci_flush_to = ((p_cfg->flush_to * 8) + 3) / 5;
2059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to);
20605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
20625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
20645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_our_cfg_rsp
2069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
20709ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      This function is called when we send the peer a "config
20719ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  response" message. It extracts the configuration of interest
20729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  and saves it in the CCB.
2073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2074ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2075ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2076ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_our_cfg_rsp(tL2C_CCB* p_ccb, tL2CAP_CFG_INFO* p_cfg) {
2078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If peer wants QoS, we are allowed to change the values in a positive
2079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * response */
2080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->qos_present) && (p_ccb->peer_cfg.qos_present))
2081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_cfg.qos = p_cfg->qos;
2082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->qos_present = false;
20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_adj_our_rsp_options(p_ccb, p_cfg);
20865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_device_reset
2091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2092ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when reset of the device is
2093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  completed.  For all active connection simulate HCI_DISC
2094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2095ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_device_reset(void) {
2099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
21015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle != HCI_INVALID_HANDLE)) {
2104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_link_hci_disc_comp(p_lcb->handle, (uint8_t)-1);
21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.is_ble_connecting = false;
21085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn
2113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport) {
212096fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
212196fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  return l2cu_create_conn(p_lcb, transport, phy);
212296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski}
212396fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski
212496fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowskibool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
212596fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski                      uint8_t initiating_phys) {
2126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
2128d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool is_sco_active;
21305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
21315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_DEVICE_TYPE dev_type;
2133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBLE_ADDR_TYPE addr_type;
21340fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
21360fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (transport == BT_TRANSPORT_LE) {
2138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!controller_get_interface()->supports_ble()) return false;
21390fc412c934cb930d5f5374ed53826c3bb01c25baAndre Eisenbach
2140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->ble_addr_type = addr_type;
2141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->transport = BT_TRANSPORT_LE;
214296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski    p_lcb->initiating_phys = initiating_phys;
21435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (l2cble_create_conn(p_lcb));
2145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If there is a connection where we perform as a slave, try to switch roles
2148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     for this connection */
2149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0, p_lcb_cur = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       xx++, p_lcb_cur++) {
2151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb_cur == p_lcb) continue;
21525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
2154d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (BTM_SCO_INCLUDED == TRUE)
2155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* The LMP_switch_req shall be sent only if the ACL logical transport
2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is in active mode, when encryption is disabled, and all synchronous
2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      logical transports on the same physical link are disabled." */
21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Check if there is any SCO Active on this BD Address */
2160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      is_sco_active = btm_is_sco_active_by_bdaddr(p_lcb_cur->remote_bd_addr);
21615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_API(
2163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "l2cu_create_conn - btm_is_sco_active_by_bdaddr() is_sco_active = %s",
2164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (is_sco_active == true) ? "true" : "false");
21655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (is_sco_active == true)
2167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        continue; /* No Master Slave switch not allowed when SCO Active */
21685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
2170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
2171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* mark this lcb waiting for switch to be completed and
2172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson           start switch on the other one */
2173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_state = LST_CONNECTING_WAIT_SWITCH;
2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_role = HCI_ROLE_MASTER;
2175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (BTM_SwitchRole(p_lcb_cur->remote_bd_addr, HCI_ROLE_MASTER, NULL) ==
2177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            BTM_CMD_STARTED) {
2178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          alarm_set_on_queue(
2179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_lcb->l2c_lcb_timer, L2CAP_LINK_ROLE_SWITCH_TIMEOUT_MS,
2180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
2181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (true);
21825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
21845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
21885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cu_create_conn_after_switch(p_lcb));
21905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_num_hi_priority
2195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Gets the number of high priority channels.
2197ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns
2199ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2200ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t l2cu_get_num_hi_priority(void) {
2202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi = 0;
2203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
2204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
22055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
2207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      no_hi++;
22095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return no_hi;
22125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
22135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2216ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_create_conn_after_switch
2217ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2218ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function initiates an acl connection via HCI
2219ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  If switch required to create connection it is already done.
2220ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2221ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if successful, false if get buffer fails.
2222ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
22245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2225911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb) {
2226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_INQ_INFO* p_inq_info;
2228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_rep_mode;
2229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t page_scan_mode;
2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t clock_offset;
2231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p_features;
2232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t num_acl = BTM_GetNumAclLinks();
2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(p_lcb->remote_bd_addr);
2234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t no_hi_prio_chs = l2cu_get_num_hi_priority();
22355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_features = BTM_ReadLocalFeatures();
22375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_create_conn_after_switch :%d num_acl:%d no_hi: %d is_bonding:%d",
2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.disallow_switch, num_acl, no_hi_prio_chs, p_lcb->is_bonding);
2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* FW team says that we can participant in 4 piconets
2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * typically 3 piconet + 1 for scanning.
2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * We can enhance the code to count the number of piconets later. */
2244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((!l2cb.disallow_switch && (num_acl < 3)) ||
2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       (p_lcb->is_bonding && (no_hi_prio_chs == 0))) &&
2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      HCI_SWITCH_SUPPORTED(p_features))
2247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_ALLOW_SWITCH;
2248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    allow_switch = HCI_CR_CONN_NOT_ALLOW_SWITCH;
22505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTING;
22525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check with the BT manager if details about remote device are known */
2254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_inq_info = BTM_InqDbRead(p_lcb->remote_bd_addr);
2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_inq_info != NULL) {
2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = p_inq_info->results.page_scan_rep_mode;
2257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = p_inq_info->results.page_scan_mode;
2258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (uint16_t)(p_inq_info->results.clock_offset);
2259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No info known. Use default settings */
2261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_rep_mode = HCI_PAGE_SCAN_REP_MODE_R1;
2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    page_scan_mode = HCI_MANDATARY_PAGE_SCAN_MODE;
22635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    clock_offset = (p_dev_rec) ? p_dev_rec->clock_offset : 0;
2265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2267b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski  btsnd_hcic_create_conn(
2268b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski      p_lcb->remote_bd_addr, (HCI_PKT_TYPES_MASK_DM1 | HCI_PKT_TYPES_MASK_DH1 |
2269b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski                              HCI_PKT_TYPES_MASK_DM3 | HCI_PKT_TYPES_MASK_DH3 |
2270b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski                              HCI_PKT_TYPES_MASK_DM5 | HCI_PKT_TYPES_MASK_DH5),
2271b8a477e9ac51898b05cb328eda897d95f1ef3d02Jakub Pawlowski      page_scan_rep_mode, page_scan_mode, clock_offset, allow_switch);
22725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  btm_acl_update_busy_level(BTM_BLI_PAGE_EVT);
22745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_set_on_queue(p_lcb->l2c_lcb_timer, L2CAP_LINK_CONNECT_TIMEOUT_MS,
2276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     l2c_lcb_timer_timeout, p_lcb, btu_general_alarm_queue);
2277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
2279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson}
22805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
22815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_state
2284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
2286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  LCB state.
2287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to first matched LCB, or NULL if no match
2289ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2291911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state) {
2292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
22945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->link_state == state)) {
2297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
22985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
23005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
2302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
23035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2306ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2307ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_lcb_disconnecting
2308ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2309ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      On each active lcb, check if the lcb is in disconnecting
2310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  state, or if there are no ccb's on the lcb (implying
23115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    idle timeout is running), or if last ccb on the link
23125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project                    is in disconnecting state.
2313ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2314ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if any of above conditions met, false otherwise
2315ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2316ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_lcb_disconnecting(void) {
2318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t i;
2321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool status = false;
23225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = &l2cb.lcb_pool[0];
23245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
2326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->in_use) {
2327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* no ccbs on lcb, or lcb is in disconnecting state */
2328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((!p_lcb->ccb_queue.p_first_ccb) ||
2329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb->link_state == LST_DISCONNECTING)) {
2330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        status = true;
2331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
2332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* only one ccb left on lcb */
2334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else if (p_lcb->ccb_queue.p_first_ccb == p_lcb->ccb_queue.p_last_ccb) {
2335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb = p_lcb->ccb_queue.p_first_ccb;
2336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->in_use) &&
2338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
2339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson             (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
2340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          status = true;
2341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          break;
23425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
23445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2345911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return status;
23475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
23485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
23495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_priority
2352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the transmission priority for a channel.
2354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  (For initial implementation only two values are valid.
2355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
2356ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2357ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
2358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
23605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2361c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskibool l2cu_set_acl_priority(const bt_bdaddr_t& bd_addr, uint8_t priority,
2362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           bool reset_after_rs) {
2363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* pp;
2365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t command[HCI_BRCM_ACL_PRIORITY_PARAM_SIZE];
2366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t vs_param;
23675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  APPL_TRACE_EVENT("SET ACL PRIORITY %d", priority);
23695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the link control block for the acl channel */
2371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
2372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
2373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_SetAclPriority");
2374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
2375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
23765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (BTM_IS_BRCM_CONTROLLER()) {
2378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Called from above L2CAP through API; send VSC if changed */
2379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((!reset_after_rs && (priority != p_lcb->acl_priority)) ||
2380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* Called because of a master/slave role switch; if high resend VSC */
2381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (reset_after_rs && p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)) {
2382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      pp = command;
23835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      vs_param = (priority == L2CAP_PRIORITY_HIGH) ? HCI_BRCM_ACL_PRIORITY_HIGH
2385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                   : HCI_BRCM_ACL_PRIORITY_LOW;
23865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(pp, p_lcb->handle);
2388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT8_TO_STREAM(pp, vs_param);
23895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BTM_VendorSpecificCommand(HCI_BRCM_SET_ACL_PRIORITY,
2391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                HCI_BRCM_ACL_PRIORITY_PARAM_SIZE, command,
2392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                NULL);
23935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Adjust lmp buffer allocation for this channel if priority changed */
2395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->acl_priority != priority) {
2396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->acl_priority = priority;
2397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_link_adjust_allocation();
2398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
23995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
24025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
24055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
2406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_non_flushable_pbf
2408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      set L2CAP_PKT_START_NON_FLUSHABLE if controller supoorts
2410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2412ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_non_flushable_pbf(bool is_supported) {
2415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (is_supported)
2416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf =
2417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_PKT_START_NON_FLUSHABLE << L2CAP_PKT_TYPE_SHIFT);
2418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
2419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.non_flushable_pbf = (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT);
24205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
24225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2424ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2425ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_resubmit_pending_sec_req
2426ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2427ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function is called when required security procedures
2428ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  are completed and any pending requests can be re-submitted.
2429ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2430ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2431ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2432ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2433c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskivoid l2cu_resubmit_pending_sec_req(const bt_bdaddr_t* p_bda) {
2434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_next_ccb;
2437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
24385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_resubmit_pending_sec_req  p_bda: 0x%08x", p_bda);
24405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we are called with a BDA, only resubmit for that BDA */
2442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_bda) {
2443c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    p_lcb = l2cu_find_lcb_by_bd_addr(*p_bda, BT_TRANSPORT_BR_EDR);
2444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If we don't have one, this is an error */
2446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb) {
2447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* For all channels, send the event through their FSMs */
2448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_next_ccb = p_ccb->p_next_ccb;
2450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
2451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
2453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("l2cu_resubmit_pending_sec_req - unknown BD_ADDR");
24545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No BDA pasesed in, so check all links */
2457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0, p_lcb = &l2cb.lcb_pool[0]; xx < MAX_L2CAP_LINKS;
2458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         xx++, p_lcb++) {
2459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->in_use) {
2460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* For all channels, send the event through their FSMs */
2461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_next_ccb) {
2462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_next_ccb = p_ccb->p_next_ccb;
2463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2c_csm_execute(p_ccb, L2CEVT_SEC_RE_SEND_CMD, NULL);
24645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2465911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
24665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
24685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
24695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2470d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_CONFORMANCE_TESTING == TRUE)
24715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_info_rsp_mask
2474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function allows the script wrapper to change the
2476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  info resp mask for conformance testing.
2477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2478ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB, or NULL if none
2479ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2480ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_info_rsp_mask(uint32_t mask) { l2cb.test_info_resp = mask; }
2482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif /* L2CAP_CONFORMANCE_TESTING */
24835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
24845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2485ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2486ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_adjust_out_mps
2487ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2488ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets our MPS based on current controller capabilities
2489ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2490ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2491ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2492ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_adjust_out_mps(tL2C_CCB* p_ccb) {
2494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t packet_size;
2495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* on the tx side MTU is selected based on packet size of the controller */
2497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  packet_size = btm_get_max_packet_size(p_ccb->p_lcb->remote_bd_addr);
2498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (packet_size <= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN)) {
2501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* something is very wrong */
2502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
2503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps bad packet size: %u  will use MPS: %u",
2504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        packet_size, p_ccb->peer_cfg.fcr.mps);
2505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
2506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet_size -= (L2CAP_PKT_OVERHEAD + L2CAP_FCR_OVERHEAD +
2508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    L2CAP_SDU_LEN_OVERHEAD + L2CAP_FCS_LEN);
2509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* We try to negotiate MTU that each packet can be split into whole
2511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    number of max packets.  For example if link is 1.2 max packet size is 339
2512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    bytes.
2513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    At first calculate how many whole packets it is.  MAX L2CAP is 1691 + 4
2514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    overhead.
2515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1695, that will be 5 Dh5 packets.  Now maximum L2CAP packet is
2516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    5 * 339 = 1695. Minus 4 bytes L2CAP header 1691.
2517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    For EDR 2.0 packet size is 1027.  So we better send RFCOMM packet as 1 3DH5
2519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    packet
2520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    1 * 1027 = 1027.  Minus 4 bytes L2CAP header 1023.  */
2521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mps >= packet_size)
2522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps / packet_size * packet_size;
25235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    else
2524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->tx_mps = p_ccb->peer_cfg.fcr.mps;
25255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_adjust_out_mps use %d   Based on peer_cfg.fcr.mps: %u  "
2528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "packet_size: %u",
2529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->tx_mps, p_ccb->peer_cfg.fcr.mps, packet_size);
2530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2534ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2535ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_initialize_fixed_ccb
2536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Initialize a fixed channel's CCB
2538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true or false
2540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_initialize_fixed_ccb(tL2C_LCB* p_lcb, uint16_t fixed_cid,
2543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               tL2CAP_FCR_OPTS* p_fcr) {
25445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2546911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we already have a CCB, then simply return */
2548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
2549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_ccb != NULL) && p_ccb->in_use) {
2550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /*
2551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * NOTE: The "in_use" check is needed to ignore leftover entries
2552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * that have been already released by l2cu_release_ccb().
2553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     */
2554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (true);
2555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_allocate_ccb(NULL, 0);
2558911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (false);
25595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2560911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  alarm_cancel(p_lcb->l2c_lcb_timer);
2561ead3cde4bac0c3e32cd31f149093f004eef8ceebGanesh Ganapathi Batta
2562911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set CID for the connection */
2563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_cid = fixed_cid;
2564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->remote_cid = fixed_cid;
25655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = false;
25675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2568911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_fcr) {
2569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Set the FCR parameters. For now, we will use default pools */
2570911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->our_cfg.fcr = p_ccb->peer_cfg.fcr = *p_fcr;
25715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
2573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
2574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
2575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
25765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.max_held_acks = p_fcr->tx_win_sz / 3;
2578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
25795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Link ccb to lcb and lcb to ccb */
2581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = p_ccb;
2582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb = p_lcb;
25835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* There is no configuration, so if the link is up, the channel is up */
2585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) p_ccb->chnl_state = CST_OPEN;
25865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the default idle timeout value to use */
2588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fixed_chnl_idle_tout =
2589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].default_idle_tout;
25905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
2591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
25925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
25935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2595ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2596ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_no_dynamic_ccbs
2597ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
25989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Handles the case when there are no more dynamic CCBs. If
25999ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  there are any fixed CCBs, start the longest of the fixed CCB
26009ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  timeouts, otherwise start the default link idle timeout or
26019ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  disconnect.
2602ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2603ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2604ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2605ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2606911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
2607911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBTM_STATUS rc;
2608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  period_ms_t timeout_ms = p_lcb->idle_timeout * 1000;
2609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool start_timeout = true;
26105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
2612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
26135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
2616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
2617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
26185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
26215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the link is pairing, do not mess with the timeouts */
2623911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->is_bonding) return;
2624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (timeout_ms == 0) {
2626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG(
2627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_no_dynamic_ccbs() IDLE timer 0, disconnecting link");
2628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2630911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (rc == BTM_CMD_STARTED) {
2631911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2632911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2633911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
2634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (rc == BTM_SUCCESS) {
2635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* BTM SEC will make sure that link is release (probably after pairing is
2637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * done) */
2638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      start_timeout = false;
2640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (p_lcb->is_bonding) {
2641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
2642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_process_fixed_disc_cback(p_lcb);
2643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->link_state = LST_DISCONNECTING;
2644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = L2CAP_LINK_DISCONNECT_TIMEOUT_MS;
264578bcff79e1b1f0efce436b33bdd6da88745bfc8aPavlin Radoslavov    } else {
2646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* probably no buffer to send disconnect */
2647911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      timeout_ms = BT_1SEC_TIMEOUT_MS;
26485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2649911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2650911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2651911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (start_timeout) {
2652911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("%s starting IDLE timeout: %d ms", __func__, timeout_ms);
2653911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_set_on_queue(p_lcb->l2c_lcb_timer, timeout_ms, l2c_lcb_timer_timeout,
2654911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb, btu_general_alarm_queue);
2655911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    alarm_cancel(p_lcb->l2c_lcb_timer);
2657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
26585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
26595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
26605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
26615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2662ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2663ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_chnl_resp
2664ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2665ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      handle a fixed channel response (or lack thereof)
2666ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  if the link failed, or a fixed channel response was
2667ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  not received, the bitfield is all zeros.
2668ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2669ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2670911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_chnl_resp(tL2C_LCB* p_lcb) {
2671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_BR_EDR) {
2672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* ignore all not assigned BR/EDR channels */
2673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] &=
2674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_FIXED_CHNL_SIG_BIT | L2CAP_FIXED_CHNL_CNCTLESS_BIT |
2675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FIXED_CHNL_SMP_BR_BIT);
2676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else
2677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
2678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Tell all registered fixed channels about the connection */
2680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* skip sending LE fix channel callbacks on BR/EDR links */
2682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
2683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
2684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID)
2685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
2686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
2687911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] &
2688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
2689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx])
2690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
2691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
2692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->remote_bd_addr, true, 0,
2693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                 p_lcb->transport);
2694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
2695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->p_fixed_ccbs[xx]) {
2700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
2701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[xx] = NULL;
27025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
27045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
27085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27098fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta/*******************************************************************************
2710ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2711ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_process_fixed_disc_cback
2712ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
27139ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      send l2cap fixed channel disconnection callback to the
27149ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  application
2715ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2716ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2717ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2718ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_process_fixed_disc_cback(tL2C_LCB* p_lcb) {
27208fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#if (L2CAP_NUM_FIXED_CHNLS > 0)
27218fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
2722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Select peer channels mask to use depending on transport */
2723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t peer_channel_mask = p_lcb->peer_chnl_mask[0];
2724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // For LE, reset the stored peer channel mask
2726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->transport == BT_TRANSPORT_LE) p_lcb->peer_chnl_mask[0] = 0;
2727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
2729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->p_fixed_ccbs[xx]) {
2730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->p_fixed_ccbs[xx] != p_lcb->p_pending_ccb) {
2731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        tL2C_CCB* p_l2c_chnl_ctrl_block;
2732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_l2c_chnl_ctrl_block = p_lcb->p_fixed_ccbs[xx];
2733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->p_fixed_ccbs[xx] = NULL;
2734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_release_ccb(p_l2c_chnl_ctrl_block);
2735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->disc_reason, p_lcb->transport);
2738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if ((peer_channel_mask & (1 << (xx + L2CAP_FIRST_FIXED_CHNL))) &&
2740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL))
2741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
2742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
2743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->disc_reason, p_lcb->transport);
2744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27458fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta#endif
27468fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta}
27478fe58875ce67c6e1099e7ba2339dcd2b979491b0Ganesh Ganapathi Batta
27485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2749ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2750ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_req
2751ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2752ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update request message
2753ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2754ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2755ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2756ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2757ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_req(tL2C_LCB* p_lcb, uint16_t min_int,
2759911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t max_int, uint16_t latency,
2760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t timeout) {
2761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
27635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->id++;
2766911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_ID);
27675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_REQ_LEN,
2769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_REQ, p_lcb->id);
2770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_req - no buffer");
2772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2773911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
27745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
27775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, min_int);
2779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, max_int);
2780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, latency);
2781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, timeout);
27825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
27845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
27855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
27865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2787ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2788ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_par_rsp
2789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2790ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE parameter update response message
2791ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  to the peer.
2792ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2793ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2794ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2795ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_par_rsp(tL2C_LCB* p_lcb, uint16_t reason,
2797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint8_t rem_id) {
2798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
28005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_UPD_RSP_LEN,
2802911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_UPDATE_RSP, rem_id);
2803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_par_rsp - no buffer");
2805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2811911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, reason);
28125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2813911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
28155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
28166721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2817ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2818ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28209ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to establish LE connection
28219ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2823ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2824ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2825ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_req(tL2C_CCB* p_ccb) {
2827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mtu;
2831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t mps;
2832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t initial_credit;
28336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
28366721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
28406721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
28426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ_LEN,
2844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ, p_lcb->id);
2845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28496721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28526721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mtu = p_ccb->local_conn_cfg.mtu;
2854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  mps = p_ccb->local_conn_cfg.mps;
2855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  initial_credit = p_ccb->local_conn_cfg.credits;
28566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG(
2858911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "l2cu_send_peer_ble_credit_based_conn_req PSM:0x%04x local_cid:%d\
2859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                mtu:%d mps:%d initial_credit:%d",
2860911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->p_rcb->real_psm, p_ccb->local_cid, mtu, mps, initial_credit);
28616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->p_rcb->real_psm);
2863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mtu);
2865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, mps);
2866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, initial_credit);
28676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
28696721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
28706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
28716721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2872ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2873ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_reject_ble_connection
2874ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
28759ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
28769ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called for non-success
28779ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  cases.
2878ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2879ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2880ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2881ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_reject_ble_connection(tL2C_LCB* p_lcb, uint8_t rem_id,
2883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                uint16_t result) {
2884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
28866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, rem_id);
2889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_reject_ble_connection - no buffer");
2891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
28936721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
28966721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* Local CID of 0   */
2898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MTU */
2899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* MPS */
2900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, 0); /* initial credit */
2901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
29026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
29046721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29056721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_res
2909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
29109ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send an L2CAP "Credit based connection res"
29119ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  message to the peer. This function is called in case of
29129ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  success.
2913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2914ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2915ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2916ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_conn_res(tL2C_CCB* p_ccb,
2918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                              uint16_t result) {
2919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
29216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("l2cu_send_peer_ble_credit_based_conn_res");
2923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf =
2924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cu_build_header(p_ccb->p_lcb, L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES_LEN,
2925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES, p_ccb->remote_id);
2926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_res - no buffer");
2928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29336721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2934911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);              /* Local CID */
2935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mtu);     /* MTU */
2936911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.mps);     /* MPS */
2937911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_conn_cfg.credits); /* initial credit */
2938911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, result);
29396721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2940911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_ccb->p_lcb, NULL, p_buf);
29416721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29426721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29436721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2945ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_flow_control_credit
2946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Build and send a BLE packet to give credits to peer device
2948ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  for LE connection oriented L2CAP channel.
2949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2953911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_flow_control_credit(tL2C_CCB* p_ccb,
2954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                            uint16_t credit_value) {
2955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
29586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
2960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
29616721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
2963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
2964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
29656721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2966911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
29676721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_CMD_BLE_FLOW_CTRL_CREDIT_LEN,
2969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            L2CAP_CMD_BLE_FLOW_CTRL_CREDIT, p_lcb->id);
2970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
2971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("l2cu_send_peer_ble_credit_based_conn_req - no buffer");
2972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
2973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
29746721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
2976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
29776721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
2979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, credit_value);
29806721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
2981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
29826721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
29836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
29846721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
2985ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_send_peer_ble_credit_based_conn_req
2987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
29889ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Build and send a BLE packet to disconnect LE connection
29899ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  oriented L2CAP channel.
2990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
2992ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2993ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_send_peer_ble_credit_based_disconn_req(tL2C_CCB* p_ccb) {
2995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
2996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
2997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
2998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("%s", __func__);
29996721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_ccb) return;
3001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = p_ccb->p_lcb;
30026721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Create an identifier for this packet */
3004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_lcb->id++;
3005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_ccb->p_lcb, L2CAP_ADJ_ID);
30066721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->local_id = p_ccb->p_lcb->id;
3008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf = l2cu_build_header(p_lcb, L2CAP_DISC_REQ_LEN, L2CAP_CMD_DISC_REQ,
3009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                            p_lcb->id);
3010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_buf == NULL) {
3011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
3012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "l2cu_send_peer_ble_credit_based_disconn_req - no buffer");
3013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
3014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30156721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + L2CAP_SEND_CMD_OFFSET + HCI_DATA_PREAMBLE_SIZE +
3017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_PKT_OVERHEAD + L2CAP_CMD_OVERHEAD;
30186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->remote_cid);
3020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  UINT16_TO_STREAM(p, p_ccb->local_cid);
30216721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, p_buf);
30236721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
30245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3026ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Functions used by both Full and Light Stack
3027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
30285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3030ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3031ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_lcb_by_handle
3032ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active LCBs for a match based on the
3034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  HCI handle.
3035ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3036ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched LCB, or NULL if no match
3037ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3038ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3039911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_LCB* l2cu_find_lcb_by_handle(uint16_t handle) {
3040911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
3041911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
30425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
3044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->in_use) && (p_lcb->handle == handle)) {
3045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (p_lcb);
30465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
30485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If here, no match found */
3050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (NULL);
30515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
30525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
30535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
3054ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3055ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_find_ccb_by_cid
3056ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3057ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Look through all active CCBs on a link for a match based
3058ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  on the local CID. If passed the link pointer is NULL, all
3059ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  active links are searched.
3060ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3061ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to matched CCB, or NULL if no match
3062ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3063ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3064911d1ae03efec2d54c3b1b605589d790d1745488Myles WatsontL2C_CCB* l2cu_find_ccb_by_cid(tL2C_LCB* p_lcb, uint16_t local_cid) {
3065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = NULL;
30665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t xx;
30685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
30695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (local_cid >= L2CAP_BASE_APPL_CID) {
3071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* find the associated CCB by "index" */
3072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    local_cid -= L2CAP_BASE_APPL_CID;
30735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3074911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (local_cid >= MAX_L2CAP_CHANNELS) return NULL;
30755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool + local_cid;
30775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure the CCB is in use */
3079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_ccb->in_use) {
3080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3082911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure it's for the same LCB */
3083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else if (p_lcb && p_lcb != p_ccb->p_lcb) {
3084911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = NULL;
30855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3087911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#if (L2CAP_UCD_INCLUDED == TRUE)
3088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
3089911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* searching fixed channel */
3090911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cb.ccb_pool;
3091911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0; xx < MAX_L2CAP_CHANNELS; xx++) {
3092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->local_cid == local_cid) && (p_ccb->in_use) &&
3093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_lcb == p_ccb->p_lcb))
3094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        break;
3095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else
3096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb++;
3097911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (xx >= MAX_L2CAP_CHANNELS) return NULL;
3099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
31005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
31015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb);
31035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
31045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
31055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
31065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
31075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel_in_rr
3110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link. It also adjusts the
3112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel_in_rr(tL2C_LCB* p_lcb) {
3118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_serve_ccb = NULL;
3119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
31205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int i, j;
31225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* scan all of priority until finding a channel to serve */
3124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (i = 0; (i < L2CAP_NUM_CHNL_PRIORITY) && (!p_serve_ccb); i++) {
3125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* scan all channel within serving priority group until finding a channel to
3126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * serve */
3127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (j = 0; (j < p_lcb->rr_serv[p_lcb->rr_pri].num_ccb) && (!p_serve_ccb);
3128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         j++) {
3129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* scaning from next serving channel */
3130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb = p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb;
31315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!p_ccb) {
3133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("p_serve_ccb is NULL, rr_pri=%d", p_lcb->rr_pri);
3134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return NULL;
3135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("RR scan pri=%d, lcid=0x%04x, q_cout=%d",
3138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_ccb->ccb_priority, p_ccb->local_cid,
3139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        fixed_queue_length(p_ccb->xmit_hold_q));
3140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* store the next serving channel */
3142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* this channel is the last channel of its priority group */
3143911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_ccb->p_next_ccb == NULL) ||
3144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (p_ccb->p_next_ccb->ccb_priority != p_ccb->ccb_priority)) {
3145911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the first channel in the group */
3146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb =
3147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb->rr_serv[p_lcb->rr_pri].p_first_ccb;
3148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3149911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* next serving channel is set to the next channel in the group */
3150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->rr_serv[p_lcb->rr_pri].p_serve_ccb = p_ccb->p_next_ccb;
3151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->chnl_state != CST_OPEN) continue;
3154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_DEBUG("%s : Connection oriented channel", __func__);
3157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      } else {
3160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* eL2CAP option in use */
3161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
31635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            /* If in eRTM mode, check for window closure */
3168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (l2c_fcr_is_flow_controlled(p_ccb)))
3170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              continue;
3171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        } else {
3173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
31745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
31765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* found a channel to serve */
3178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_serve_ccb = p_ccb;
3179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* decrease quota of its priority group */
3180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota--;
31815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
31825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if there is no more quota of the priority group or no channel to have
3184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * data to send */
3185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb->rr_serv[p_lcb->rr_pri].quota == 0) || (!p_serve_ccb)) {
3186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* serve next priority group */
3187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_pri = (p_lcb->rr_pri + 1) % L2CAP_NUM_CHNL_PRIORITY;
3188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* initialize its quota */
3189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->rr_serv[p_lcb->rr_pri].quota =
3190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_GET_PRIORITY_QUOTA(p_lcb->rr_pri);
31915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_serve_ccb) {
3195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("RR service pri=%d, quota=%d, lcid=0x%04x",
3196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->ccb_priority,
3197911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_lcb->rr_serv[p_serve_ccb->ccb_priority].quota,
3198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_serve_ccb->local_cid);
3199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
32005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return p_serve_ccb;
32025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
32035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#else  /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
32055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
32065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3207ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3208ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_channel
3209ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3210ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next channel to send on a link bassed on priority
3211ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  scheduling.
3212ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3213ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to CCB or NULL
3214ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3215ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tL2C_CCB* l2cu_get_next_channel(tL2C_LCB* p_lcb) {
3217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
32185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Get the first CCB with data to send.
3220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
3221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb) {
3222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->chnl_state != CST_OPEN) continue;
32235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) return p_ccb;
32275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
32295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If in eRTM mode, check for window closure */
3231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (l2c_fcr_is_flow_controlled(p_ccb)))
3233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
32345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If here, we found someone */
3236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return p_ccb;
3237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
32385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return NULL;
32405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
32415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE) */
32425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
324335e95c989923880e838741d52035c065c043921dYamei Duvoid l2cu_tx_complete(tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3244c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  if (p_cbi->cb != NULL) p_cbi->cb(p_cbi->local_cid, p_cbi->num_sdu);
324535e95c989923880e838741d52035c065c043921dYamei Du}
324635e95c989923880e838741d52035c065c043921dYamei Du
32475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3248ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3249ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_get_next_buffer_to_send
3250ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3251ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      get the next buffer to send on a link. It also adjusts the
3252ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  CCB queue to do a basic priority and round-robin scheduling.
3253ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3254ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          pointer to buffer or NULL
3255ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3256ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3257c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub PawlowskiBT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
3258c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                                     tL2C_TX_COMPLETE_CB_INFO* p_cbi) {
3259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
3260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  BT_HDR* p_buf;
32615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson/* Highest priority are fixed channels */
32635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
3264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int xx;
32655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
326635e95c989923880e838741d52035c065c043921dYamei Du  p_cbi->cb = NULL;
326735e95c989923880e838741d52035c065c043921dYamei Du
3268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = p_lcb->p_fixed_ccbs[xx];
3270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == NULL) continue;
32715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* eL2CAP option in use */
3273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_ccb->fcrb.wait_ack || p_ccb->fcrb.remote_busy) continue;
32755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* No more checks needed if sending from the reatransmit queue */
3277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (fixed_queue_is_empty(p_ccb->fcrb.retrans_q)) {
3278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (fixed_queue_is_empty(p_ccb->xmit_hold_q)) continue;
3279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* If in eRTM mode, check for window closure */
3281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) &&
3282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            (l2c_fcr_is_flow_controlled(p_ccb)))
3283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
3284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf != NULL) {
3288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3289911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
3294911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3295911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (NULL == p_buf) {
329635e95c989923880e838741d52035c065c043921dYamei Du          L2CAP_TRACE_ERROR("%s: No data to be sent", __func__);
3297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          return (NULL);
3298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
329935e95c989923880e838741d52035c065c043921dYamei Du
330035e95c989923880e838741d52035c065c043921dYamei Du        /* Prepare callback info for TX completion */
330135e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->cb = l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb;
330235e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->local_cid = p_ccb->local_cid;
330335e95c989923880e838741d52035c065c043921dYamei Du        p_cbi->num_sdu = 1;
3304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_check_channel_congestion(p_ccb);
3306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2cu_set_acl_hci_header(p_buf, p_ccb);
3307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (p_buf);
3308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
33115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
33125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
3314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* get next serving channel in round-robin */
3315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel_in_rr(p_lcb);
33165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
3317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_get_next_channel(p_lcb);
33185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
33195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return if no buffer */
3321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) return (NULL);
33226721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
3323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Check credits */
3325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_conn_cfg.credits == 0) {
3326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("%s No credits to send packets", __func__);
3327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return NULL;
33285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_buf = l2c_lcc_get_next_xmit_sdu_seg(p_ccb, 0);
3330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf == NULL) return (NULL);
33315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->peer_conn_cfg.credits--;
3333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) {
3335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = l2c_fcr_get_next_xmit_sdu_seg(p_ccb, 0);
3336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_buf == NULL) return (NULL);
3337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
3339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (NULL == p_buf) {
3340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send() #2: No data to be sent");
3341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        return (NULL);
3342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
33455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb &&
3347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
3348911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, 1);
33495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_check_channel_congestion(p_ccb);
33515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3352911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_set_acl_hci_header(p_buf, p_ccb);
33535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_buf);
33555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
33565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3358ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3359ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_set_acl_hci_header
3360ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3361ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Set HCI handle for ACL packet
3362ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3363ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3364ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3365ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_set_acl_hci_header(BT_HDR* p_buf, tL2C_CCB* p_ccb) {
3367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* p;
33685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the pointer to the beginning of the data minus 4 bytes for the packet
3370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * header */
3371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p = (uint8_t*)(p_buf + 1) + p_buf->offset - HCI_DATA_PREAMBLE_SIZE;
33725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
3374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | (L2CAP_PKT_START_NON_FLUSHABLE
3375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                << L2CAP_PKT_TYPE_SHIFT));
3376eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh
3377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_ble();
3379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
338484baa7f16e830394408278dbb8c508dd9fa02887Myles Watson    }
3385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
3386eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
3387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_FLUSHABLE_CH_BASED) &&
3389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         (p_ccb->is_flushable)) ||
3390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        ((p_buf->layer_specific & L2CAP_FLUSHABLE_MASK) ==
3391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         L2CAP_FLUSHABLE_PKT)) {
3392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(
3393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_ccb->p_lcb->handle | l2cb.non_flushable_pbf);
3396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
3397eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#else
3398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    UINT16_TO_STREAM(
3399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p, p_ccb->p_lcb->handle | (L2CAP_PKT_START << L2CAP_PKT_TYPE_SHIFT));
3400eb29aed689d70decec163e41c68200bf8fb3d9afRichie Hsieh#endif
34015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3402911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    uint16_t acl_data_size =
3403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        controller_get_interface()->get_acl_data_size_classic();
3404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* The HCI transport will segment the buffers. */
3405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->len > acl_data_size) {
3406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, acl_data_size);
3407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      UINT16_TO_STREAM(p, p_buf->len);
34095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->offset -= HCI_DATA_PREAMBLE_SIZE;
3412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->len += HCI_DATA_PREAMBLE_SIZE;
34135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
34145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
3416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_check_channel_congestion
3418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3419ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      check if any change in congestion status
3420ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3421ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          None
3422ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3423ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid l2cu_check_channel_congestion(tL2C_CCB* p_ccb) {
3425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  size_t q_count = fixed_queue_length(p_ccb->xmit_hold_q);
34265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
34275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    q_count += fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q);
3430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
34315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If the CCB queue limit is subject to a quota, check for congestion */
3433911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* if this channel has outgoing traffic */
3434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->buff_quota != 0) {
3435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If this channel was congested */
3436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->cong_sent) {
3437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If the channel is not congested now, tell the app */
3438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count <= (p_ccb->buff_quota / 2)) {
3439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = false;
3440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb (false), CID: 0x%04x  "
3443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "xmit_hold_q.count: %u  buff_quota: %u",
3444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3445911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* Prevent recursive calling */
3447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = true;
3448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         false);
3450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_cong_cback_context = false;
3451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (false), "
3457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, false);
3462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
34645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3465493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3466911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3467911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, false);
3473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
34745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
3477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
3479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
3480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If this channel was not congested but it is congested now, tell the app
3481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       */
3482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (q_count > p_ccb->buff_quota) {
3483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ccb->cong_sent = true;
3484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb) {
3485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          L2CAP_TRACE_DEBUG(
3486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "L2CAP - Calling CongestionStatus_Cb "
3487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "(true),CID:0x%04x,XmitQ:%u,Quota:%u",
3488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              p_ccb->local_cid, q_count, p_ccb->buff_quota);
3489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
3490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (*p_ccb->p_rcb->api.pL2CA_CongestionStatus_Cb)(p_ccb->local_cid,
3491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                                         true);
34925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
34935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_UCD_INCLUDED == TRUE)
3494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else if (p_ccb->p_rcb && p_ccb->local_cid == L2CAP_CONNECTIONLESS_CID) {
3495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          if (p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb) {
3496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            L2CAP_TRACE_DEBUG(
3497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "L2CAP - Calling UCD CongestionStatus_Cb (true), "
3498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                "SecPendingQ:%u,XmitQ:%u,Quota:%u",
3499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->p_lcb->ucd_out_sec_pending_q),
3500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                fixed_queue_length(p_ccb->xmit_hold_q), p_ccb->buff_quota);
3501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_ccb->p_rcb->ucd.cb_info.pL2CA_UCD_Congestion_Status_Cb(
3502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                p_ccb->p_lcb->remote_bd_addr, true);
3503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
3504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        }
35055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
3506493a98a8de29a35808db28470736819af5fd22d2Andre Eisenbach#if (L2CAP_NUM_FIXED_CHNLS > 0)
3507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        else {
3508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          uint8_t xx;
3509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
3510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            if (p_ccb->p_lcb->p_fixed_ccbs[xx] == p_ccb) {
3511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              if (l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb != NULL)
3512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                (*l2cb.fixed_reg[xx].pL2CA_FixedCong_Cb)(
3513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->p_lcb->remote_bd_addr, true);
3514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              break;
35155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project            }
3516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          }
35175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
3518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#endif
3519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
35205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
3521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
35225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
35235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3524494b510b9bdf5bf9bb8b74181a8f640e54e6cd40Gurpreet Ghai/*******************************************************************************
3525ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3526ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         l2cu_is_ccb_active
3527ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3528ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Check if Channel Control Block is in use or released
3529ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3530ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          bool    - true if Channel Control Block is in use
3531ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                            false if p_ccb is null or is released.
3532ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
3533ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool l2cu_is_ccb_active(tL2C_CCB* p_ccb) { return (p_ccb && p_ccb->in_use); }
3535