15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35b790feeeb211c42bf78ca3ae9c26aa30e516765Jakub Pawlowski *  Copyright 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 the L2CAP API code
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
25a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#define LOG_TAG "bt_l2cap"
26a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
27f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h>
28c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski#include <base/strings/stringprintf.h>
2949a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include <stdio.h>
305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <stdlib.h>
315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include <string.h>
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
33911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "bt_common.h"
345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bt_types.h"
3549a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "btm_api.h"
3649a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "btu.h"
3796fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski#include "device/include/controller.h"
385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcidefs.h"
395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "hcimsgs.h"
405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "l2c_int.h"
4149a86709488e5cfd5e23759da18bf9613e15b04dMarie Janssen#include "l2cdefs.h"
42a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#include "osi/include/allocator.h"
43a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati#include "osi/include/log.h"
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
45c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowskiusing base::StringPrintf;
46c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski
475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
48ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
49ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_Register
50ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
51ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Other layers call this function to register for L2CAP
52ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  services.
53ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
54ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          PSM to use or zero if error. Typically, the PSM returned
55ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is the same as was passed in, but for an outgoing-only
56ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  connection to a dynamic PSM, a "virtual" PSM is returned
57ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and should be used in the calls to L2CA_ConnectReq(),
58ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CA_ErtmConnectReq() and L2CA_Deregister()
59ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
60ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
61911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
62911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb;
63911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t vpsm = psm;
64911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
65911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CAP - L2CA_Register() called for PSM: 0x%04x", psm);
66911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
67911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify that the required callback info has been filled in
68911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **      Note:  Connection callbacks are required but not checked
69911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **             for here because it is possible to be only a client
70911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **             or only a server.
71911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
72911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_cb_info->pL2CA_ConfigCfm_Cb) || (!p_cb_info->pL2CA_ConfigInd_Cb) ||
73911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (!p_cb_info->pL2CA_DataInd_Cb) || (!p_cb_info->pL2CA_DisconnectInd_Cb)) {
74911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CAP - no cb registering PSM: 0x%04x", psm);
75911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
76911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
78911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify PSM is valid */
79911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (L2C_INVALID_PSM(psm)) {
80911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CAP - invalid PSM value, PSM: 0x%04x", psm);
81911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
82911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
84911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check if this is a registration for an outgoing-only connection to */
85911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* a dynamic PSM. If so, allocate a "virtual" PSM for the app to use. */
86911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((psm >= 0x1001) && (p_cb_info->pL2CA_ConnectInd_Cb == NULL)) {
87911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (vpsm = 0x1002; vpsm < 0x8000; vpsm += 2) {
88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_rcb = l2cu_find_rcb_by_psm(vpsm);
89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_rcb == NULL) break;
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_API("L2CA_Register - Real PSM: 0x%04x  Virtual PSM: 0x%04x",
93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    psm, vpsm);
94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If registration block already there, just overwrite it */
97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb = l2cu_find_rcb_by_psm(vpsm);
98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_rcb = l2cu_allocate_rcb(vpsm);
100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_rcb == NULL) {
101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("L2CAP - no RCB available, PSM: 0x%04x  vPSM: 0x%04x",
102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          psm, vpsm);
103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (0);
1045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->api = *p_cb_info;
108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->real_psm = psm;
1095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (vpsm);
1115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
115ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_Deregister
116ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
117ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Other layers call this function to de-register for L2CAP
118ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  services.
119ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
120ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
121ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
122ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid L2CA_Deregister(uint16_t psm) {
124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb;
125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  int ii;
128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CAP - L2CA_Deregister() called for PSM: 0x%04x", psm);
130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb = l2cu_find_rcb_by_psm(psm);
132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb != NULL) {
133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = &l2cb.lcb_pool[0];
134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (ii = 0; ii < MAX_L2CAP_LINKS; ii++, p_lcb++) {
135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->in_use) {
136f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        p_ccb = p_lcb->ccb_queue.p_first_ccb;
137f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        if ((p_ccb == NULL) || (p_lcb->link_state == LST_DISCONNECTING)) {
138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
139f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        }
140911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
141911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if ((p_ccb->in_use) &&
142911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            ((p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP) ||
143f9c5752344ec459def74765f512d28fa0f402168Marie Janssen             (p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))) {
144911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          continue;
145f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        }
146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
147f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        if (p_ccb->p_rcb == p_rcb) {
148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_REQ, NULL);
149f9c5752344ec459def74765f512d28fa0f402168Marie Janssen        }
150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_rcb(p_rcb);
153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - PSM: 0x%04x not found for deregistration",
155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        psm);
156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
160ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
161ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_AllocatePSM
162ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1639ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Other layers call this function to find an unused PSM for
1649ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  L2CAP services.
165ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          PSM to use.
167ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t L2CA_AllocatePSM(void) {
170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool done = false;
171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t psm = l2cb.dyn_psm;
172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_AllocatePSM");
174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while (!done) {
175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    psm += 2;
176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (psm > 0xfeff) {
177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      psm = 0x1001;
178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else if (psm & 0x0100) {
179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* the upper byte must be even */
180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      psm += 0x0100;
181911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if psm is in range of reserved BRCM Aware features */
184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((BRCM_RESERVED_PSM_START <= psm) && (psm <= BRCM_RESERVED_PSM_END))
185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* make sure the newlly allocated psm is not used right now */
188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((l2cu_find_rcb_by_psm(psm)) == NULL) done = true;
189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.dyn_psm = psm;
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (psm);
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
196ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
19749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Function         L2CA_AllocateLePSM
19849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
19949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Description      To find an unused LE PSM for L2CAP services.
20049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
20149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Returns          LE_PSM to use if success. Otherwise returns 0.
20249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
20349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng ******************************************************************************/
20449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tnguint16_t L2CA_AllocateLePSM(void) {
20549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  bool done = false;
20649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  uint16_t psm = l2cb.le_dyn_psm;
20749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  uint16_t count = 0;
20849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
20949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  L2CAP_TRACE_API("%s: last psm=%d", __func__, psm);
21049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  while (!done) {
21149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    count++;
21249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    if (count > LE_DYNAMIC_PSM_RANGE) {
21349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      L2CAP_TRACE_ERROR("%s: Out of free BLE PSM", __func__);
21449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      return 0;
21549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    }
21649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
21749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    psm++;
21849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    if (psm > LE_DYNAMIC_PSM_END) {
21949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      psm = LE_DYNAMIC_PSM_START;
22049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    }
22149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
22249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    if (!l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START]) {
22349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      /* make sure the newly allocated psm is not used right now */
22449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      if (l2cu_find_ble_rcb_by_psm(psm)) {
22549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng        L2CAP_TRACE_WARNING("%s: supposedly-free PSM=%d have allocated rcb!",
22649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng                            __func__, psm);
22749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng        continue;
22849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      }
22949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
23049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START] = true;
23149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      L2CAP_TRACE_DEBUG("%s: assigned PSM=%d", __func__, psm);
23249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      done = true;
23349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      break;
23449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    }
23549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  }
23649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  l2cb.le_dyn_psm = psm;
23749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
23849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  return (psm);
23949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng}
24049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
24149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng/*******************************************************************************
24249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
24349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Function         L2CA_FreeLePSM
24449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
24549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Description      Free an assigned LE PSM.
24649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
24749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng * Returns          void
24849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
24949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng ******************************************************************************/
25049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tngvoid L2CA_FreeLePSM(uint16_t psm) {
25149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  L2CAP_TRACE_API("%s: to free psm=%d", __func__, psm);
25249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
25349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  if ((psm < LE_DYNAMIC_PSM_START) || (psm > LE_DYNAMIC_PSM_END)) {
25449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    L2CAP_TRACE_ERROR("%s: Invalid PSM=%d value!", __func__, psm);
25549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    return;
25649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  }
25749dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
25849dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  if (!l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START]) {
25949dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    L2CAP_TRACE_WARNING("%s: PSM=%d was not allocated!", __func__, psm);
26049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  }
26149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  l2cb.le_dyn_psm_assigned[psm - LE_DYNAMIC_PSM_START] = false;
26249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng}
26349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng
26449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng/*******************************************************************************
26549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng *
266ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConnectReq
267ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2689ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Higher layers call this function to create an L2CAP
2699ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  connection. Note that the connection is not established at
2709ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this time, but connection establishment gets started. The
2719ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  callback function will be invoked when connection
2729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  establishes or fails.
273ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
274ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          the CID of the connection, or 0 if it failed to start
275ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
276ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
277a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskiuint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr) {
278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return L2CA_ErtmConnectReq(psm, p_bd_addr, NULL);
2795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
282ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
283ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ErtmConnectReq
284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2859ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Higher layers call this function to create an L2CAP
2869ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  connection. Note that the connection is not established at
2879ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this time, but connection establishment gets started. The
2889ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  callback function will be invoked when connection
2899ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  establishes or fails.
290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
291ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:       PSM: L2CAP PSM for the connection
292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                    BD address of the peer
293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                   Enhaced retransmission mode configurations
294ee96a3c60fca590d38025925c072d264e06493c4Myles Watson
295ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          the CID of the connection, or 0 if it failed to start
296ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
297ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
298a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskiuint16_t L2CA_ErtmConnectReq(uint16_t psm, const RawAddress& p_bd_addr,
299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                             tL2CAP_ERTM_INFO* p_ertm_info) {
300911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
302911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb;
303911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
304c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << "BDA " << p_bd_addr
305c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" PSM: 0x%04x allowed:0x%x preferred:%d", psm,
306c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          (p_ertm_info) ? p_ertm_info->allowed_modes : 0,
307c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          (p_ertm_info) ? p_ertm_info->preferred_mode : 0);
308911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
309911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if we have not established communications with the controller */
310911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) {
311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP connect req - BTU not ready");
312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if the PSM is not registered */
315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb = l2cu_find_rcb_by_psm(psm);
316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_conn_req, PSM: 0x%04x", psm);
318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* First, see if we already have a link to the remote */
322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* assume all ERTM l2cap connection is going over BR/EDR for now */
323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
325911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No link. Get an LCB and start link establishment */
326f9c5752344ec459def74765f512d28fa0f402168Marie Janssen    p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR);
327f9c5752344ec459def74765f512d28fa0f402168Marie Janssen    /* currently use BR/EDR for ERTM mode l2cap connection */
3285d5fcf26d941315bf91056a7d634846820b7c02fMyles Watson    if ((p_lcb == NULL) || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR))) {
329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING(
330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "L2CAP - conn not started for PSM: 0x%04x  p_lcb: 0x%08x", psm,
331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb);
332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (0);
3335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Allocate a channel control block */
337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_allocate_ccb(p_lcb, 0);
338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
339911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_conn_req, PSM: 0x%04x", psm);
340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
341911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
343911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save registration info */
344911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = p_rcb;
3455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
346911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ertm_info) {
347911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info = *p_ertm_info;
3485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
349911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Replace default indicators with the actual default pool */
350911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.fcr_rx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
351911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
3525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
353911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.fcr_tx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
3555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.user_rx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
3585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.user_tx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
3615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->max_rx_mtu =
363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ertm_info->user_rx_buf_size -
364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET + L2CAP_FCS_LEN);
365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If link is up, start the L2CAP connection */
368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) {
369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_REQ, NULL);
370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If link is disconnecting, save link info to retry after disconnect
373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * Possible Race condition when a reconnect occurs
374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * on the channel during a disconnect of link. This
375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * ccb will be automatically retried after link disconnect
376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * arrives
377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   */
378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_lcb->link_state == LST_DISCONNECTING) {
379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("L2CAP API - link disconnecting: RETRY LATER");
380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Save ccb so it can be started after disconnect is finished */
382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_pending_ccb = p_ccb;
383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CAP - L2CA_conn_req(psm: 0x%04x) returned CID: 0x%04x",
386911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  psm, p_ccb->local_cid);
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return the local CID as our handle */
389911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb->local_cid);
3905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
3915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
3926721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
393ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
394ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_RegisterLECoc
395ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
396ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Other layers call this function to register for L2CAP
397ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Connection Oriented Channel.
398ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
399ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          PSM to use or zero if error. Typically, the PSM returned
400ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  is the same as was passed in, but for an outgoing-only
401ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  connection to a dynamic PSM, a "virtual" PSM is returned
402ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and should be used in the calls to L2CA_ConnectLECocReq()
403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  and L2CA_DeregisterLECoc()
404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
406911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t L2CA_RegisterLECoc(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("%s called for LE PSM: 0x%04x", __func__, psm);
408911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
409911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify that the required callback info has been filled in
410911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **      Note:  Connection callbacks are required but not checked
411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **             for here because it is possible to be only a client
412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  **             or only a server.
413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  */
414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_cb_info->pL2CA_DataInd_Cb) || (!p_cb_info->pL2CA_DisconnectInd_Cb)) {
415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s No cb registering BLE PSM: 0x%04x", __func__, psm);
416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
417911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4186721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Verify PSM is valid */
420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!L2C_IS_VALID_LE_PSM(psm)) {
421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s Invalid BLE PSM value, PSM: 0x%04x", __func__, psm);
422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4246721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb;
426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t vpsm = psm;
4276721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check if this is a registration for an outgoing-only connection to */
429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* a dynamic PSM. If so, allocate a "virtual" PSM for the app to use. */
43049dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  if ((psm >= LE_DYNAMIC_PSM_START) &&
43149dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      (p_cb_info->pL2CA_ConnectInd_Cb == NULL)) {
43249dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    vpsm = L2CA_AllocateLePSM();
43349dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    if (vpsm == 0) {
43449dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      L2CAP_TRACE_ERROR("%s: Out of free BLE PSM", __func__);
43549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng      return 0;
4366721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
4376721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_API("%s Real PSM: 0x%04x  Virtual PSM: 0x%04x", __func__, psm,
439911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    vpsm);
440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
441911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
442911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If registration block already there, just overwrite it */
443911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb = l2cu_find_ble_rcb_by_psm(vpsm);
444911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
44549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    L2CAP_TRACE_API("%s Allocate rcp for Virtual PSM: 0x%04x", __func__, vpsm);
446911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_rcb = l2cu_allocate_ble_rcb(vpsm);
447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_rcb == NULL) {
448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("%s No BLE RCB available, PSM: 0x%04x  vPSM: 0x%04x",
449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          __func__, psm, vpsm);
450911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return 0;
4516721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
452911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4536721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
454911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->api = *p_cb_info;
455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb->real_psm = psm;
4566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return vpsm;
4586721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
4596721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
4606721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
462ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_DeregisterLECoc
463ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
464ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Other layers call this function to de-register for L2CAP
465ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Connection Oriented Channel.
466ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid L2CA_DeregisterLECoc(uint16_t psm) {
471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("%s called for PSM: 0x%04x", __func__, psm);
4726721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = l2cu_find_ble_rcb_by_psm(psm);
474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
47549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng    L2CAP_TRACE_WARNING("%s PSM: 0x%04x not found for deregistration", __func__,
47649dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng                        psm);
477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return;
478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4796721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (int i = 0; i < MAX_L2CAP_LINKS; i++, p_lcb++) {
482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!p_lcb->in_use || p_lcb->transport != BT_TRANSPORT_LE) continue;
4836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2C_CCB* p_ccb = p_lcb->ccb_queue.p_first_ccb;
485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb == NULL) || (p_lcb->link_state == LST_DISCONNECTING)) continue;
4866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->in_use && (p_ccb->chnl_state == CST_W4_L2CAP_DISCONNECT_RSP ||
488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          p_ccb->chnl_state == CST_W4_L2CA_DISCONNECT_RSP))
489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      continue;
490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_rcb == p_rcb)
492911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_REQ, NULL);
493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
4946721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
49549dd53cb3db63dc0f328a6d18413d97b01a48176Stanley Tng  l2cu_release_ble_rcb(p_rcb);
4966721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
4976721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
4986721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
499ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
500ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConnectLECocReq
501ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
5029ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description      Higher layers call this function to create an L2CAP
5039ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  connection. Note that the connection is not established at
5049ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  this time, but connection establishment gets started. The
5059ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  callback function will be invoked when connection
5069ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  establishes or fails.
507ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
508ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:     PSM: L2CAP PSM for the connection
509ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  BD address of the peer
510ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Local Coc configurations
511ee96a3c60fca590d38025925c072d264e06493c4Myles Watson
512ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          the CID of the connection, or 0 if it failed to start
513ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
514ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
515a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskiuint16_t L2CA_ConnectLECocReq(uint16_t psm, const RawAddress& p_bd_addr,
516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              tL2CAP_LE_CFG_INFO* p_cfg) {
517c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << p_bd_addr
518c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" PSM: 0x%04x", psm);
519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if we have not established communications with the controller */
521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) {
522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s BTU not ready", __func__);
523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5256721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if the PSM is not registered */
527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb = l2cu_find_ble_rcb_by_psm(psm);
528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s No BLE RCB, PSM: 0x%04x", __func__, psm);
530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5326721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* First, see if we already have a le link to the remote */
534911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_LE);
535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
536911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No link. Get an LCB and start link establishment */
537911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_LE);
538911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb == NULL)
539911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        /* currently use BR/EDR for ERTM mode l2cap connection */
5405d5fcf26d941315bf91056a7d634846820b7c02fMyles Watson        || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_LE))) {
541911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("%s conn not started for PSM: 0x%04x  p_lcb: 0x%08x",
542911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          __func__, psm, p_lcb);
543911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return 0;
5446721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
545911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5466721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
547911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Allocate a channel control block */
548911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = l2cu_allocate_ccb(p_lcb, 0);
549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s no CCB, PSM: 0x%04x", __func__, psm);
551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return 0;
552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5536721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save registration info */
555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = p_rcb;
5566721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the configuration */
5582dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski  if (p_cfg) {
5592dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski    memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
5602dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski    p_ccb->remote_credit_count = p_cfg->credits;
5612dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski  }
5626721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
563911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If link is up, start the L2CAP connection */
564911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) {
565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
566911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("%s LE Link is up", __func__);
567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_REQ, NULL);
5686721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar    }
569911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
571911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If link is disconnecting, save link info to retry after disconnect
572911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * Possible Race condition when a reconnect occurs
573911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * on the channel during a disconnect of link. This
574911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * ccb will be automatically retried after link disconnect
575911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * arrives
576911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   */
577911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (p_lcb->link_state == LST_DISCONNECTING) {
578911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_DEBUG("%s link disconnecting: RETRY LATER", __func__);
579911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
580911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Save ccb so it can be started after disconnect is finished */
581911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->p_pending_ccb = p_ccb;
582911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
5836721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("%s(psm: 0x%04x) returned CID: 0x%04x", __func__, psm,
585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  p_ccb->local_cid);
5866721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return the local CID as our handle */
588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return p_ccb->local_cid;
5896721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
5906721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
5916721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
592ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
593ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConnectLECocRsp
594ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
595ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to accept an incoming
596ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP COC connection, for which they had gotten an connect
597ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  indication callback.
598ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
599ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true for success, false for failure
600ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
601ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
602a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_ConnectLECocRsp(const RawAddress& p_bd_addr, uint8_t id,
603c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          uint16_t lcid, uint16_t result, uint16_t status,
604911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          tL2CAP_LE_CFG_INFO* p_cfg) {
605c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << p_bd_addr
606c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" CID: 0x%04x Result: %d Status: %d", lcid, result,
607c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          status);
608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* First, find the link control block */
610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_LE);
611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No link. Get an LCB and start link establishment */
613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s no LCB", __func__);
614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6166721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, find the channel control block */
618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
619911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s no CCB", __func__);
621911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
622911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6236721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
624911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* The IDs must match */
625911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->remote_id != id) {
626911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s bad id. Expected: %d  Got: %d", __func__,
627911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_ccb->remote_id, id);
628911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
629911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6306721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
6312dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski  if (p_cfg) {
6322dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski    memcpy(&p_ccb->local_conn_cfg, p_cfg, sizeof(tL2CAP_LE_CFG_INFO));
6332dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski    p_ccb->remote_credit_count = p_cfg->credits;
6342dbd3acb4dcaf94efc7cc64fb9a3155562c0e8f3Jakub Pawlowski  }
6356721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (result == L2CAP_CONN_OK)
637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2C_CONN_INFO conn_info;
640c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    conn_info.bd_addr = p_bd_addr;
641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    conn_info.l2cap_result = result;
642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    conn_info.l2cap_status = status;
643911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP_NEG, &conn_info);
644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6456721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
646911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
6476721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
6486721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
6496721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar/*******************************************************************************
650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function         L2CA_GetPeerLECocConfig
652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
6539ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *  Description      Get a peers configuration for LE Connection Oriented
6549ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                   Channel.
655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:      local channel id
657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                   Pointers to peers configuration storage area
658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:    true if peer is connected
660ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
661ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_GetPeerLECocConfig(uint16_t lcid, tL2CAP_LE_CFG_INFO* peer_cfg) {
663911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("%s CID: 0x%04x", __func__, lcid);
6646721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
665911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
666911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s No CCB for CID:0x%04x", __func__, lcid);
668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
6706721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
671911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (peer_cfg != NULL)
672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    memcpy(peer_cfg, &p_ccb->peer_conn_cfg, sizeof(tL2CAP_LE_CFG_INFO));
673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
6756721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar}
6766721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar
677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SetConnectionCallbacks(uint16_t local_cid,
678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 const tL2CAP_APPL_INFO* callbacks) {
679f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks != NULL);
680f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_ConnectInd_Cb == NULL);
681f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_ConnectCfm_Cb != NULL);
682f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_ConfigInd_Cb != NULL);
683f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_ConfigCfm_Cb != NULL);
684f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_DisconnectInd_Cb != NULL);
685f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_DisconnectCfm_Cb != NULL);
686f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_CongestionStatus_Cb != NULL);
687f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_DataInd_Cb != NULL);
688f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He  CHECK(callbacks->pL2CA_TxComplete_Cb != NULL);
689a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
690911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* channel_control_block = l2cu_find_ccb_by_cid(NULL, local_cid);
691a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  if (!channel_control_block) {
692911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    LOG_ERROR(LOG_TAG,
693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              "%s no channel control block found for L2CAP LCID=0x%04x.",
694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson              __func__, local_cid);
695a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati    return false;
696a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  }
697a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
6989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson  // We're making a connection-specific registration control block so we check
6999ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson  // if we already have a private one allocated to us on the heap. If not, we
7009ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson  // make a new allocation, mark it as heap-allocated, and inherit the fields
7019ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson  // from the old control block.
702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* registration_control_block = channel_control_block->p_rcb;
703a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  if (!channel_control_block->should_free_rcb) {
704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    registration_control_block = (tL2C_RCB*)osi_calloc(sizeof(tL2C_RCB));
705a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
706a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati    *registration_control_block = *channel_control_block->p_rcb;
707a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati    channel_control_block->p_rcb = registration_control_block;
708a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati    channel_control_block->should_free_rcb = true;
709a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  }
710a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati
711a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  registration_control_block->api = *callbacks;
712a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati  return true;
713a3dd6f9607654a50195215deeb388919581752c7Sharvil Nanavati}
7145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
716ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
717ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConnectRsp
718ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
719ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to accept an incoming
720ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP connection, for which they had gotten an connect
721ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  indication callback.
722ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
723ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true for success, false for failure
724ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
725ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
726a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_ConnectRsp(const RawAddress& p_bd_addr, uint8_t id, uint16_t lcid,
727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                     uint16_t result, uint16_t status) {
728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return L2CA_ErtmConnectRsp(p_bd_addr, id, lcid, result, status, NULL);
7295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
732ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
733ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ErtmConnectRsp
734ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
735ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to accept an incoming
736ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP connection, for which they had gotten an connect
737ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  indication callback.
738ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
739ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true for success, false for failure
740ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
741ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
742a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_ErtmConnectRsp(const RawAddress& p_bd_addr, uint8_t id, uint16_t lcid,
743a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowski                         uint16_t result, uint16_t status,
744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                         tL2CAP_ERTM_INFO* p_ertm_info) {
745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
748c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << p_bd_addr
749c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" CID:0x%04x  Result:%d  Status:%d", lcid, result,
750c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          status);
751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* First, find the link control block */
753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No link. Get an LCB and start link establishment */
756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_conn_rsp");
757911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
758911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
760911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now, find the channel control block */
761911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(p_lcb, lcid);
762911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
763911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_conn_rsp");
764911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* The IDs must match */
768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->remote_id != id) {
769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - bad id in L2CA_conn_rsp. Exp: %d  Got: %d",
770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_ccb->remote_id, id);
771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ertm_info) {
775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->ertm_info = *p_ertm_info;
7765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Replace default indicators with the actual default pool */
778911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.fcr_rx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
779911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_FCR_RX_BUF_SIZE;
7805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.fcr_tx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_FCR_TX_BUF_SIZE;
7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.user_rx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.user_rx_buf_size = L2CAP_USER_RX_BUF_SIZE;
7865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->ertm_info.user_tx_buf_size == L2CAP_INVALID_ERM_BUF_SIZE)
788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb->ertm_info.user_tx_buf_size = L2CAP_USER_TX_BUF_SIZE;
7895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->max_rx_mtu =
791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_ertm_info->user_rx_buf_size -
792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        (L2CAP_MIN_OFFSET + L2CAP_SDU_LEN_OFFSET + L2CAP_FCS_LEN);
793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
7945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (result == L2CAP_CONN_OK) {
796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, NULL);
797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2C_CONN_INFO conn_info;
7995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    conn_info.l2cap_result = result;
801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    conn_info.l2cap_status = status;
8025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (result == L2CAP_CONN_PENDING)
804911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP, &conn_info);
805911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
806911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_RSP_NEG, &conn_info);
807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
8105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
813ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
814ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConfigReq
815ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
816ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to send configuration.
817ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
818ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Note:  The FCR options of p_cfg are not used.
819ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
820ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if configuration sent, else false
821ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
822ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_ConfigReq(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API(
827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "L2CA_ConfigReq()  CID 0x%04x: fcr_present:%d (mode %d) mtu_present:%d "
828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "(%d)",
829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      cid, p_cfg->fcr_present, p_cfg->fcr.mode, p_cfg->mtu_present, p_cfg->mtu);
830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_cfg_req, CID: %d", cid);
835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* We need to have at least one mode type common with the peer */
839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2c_fcr_adj_our_req_options(p_ccb, p_cfg)) return (false);
8405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Don't adjust FCR options if not used */
842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((!p_cfg->fcr_present) || (p_cfg->fcr.mode == L2CAP_FCR_BASIC_MODE)) {
843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* FCR and FCS options are not used in basic mode */
844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->fcs_present = false;
845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->ext_flow_spec_present = false;
8465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_cfg->mtu_present) && (p_cfg->mtu > L2CAP_MTU_SIZE)) {
848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("L2CAP - adjust MTU: %u too large", p_cfg->mtu);
849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->mtu = L2CAP_MTU_SIZE;
8505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save the adjusted configuration in case it needs to be used for
854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * renegotiation */
855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->our_cfg = *p_cfg;
8565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_REQ, p_cfg);
8585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
8605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
863ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
864ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_ConfigRsp
865ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
866ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to send a configuration
867ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  response.
868ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
869ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if configuration response sent, else false
870ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
871ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
872911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_ConfigRsp(uint16_t cid, tL2CAP_CFG_INFO* p_cfg) {
873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API(
876911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "L2CA_ConfigRsp()  CID: 0x%04x  Result: %d MTU present:%d Flush TO:%d "
877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "FCR:%d FCS:%d",
878911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      cid, p_cfg->result, p_cfg->mtu_present, p_cfg->flush_to_present,
879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_cfg->fcr_present, p_cfg->fcs_present);
880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
884911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_cfg_rsp, CID: %d", cid);
885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
8875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_cfg->result == L2CAP_CFG_OK) || (p_cfg->result == L2CAP_CFG_PENDING))
889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_RSP, p_cfg);
890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else {
891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_cfg->fcr_present =
892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        false; /* FCR options already negotiated before this point */
8935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Clear out any cached options that are being returned as an error
895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * (excluding FCR) */
896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->mtu_present) p_ccb->peer_cfg.mtu_present = false;
897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->flush_to_present) p_ccb->peer_cfg.flush_to_present = false;
898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_cfg->qos_present) p_ccb->peer_cfg.qos_present = false;
8995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONFIG_RSP_NEG, p_cfg);
901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
903911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
9045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_DisconnectReq
909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to disconnect a channel.
911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
912ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if disconnect sent, else false
913ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
914ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
915911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_DisconnectReq(uint16_t cid) {
916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
9175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_DisconnectReq()  CID: 0x%04x", cid);
9195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_disc_req, CID: %d", cid);
924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_REQ, NULL);
9285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
9305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
933ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
934ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_DisconnectRsp
935ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to acknowledge the
937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  disconnection of a channel.
938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          void
940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
942911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_DisconnectRsp(uint16_t cid) {
943911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
9445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_DisconnectRsp()  CID: 0x%04x", cid);
9465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
947911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
948911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
949911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_disc_rsp, CID: %d", cid);
951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
9535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_csm_execute(p_ccb, L2CEVT_L2CA_DISCONNECT_RSP, NULL);
9555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
9575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
9585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
960ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
961ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_Ping
962ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
963ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to send an echo request.
964ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
965ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if echo request sent, else false.
966ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
967ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
968a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_Ping(const RawAddress& p_bd_addr, tL2CA_ECHO_RSP_CB* p_callback) {
969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
9705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
971c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << p_bd_addr;
9725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if we have not established communications with the controller */
974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) return (false);
9755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* First, see if we already have a link to the remote */
977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* No link. Get an LCB and start link establishment */
980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR);
981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb == NULL) {
982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_ping");
983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (false);
9845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9855d5fcf26d941315bf91056a7d634846820b7c02fMyles Watson    if (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR)) {
986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (false);
9875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
9885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
9895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    p_lcb->p_echo_rsp_cb = p_callback;
9905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
991d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen    return (true);
992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
993911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
994911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* We only allow 1 ping outstanding at a time */
995911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_echo_rsp_cb != NULL) {
996911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - rejected second L2CA_ping");
997911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Have a link control block. If link is disconnecting, tell user to retry
1001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * later */
1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_DISCONNECTING) {
1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - L2CA_ping rejected - link disconnecting");
1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save address of callback */
1008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_echo_rsp_cb = p_callback;
1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state == LST_CONNECTED) {
1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_adj_id(p_lcb, L2CAP_ADJ_BRCM_ID); /* Make sure not using Broadcom ID */
1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_send_peer_echo_req(p_lcb, NULL, 0);
1013be8bbd7a83ec8bc900fac58a03010fbcb74956c9Jakub Pawlowski    alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_ECHO_RSP_TIMEOUT_MS,
1014be8bbd7a83ec8bc900fac58a03010fbcb74956c9Jakub Pawlowski                       l2c_lcb_timer_timeout, p_lcb);
1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
10185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1021ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1022ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_Echo
1023ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1024ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to send an echo request
1025ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  with application-specific data.
1026ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1027ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if echo request sent, else false.
1028ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1029ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1030a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_Echo(const RawAddress& p_bd_addr, BT_HDR* p_data,
1031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson               tL2CA_ECHO_DATA_CB* p_callback) {
1032911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1033911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint8_t* pp;
10345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1035c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << p_bd_addr;
1036c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  ;
10375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1038911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if we have not established communications with the controller */
1039911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) return (false);
10405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1041b707f447cbb916de2e0dfd2b4e9bf15818376e64Jakub Pawlowski  if (RawAddress::kAny == p_bd_addr && (p_data == NULL)) {
1042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Only register callback without sending message. */
10435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    l2cb.p_echo_data_cb = p_callback;
1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return true;
1045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* We assume the upper layer will call this function only when the link is
1048911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * established. */
1049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
1050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
1051911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CA_Echo ERROR : link not established");
1052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
1053911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->link_state != LST_CONNECTED) {
1056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CA_Echo ERROR : link is not connected");
1057911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
1058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
10595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1060911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save address of callback */
1061911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.p_echo_data_cb = p_callback;
1062911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1063911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Set the pointer to the beginning of the data */
1064911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  pp = (uint8_t*)(p_data + 1) + p_data->offset;
1065911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_adj_id(p_lcb, L2CAP_ADJ_BRCM_ID); /* Make sure not using Broadcom ID */
1066911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_send_peer_echo_req(p_lcb, pp, p_data->len);
1067911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1068911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
10695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1071911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_GetIdentifiers(uint16_t lcid, uint16_t* rcid, uint16_t* handle) {
1072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* control_block = l2cu_find_ccb_by_cid(NULL, lcid);
1073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!control_block) return false;
10749f995d261c8ff0d281f5c25b283e0800bb2d59ddSharvil Nanavati
1075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (rcid) *rcid = control_block->remote_cid;
1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (handle) *handle = control_block->p_lcb->handle;
10779f995d261c8ff0d281f5c25b283e0800bb2d59ddSharvil Nanavati
10789f995d261c8ff0d281f5c25b283e0800bb2d59ddSharvil Nanavati  return true;
10799f995d261c8ff0d281f5c25b283e0800bb2d59ddSharvil Nanavati}
10809f995d261c8ff0d281f5c25b283e0800bb2d59ddSharvil Nanavati
10815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1082ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1083ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetIdleTimeout
1084ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1085ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to set the idle timeout for
10869ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  a connection, or for all future connections. The "idle
10879ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  timeout" is the amount of time that a connection can remain
10889ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  up with no L2CAP channels on it. A timeout of zero means
10899ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  that the connection will be torn down immediately when the
10909ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  last channel is removed. A timeout of 0xFFFF means no
10919ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  timeout. Values are in seconds.
1092ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if command succeeded, false if failed
1094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1095ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * NOTE             This timeout takes effect after at least 1 channel has been
1096ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  established and removed. L2CAP maintains its own timer from
1097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  whan a connection is established till the first channel is
1098ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  set up.
1099ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SetIdleTimeout(uint16_t cid, uint16_t timeout, bool is_global) {
1101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (is_global) {
1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.idle_timeout = timeout;
1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1107911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Find the channel control block. We don't know the link it is on. */
1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
1109911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb == NULL) {
1110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_SetIdleTimeout, CID: %d",
1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          cid);
1112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (false);
11135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
11145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = p_ccb->p_lcb;
11165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1117911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
1118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->idle_timeout = timeout;
1119911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
1120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (false);
1121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
11245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1127ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetIdleTimeoutByBdAddr
1129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to set the idle timeout for
1131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  a connection. The "idle timeout" is the amount of time that
1132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  a connection can remain up with no L2CAP channels on it.
1133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  A timeout of zero means that the connection will be torn
1134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  down immediately when the last channel is removed.
1135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  A timeout of 0xFFFF means no timeout. Values are in seconds.
1136b7b747369200c0c6588e3099cedc6cfc454e14e0Jakub Pawlowski *                  A bd_addr is the remote BD address. If bd_addr =
1137b707f447cbb916de2e0dfd2b4e9bf15818376e64Jakub Pawlowski *                  RawAddress::kAny, then the idle timeouts for all active
1138b707f447cbb916de2e0dfd2b4e9bf15818376e64Jakub Pawlowski *                  l2cap links will be changed.
1139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if command succeeded, false if failed
1141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * NOTE             This timeout applies to all logical channels active on the
1143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  ACL link.
1144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1145a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr, uint16_t timeout,
1146911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 tBT_TRANSPORT transport) {
1147911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1149882aec320e88b0860a3d53db828bb099c7ca2409Jack He  if (RawAddress::kAny != bd_addr) {
1150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, transport);
1151911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
1152911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->idle_timeout = timeout;
1153911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!p_lcb->ccb_queue.p_first_ccb) l2cu_no_dynamic_ccbs(p_lcb);
1155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else
1156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
1157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1158911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    int xx;
1159911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    tL2C_LCB* p_lcb = &l2cb.lcb_pool[0];
1160911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1161911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
1162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
1163911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->idle_timeout = timeout;
1164911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1165911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (!p_lcb->ccb_queue.p_first_ccb) l2cu_no_dynamic_ccbs(p_lcb);
1166911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
11675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
11695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1170911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
11715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1174ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1175ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetTraceLevel
1176ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1177ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function sets the trace level for L2CAP. If called with
1178ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  a value of 0xFF, it simply reads the current trace level.
1179ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1180ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          the new (current) trace level
1181ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1182ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t L2CA_SetTraceLevel(uint8_t new_level) {
1184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (new_level != 0xFF) l2cb.l2cap_trace_level = new_level;
11855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cb.l2cap_trace_level);
11875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
11885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
11895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1190ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1191ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function     L2CA_SetDesireRole
1192ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1193ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description  This function sets the desire role for L2CAP.
1194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              If the new role is L2CAP_ROLE_ALLOW_SWITCH, allow switch on
1195ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              HciCreateConnection.
11969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *              If the new role is L2CAP_ROLE_DISALLOW_SWITCH, do not allow
11979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *              switch on HciCreateConnection.
1198ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
11999ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *              If the new role is a valid role (HCI_ROLE_MASTER or
12009ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *              HCI_ROLE_SLAVE), the desire role is set to the new value.
12019ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *              Otherwise, it is not changed.
1202ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1203ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns      the new (current) role
1204ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1205ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t L2CA_SetDesireRole(uint8_t new_role) {
1207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_SetDesireRole() new:x%x, disallow_switch:%d", new_role,
1208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  l2cb.disallow_switch);
1209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (L2CAP_ROLE_CHECK_SWITCH != (L2CAP_ROLE_CHECK_SWITCH & new_role)) {
1211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* do not process the allow_switch when both bits are set */
1212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (new_role & L2CAP_ROLE_ALLOW_SWITCH) {
1213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.disallow_switch = false;
1214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1215911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (new_role & L2CAP_ROLE_DISALLOW_SWITCH) {
1216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      l2cb.disallow_switch = true;
12175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (new_role == HCI_ROLE_MASTER || new_role == HCI_ROLE_SLAVE)
1221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cb.desire_role = new_role;
12225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cb.desire_role);
12245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1227ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1228ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function     L2CA_LocalLoopbackReq
1229ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1230ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description  This function sets up a CID for local loopback
1231ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1232ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns      CID of 0 if none.
1233ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1234ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t L2CA_LocalLoopbackReq(uint16_t psm, uint16_t handle,
1236a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowski                               const RawAddress& p_bd_addr) {
1237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1239911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_RCB* p_rcb;
1240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_LocalLoopbackReq()  PSM: %d  Handle: 0x%04x", psm,
1242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  handle);
1243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if we have not established communications with the controller */
1245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) {
1246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP loop req - BTU not ready");
1247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
1248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Fail if the PSM is not registered */
1251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_rcb = l2cu_find_rcb_by_psm(psm);
1252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_rcb == NULL) {
1253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_conn_req, PSM: %d", psm);
1254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
1255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR);
1258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
1259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_conn_req");
1260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
1261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->link_state = LST_CONNECTED;
1264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->handle = handle;
12655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Allocate a channel control block */
1267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_allocate_ccb(p_lcb, 0);
1268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
1269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_conn_req");
1270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
1271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
12725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Save registration info */
1274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->p_rcb = p_rcb;
1275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->chnl_state = CST_OPEN;
1276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->remote_cid = p_ccb->local_cid;
1277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->config_done = CFG_DONE_MASK;
12785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return the local CID as our handle */
1280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (p_ccb->local_cid);
12815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
12835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1284ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1285ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetAclPriority
1286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1287ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the transmission priority for a channel.
1288ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  (For initial implementation only two values are valid.
1289ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_PRIORITY_NORMAL and L2CAP_PRIORITY_HIGH).
1290ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1291ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
1292ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1293ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1294a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_SetAclPriority(const RawAddress& bd_addr, uint8_t priority) {
12953ebc3c5ac0f288be3a8e1ee8b0e56a9ece740200Jack He  VLOG(1) << __func__ << " BDA: " << bd_addr
12963ebc3c5ac0f288be3a8e1ee8b0e56a9ece740200Jack He          << ", priority: " << std::to_string(priority);
1297911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (l2cu_set_acl_priority(bd_addr, priority, false));
12985738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
12995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1301ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1302ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_FlowControl
1303ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1304ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to flow control a channel.
1305ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1306ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  data_enabled - true data flows, false data is stopped
1307ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1308ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if valid channel, else false
1309ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1311911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_FlowControl(uint16_t cid, bool data_enabled) {
1312911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1313911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool on_off = !data_enabled;
1314911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1315911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_FlowControl(%d)  CID: 0x%04x", on_off, cid);
1316911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1317911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
1318911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
1319911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
1320911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
1321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CAP - no CCB for L2CA_FlowControl, CID: 0x%04x  data_enabled: %d",
1322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        cid, data_enabled);
1323911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1324911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) {
1327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_EVENT("L2CA_FlowControl()  invalid mode:%d",
1328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      p_ccb->peer_cfg.fcr.mode);
1329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1330911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->fcrb.local_busy != on_off) {
1332911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_ccb->fcrb.local_busy = on_off;
13335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_ccb->chnl_state == CST_OPEN) && (!p_ccb->fcrb.wait_ack)) {
1335911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (on_off)
1336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RNR, 0);
1337911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      else
1338911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        l2c_fcr_send_S_frame(p_ccb, L2CAP_FCR_SUP_RR, L2CAP_FCR_P_BIT);
13395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1340911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1342911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
13435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1346ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1347ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SendTestSFrame
1348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to send a test S-frame.
1350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if valid Channel, else false
1352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1354911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SendTestSFrame(uint16_t cid, uint8_t sup_type, uint8_t back_track) {
1355911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API(
1358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      "L2CA_SendTestSFrame()  CID: 0x%04x  Type: 0x%02x  back_track: %u", cid,
1359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      sup_type, back_track);
1360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
1362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
1363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
1364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_SendTestSFrame, CID: %d", cid);
1365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
13675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_ccb->chnl_state != CST_OPEN) ||
1369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE))
1370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
13715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->fcrb.next_seq_expected -= back_track;
13735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_fcr_send_S_frame(
1375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_ccb, (uint16_t)(sup_type & 3),
1376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (uint16_t)(sup_type & (L2CAP_FCR_P_BIT | L2CAP_FCR_F_BIT)));
13775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
13795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1382ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1383ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetTxPriority
1384ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1385ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the transmission priority for a channel.
1386ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1387ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
1388ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1389ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SetTxPriority(uint16_t cid, tL2CAP_CHNL_PRIORITY priority) {
1391911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
13925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1393911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_SetTxPriority()  CID: 0x%04x, priority:%d", cid,
1394911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  priority);
13955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1396911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
1397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
1398911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
1399911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_SetTxPriority, CID: %d", cid);
1400911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1401911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
14025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1403911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* it will update the order of CCB in LCB by priority and update round robin
1404911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * service variables */
1405911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_change_pri_ccb(p_ccb, priority);
14065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1407911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
14085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
14095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1411ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1412ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetChnlDataRate
1413ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1414ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Sets the tx/rx data rate for a channel.
1415ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1416ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if a valid channel, else false
1417ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1418ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SetChnlDataRate(uint16_t cid, tL2CAP_CHNL_DATA_RATE tx,
1420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          tL2CAP_CHNL_DATA_RATE rx) {
1421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_SetChnlDataRate()  CID: 0x%04x, tx:%d, rx:%d", cid, tx,
1424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  rx);
1425911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1426911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
1427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
1428911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
1429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_SetChnlDataRate, CID: %d",
1430911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        cid);
1431911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1432911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
14335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1434911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->tx_data_rate = tx;
1435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->rx_data_rate = rx;
14365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1437911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Adjust channel buffer allocation */
1438911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_adjust_chnl_allocation();
14395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1440911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
14415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
14425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
14435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1444ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1445ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetFlushTimeout
1446ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1447ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      This function set the automatic flush time out in Baseband
1448ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  for ACL-U packets.
14499ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  BdAddr : the remote BD address of ACL link. If it is
14509ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                          BT_DB_ANY then the flush time out will be applied to
14519ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                          all ACL links.
1452ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  FlushTimeout: flush time out in ms
1453ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                           0x0000 : No automatic flush
1454ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                           L2CAP_NO_RETRANSMISSION : No retransmission
14559ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                           0x0002 - 0xFFFE : flush time out, if
14569ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                            (flush_tout * 8) + 3 / 5) <=
1457b8568ae0e198a84225c9fdef1e715dc4d45565c9Pavlin Radoslavov *                                             HCI_MAX_AUTOMATIC_FLUSH_TIMEOUT
14589ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                            (in 625us slot).
1459ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                                    Otherwise, return false.
1460ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                           L2CAP_NO_AUTOMATIC_FLUSH : No automatic flush
1461ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1462ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if command succeeded, false if failed
1463ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
14649ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * NOTE             This flush timeout applies to all logical channels active on
14659ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  the ACL link.
1466ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1467a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_SetFlushTimeout(const RawAddress& bd_addr, uint16_t flush_tout) {
1468911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1469911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t hci_flush_to;
1470911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint32_t temp;
1471911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1472911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* no automatic flush (infinite timeout) */
1473911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (flush_tout == 0x0000) {
1474911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    hci_flush_to = flush_tout;
1475911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    flush_tout = L2CAP_NO_AUTOMATIC_FLUSH;
1476911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1477911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* no retransmission */
1478911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (flush_tout == L2CAP_NO_RETRANSMISSION) {
1479911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* not mandatory range for controller */
1480911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* Packet is flushed before getting any ACK/NACK */
1481911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* To do this, flush timeout should be 1 baseband slot */
1482911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    hci_flush_to = flush_tout;
1483911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* no automatic flush (infinite timeout) */
1485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else if (flush_tout == L2CAP_NO_AUTOMATIC_FLUSH) {
1486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    hci_flush_to = 0x0000;
1487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1488911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* convert L2CAP flush_to to 0.625 ms units, with round */
1489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    temp = (((uint32_t)flush_tout * 8) + 3) / 5;
1490911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* if L2CAP flush_to within range of HCI, set HCI flush timeout */
1492b8568ae0e198a84225c9fdef1e715dc4d45565c9Pavlin Radoslavov    if (temp > HCI_MAX_AUTOMATIC_FLUSH_TIMEOUT) {
1493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING(
1494911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          "WARNING L2CA_SetFlushTimeout timeout(0x%x) is out of range",
1495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          flush_tout);
1496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
1497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      hci_flush_to = (uint16_t)temp;
14995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1500911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1502882aec320e88b0860a3d53db828bb099c7ca2409Jack He  if (RawAddress::kAny != bd_addr) {
1503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
15045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1505911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
1506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (p_lcb->link_flush_tout != flush_tout) {
1507911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->link_flush_tout = flush_tout;
1508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1509c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski        VLOG(1) << __func__ << " BDA: " << bd_addr << " " << flush_tout << "ms";
1510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1511911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to);
1512911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
1513911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    } else {
1514c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski      LOG(WARNING) << __func__ << " No lcb for bd_addr " << bd_addr;
1515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (false);
1516911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
1517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
1518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    int xx;
1519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb = &l2cb.lcb_pool[0];
1520911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++) {
1522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED)) {
1523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        if (p_lcb->link_flush_tout != flush_tout) {
1524911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->link_flush_tout = flush_tout;
1525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1526c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          VLOG(1) << __func__ << " BDA: " << p_lcb->remote_bd_addr << " "
1527c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                  << flush_tout << "ms";
1528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btsnd_hcic_write_auto_flush_tout(p_lcb->handle, hci_flush_to);
15305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
1531911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
15325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1535911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
15365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1539ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1540ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function         L2CA_GetPeerFeatures
1541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1542ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description      Get a peers features and fixed channel map
1543ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:      BD address of the peer
1545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                   Pointers to features and channel mask storage area
1546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:    true if peer is connected
1548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1549ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1550a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_GetPeerFeatures(const RawAddress& bd_addr, uint32_t* p_ext_feat,
1551911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          uint8_t* p_chnl_mask) {
1552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1553911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* We must already have a link to the remote */
1555911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
1556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
1557c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    LOG(WARNING) << __func__ << " No BDA: " << bd_addr;
1558c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    return false;
1559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1561c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << bd_addr
1562c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" ExtFea: 0x%08x Chnl_Mask[0]: 0x%02x",
1563c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                          p_lcb->peer_ext_fea, p_lcb->peer_chnl_mask[0]);
15645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1565911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  *p_ext_feat = p_lcb->peer_ext_fea;
15665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1567911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  memcpy(p_chnl_mask, p_lcb->peer_chnl_mask, L2CAP_FIXED_CHNL_ARRAY_SIZE);
15685738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1569c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  return true;
15705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1573ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function         L2CA_GetBDAddrbyHandle
1575ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1576ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description      Get BD address for the given HCI handle
1577ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1578ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:      HCI handle
1579ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                   BD address of the peer
1580ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1581ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:    true if found lcb for the given handle, false otherwise
1582ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1583ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1584a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_GetBDAddrbyHandle(uint16_t handle, RawAddress& bd_addr) {
1585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb = NULL;
1586911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  bool found_dev = false;
1587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_handle(handle);
1589911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb) {
1590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    found_dev = true;
1591c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    bd_addr = p_lcb->remote_bd_addr;
1592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
15935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1594911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return found_dev;
15955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
15965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
15975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1598ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1599ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function         L2CA_GetChnlFcrMode
1600ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1601ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description      Get the channel FCR mode
1602ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1603ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:      Local CID
1604ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1605ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:    Channel mode
1606ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1607ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1608911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t L2CA_GetChnlFcrMode(uint16_t lcid) {
1609911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
16105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb) {
1612911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_API("L2CA_GetChnlFcrMode() returns mode %d",
1613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    p_ccb->peer_cfg.fcr.mode);
1614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (p_ccb->peer_cfg.fcr.mode);
1615911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1616911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_GetChnlFcrMode() returns mode L2CAP_FCR_BASIC_MODE");
1618911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (L2CAP_FCR_BASIC_MODE);
16195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NUM_FIXED_CHNLS > 0)
16225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1623ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1624ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function        L2CA_RegisterFixedChannel
1625ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1626ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description     Register a fixed channel.
1627ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1628ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:     Fixed Channel #
1629ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Channel Callbacks and config
1630ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1631ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:   -
1632ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1633ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1634911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_RegisterFixedChannel(uint16_t fixed_cid,
1635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               tL2CAP_FIXED_CHNL_REG* p_freg) {
1636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((fixed_cid < L2CAP_FIRST_FIXED_CHNL) ||
1637911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (fixed_cid > L2CAP_LAST_FIXED_CHNL)) {
1638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CA_RegisterFixedChannel()  Invalid CID: 0x%04x",
1639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      fixed_cid);
1640911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1642911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1644911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = *p_freg;
1645911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
16465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
16475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
16485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function        L2CA_ConnectFixedChnl
1651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description     Connect an fixed signalling channel to a remote device.
1653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1654ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:     Fixed CID
1655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  BD Address of remote
1656ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1657ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:   true if connection started
1658ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1659ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1660a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& rem_bda) {
166196fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
166296fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  return L2CA_ConnectFixedChnl(fixed_cid, rem_bda, phy);
166396fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski}
166496fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski
1665a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& rem_bda,
166696fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski                           uint8_t initiating_phys) {
1667911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1668911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
1669911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1670c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(1) << __func__ << " BDA: " << rem_bda
1671c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf("CID: 0x%04x ", fixed_cid);
1672911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1673911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Check CID is valid and registered
1674911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((fixed_cid < L2CAP_FIRST_FIXED_CHNL) ||
1675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (fixed_cid > L2CAP_LAST_FIXED_CHNL) ||
1676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb ==
1677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       NULL)) {
1678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("%s() Invalid CID: 0x%04x", __func__, fixed_cid);
1679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1680911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Fail if BT is not yet up
1683911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) {
1684911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s(0x%04x) - BTU not ready", __func__, fixed_cid);
1685911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1686911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
16875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1688911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
1689911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    transport = BT_TRANSPORT_LE;
16900b47e0a35c16f5b7d77c30ec1c095ed92ff4fd74Satya Calloji
1691911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_BLE_FIXED_CHNLS_MASK peer_channel_mask;
16927fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
1693911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // If we already have a link to the remote, check if it supports that CID
1694911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, transport);
1695911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb != NULL) {
1696911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // Fixed channels are mandatory on LE transports so ignore the received
1697911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // channel mask and use the locally cached LE channel mask.
16987fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
1699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (transport == BT_TRANSPORT_LE)
1700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      peer_channel_mask = l2cb.l2c_ble_fixed_chnls_mask;
1701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    else
1702911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      peer_channel_mask = p_lcb->peer_chnl_mask[0];
17035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // Check for supported channel
1705911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!(peer_channel_mask & (1 << fixed_cid))) {
1706c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski      VLOG(2) << __func__ << " BDA " << rem_bda
1707c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski              << StringPrintf(" CID:0x%04x not supported", fixed_cid);
1708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
17095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17110b47e0a35c16f5b7d77c30ec1c095ed92ff4fd74Satya Calloji    // Get a CCB and link the lcb to it
1712911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!l2cu_initialize_fixed_ccb(
1713911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb, fixed_cid,
1714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL]
1715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 .fixed_chnl_opts)) {
1716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("%s(0x%04x) - LCB but no CCB", __func__, fixed_cid);
1717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return false;
17185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
17195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // racing with disconnecting, queue the connection request
1721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_lcb->link_state == LST_DISCONNECTING) {
1722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_DEBUG("$s() - link disconnecting: RETRY LATER", __func__);
1723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* Save ccb so it can be started after disconnect is finished */
1724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      p_lcb->p_pending_ccb =
1725911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
1726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return true;
17278d36b38752e82bfe33d9e6d861ed59ede3f0a7bfMudumba Ananth    }
1728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)(
1730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        fixed_cid, p_lcb->remote_bd_addr, true, 0, p_lcb->transport);
1731d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen    return true;
1732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // No link. Get an LCB and start link establishment
1735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_allocate_lcb(rem_bda, false, transport);
1736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb == NULL) {
1737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s(0x%04x) - no LCB", __func__, fixed_cid);
1738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
1739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Get a CCB and link the lcb to it
1742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!l2cu_initialize_fixed_ccb(
1743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          p_lcb, fixed_cid, &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL]
1744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 .fixed_chnl_opts)) {
1745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
1746911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s(0x%04x) - no CCB", __func__, fixed_cid);
1747911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_lcb(p_lcb);
1748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
1749911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
175196fb273d92a31204edcf43ab2594a19876d14056Jakub Pawlowski  if (!l2cu_create_conn(p_lcb, transport, initiating_phys)) {
1752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("%s() - create_conn failed", __func__);
1753911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_release_lcb(p_lcb);
1754911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
1755911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
1756911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
17575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
17585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
17595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1760ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1761ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function        L2CA_SendFixedChnlData
1762ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1763ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description     Write data on a fixed channel.
1764ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1765ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:     Fixed CID
1766ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  BD Address of remote
1767ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Pointer to buffer of type BT_HDR
1768ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1769ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Return value     L2CAP_DW_SUCCESS, if data accepted
1770ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_DW_FAILED,  if error
1771ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1772ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1773a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskiuint16_t L2CA_SendFixedChnlData(uint16_t fixed_cid, const RawAddress& rem_bda,
1774911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                BT_HDR* p_buf) {
1775911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1776911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
1777911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1778c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(2) << __func__ << " BDA: " << rem_bda
1779c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" CID: 0x%04x", fixed_cid);
1780911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1781911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
1782911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    transport = BT_TRANSPORT_LE;
1783911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1784911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Check CID is valid and registered
1785911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((fixed_cid < L2CAP_FIRST_FIXED_CHNL) ||
1786911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (fixed_cid > L2CAP_LAST_FIXED_CHNL) ||
1787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb ==
1788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       NULL)) {
1789911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CA_SendFixedChnlData()  Invalid CID: 0x%04x",
1790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                      fixed_cid);
1791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
1792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_FAILED);
1793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
17945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Fail if BT is not yet up
1796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!BTM_IsDeviceUp()) {
1797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CA_SendFixedChnlData(0x%04x) - BTU not ready",
1798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        fixed_cid);
1799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
1800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_FAILED);
1801911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1803911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // We need to have a link up
1804f9c5752344ec459def74765f512d28fa0f402168Marie Janssen  p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, transport);
1805f9c5752344ec459def74765f512d28fa0f402168Marie Janssen  if (p_lcb == NULL || p_lcb->link_state == LST_DISCONNECTING) {
1806f9c5752344ec459def74765f512d28fa0f402168Marie Janssen    /* if link is disconnecting, also report data sending failure */
1807911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CA_SendFixedChnlData(0x%04x) - no LCB", fixed_cid);
1808911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
1809911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_FAILED);
1810911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1812911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_BLE_FIXED_CHNLS_MASK peer_channel_mask;
18130b47e0a35c16f5b7d77c30ec1c095ed92ff4fd74Satya Calloji
1814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Select peer channels mask to use depending on transport
1815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (transport == BT_TRANSPORT_LE)
1816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    peer_channel_mask = l2cb.l2c_ble_fixed_chnls_mask;
1817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  else
1818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    peer_channel_mask = p_lcb->peer_chnl_mask[0];
18190b47e0a35c16f5b7d77c30ec1c095ed92ff4fd74Satya Calloji
1820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((peer_channel_mask & (1 << fixed_cid)) == 0) {
1821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
1822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CA_SendFixedChnlData() - peer does not support fixed chnl: 0x%04x",
1823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        fixed_cid);
1824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
1825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_FAILED);
1826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->event = 0;
1829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_buf->layer_specific = L2CAP_FLUSHABLE_CH_BASED;
18305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]) {
1832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!l2cu_initialize_fixed_ccb(
1833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            p_lcb, fixed_cid,
1834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            &l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL]
1835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                 .fixed_chnl_opts)) {
1836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      L2CAP_TRACE_WARNING("L2CA_SendFixedChnlData() - no CCB for chnl: 0x%4x",
1837911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                          fixed_cid);
1838911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      osi_free(p_buf);
1839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      return (L2CAP_DW_FAILED);
18405738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
1841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1843911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // If already congested, do not accept any more packets
1844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent) {
1845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR(
1846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CAP - CID: 0x%04x cannot send, already congested \
1847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson            xmit_hold_q.count: %u buff_quota: %u",
1848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        fixed_cid, fixed_queue_length(
1849911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                       p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]
1850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           ->xmit_hold_q),
1851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->buff_quota);
1852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
1853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_FAILED);
1854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
185517b04bd498405f2bb109a85562ebbdcb6bb06e95Andre Eisenbach
1856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_enqueue_peer_data(p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL],
1857911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        p_buf);
18585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1859911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2c_link_check_send_pkts(p_lcb, NULL, NULL);
18605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1861911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // If there is no dynamic CCB on the link, restart the idle timer each time
1862911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // something is sent
1863911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->in_use && p_lcb->link_state == LST_CONNECTED &&
1864911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !p_lcb->ccb_queue.p_first_ccb) {
1865911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_no_dynamic_ccbs(p_lcb);
1866911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
18675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1868911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent)
1869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (L2CAP_DW_CONGESTED);
187017b04bd498405f2bb109a85562ebbdcb6bb06e95Andre Eisenbach
1871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (L2CAP_DW_SUCCESS);
18725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
18735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
18745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1875ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1876ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Function        L2CA_RemoveFixedChnl
1877ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1878ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Description     Remove a fixed channel to a remote device.
1879ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1880ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Parameters:     Fixed CID
1881ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  BD Address of remote
1882ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  Idle timeout to use (or 0xFFFF if don't care)
1883ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1884ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *  Return value:   true if channel removed
1885ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1886ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1887a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_RemoveFixedChnl(uint16_t fixed_cid, const RawAddress& rem_bda) {
1888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1889911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
1890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
1891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Check CID is valid and registered */
1893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((fixed_cid < L2CAP_FIRST_FIXED_CHNL) ||
1894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (fixed_cid > L2CAP_LAST_FIXED_CHNL) ||
1895911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb ==
1896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       NULL)) {
1897911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("L2CA_RemoveFixedChnl()  Invalid CID: 0x%04x", fixed_cid);
1898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1899911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19005738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1901911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
1902911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    transport = BT_TRANSPORT_LE;
19037fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
1904911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Is a fixed channel connected to the remote BDA ?*/
1905911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, transport);
19067fa4fba6f59f97df00aff07dbe8fb21b114b3c2cGanesh Ganapathi Batta
1907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((p_lcb) == NULL) ||
1908911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL])) {
1909c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    LOG(WARNING) << __func__ << " BDA: " << rem_bda
1910c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                 << StringPrintf(" CID: 0x%04x not connected", fixed_cid);
1911911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1912911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1914c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski  VLOG(2) << __func__ << " BDA: " << rem_bda
1915c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski          << StringPrintf(" CID: 0x%04x", fixed_cid);
19165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Release the CCB, starting an inactivity timeout on the LCB if no other CCBs
1918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson   * exist */
1919911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL];
19205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = NULL;
1922911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->disc_reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
192348db2d254997a69f8709e94c55607732e7772436Andre Eisenbach
1924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Retain the link for a few more seconds after SMP pairing is done, since
1925911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // the Android platform always does service discovery after pairing is
1926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // complete. This will avoid the link down (pairing is complete) and an
1927911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // immediate re-connection for service discovery.
1928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // Some devices do not do auto advertising when link is dropped, thus fail
1929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  // the second connection and service discovery.
1930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((fixed_cid == L2CAP_ATT_CID) && !p_lcb->ccb_queue.p_first_ccb)
1931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    p_lcb->idle_timeout = 0;
1932d9663b2d7ab5457cb9ab6fe39dcadb191e8f1012Pradeep Panigrahi
1933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_release_ccb(p_ccb);
19345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1935911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
19365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetFixedChannelTout
1941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to set the idle timeout for
19439ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  a fixed channel. The "idle timeout" is the amount of time
19449ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  that a connection can remain up with no L2CAP channels on
19459ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  it. A timeout of zero means that the connection will be torn
1946ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  down immediately when the last channel is removed.
1947ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  A timeout of 0xFFFF means no timeout. Values are in seconds.
1948b7b747369200c0c6588e3099cedc6cfc454e14e0Jakub Pawlowski *                  A bd_addr is the remote BD address.
1949ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1950ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if command succeeded, false if failed
1951ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1952ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1953a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_SetFixedChannelTout(const RawAddress& rem_bda, uint16_t fixed_cid,
1954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              uint16_t idle_tout) {
1955911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
1956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
1957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1958911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (fixed_cid >= L2CAP_ATT_CID && fixed_cid <= L2CAP_SMP_CID)
1959911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    transport = BT_TRANSPORT_LE;
1960911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
1961911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Is a fixed channel connected to the remote BDA ?*/
1962911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, transport);
1963911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (((p_lcb) == NULL) ||
1964911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (!p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL])) {
1965c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski    LOG(WARNING) << __func__ << " BDA: " << rem_bda
1966c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski                 << StringPrintf(" CID: 0x%04x not connected", fixed_cid);
1967911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
1968911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]
1971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      ->fixed_chnl_idle_tout = idle_tout;
19725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_lcb->in_use && p_lcb->link_state == LST_CONNECTED &&
1974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      !p_lcb->ccb_queue.p_first_ccb) {
1975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* If there are no dynamic CCBs, (re)start the idle timer in case we changed
1976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson     * it */
1977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    l2cu_no_dynamic_ccbs(p_lcb);
1978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
19795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
19815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
19825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif /* #if (L2CAP_NUM_FIXED_CHNLS > 0) */
19845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
19855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1986ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1987ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function     L2CA_GetCurrentConfig
1988ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1989ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description  This function returns configurations of L2CAP channel
1990ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              pp_our_cfg : pointer of our saved configuration options
1991ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              p_our_cfg_bits : valid config in bitmap
1992ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              pp_peer_cfg: pointer of peer's saved configuration options
1993ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              p_peer_cfg_bits : valid config in bitmap
1994ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1995ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns      true if successful
1996ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
1997ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1998911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_GetCurrentConfig(uint16_t lcid, tL2CAP_CFG_INFO** pp_our_cfg,
1999911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           tL2CAP_CH_CFG_BITS* p_our_cfg_bits,
2000911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           tL2CAP_CFG_INFO** pp_peer_cfg,
2001911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                           tL2CAP_CH_CFG_BITS* p_peer_cfg_bits) {
2002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_GetCurrentConfig()  CID: 0x%04x", lcid);
2005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
2007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2008911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb) {
2009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *pp_our_cfg = &(p_ccb->our_cfg);
2010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    /* convert valid config items into bitmap */
2012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *p_our_cfg_bits = 0;
2013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.mtu_present) *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_MTU;
2014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.qos_present) *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_QOS;
2015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.flush_to_present)
2016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_FLUSH_TO;
2017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.fcr_present) *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_FCR;
2018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.fcs_present) *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_FCS;
2019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.ext_flow_spec_present)
2020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      *p_our_cfg_bits |= L2CAP_CH_CFG_MASK_EXT_FLOW_SPEC;
2021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *pp_peer_cfg = &(p_ccb->peer_cfg);
2023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *p_peer_cfg_bits = p_ccb->peer_cfg_bits;
2024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return true;
2026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_ERROR("No CCB for CID:0x%04x", lcid);
2028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return false;
2029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
20305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2033ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2034ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function      L2CA_GetConnectionConfig
2035ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2036ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description  This function returns configurations of L2CAP channel
2037ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              pp_l2c_ccb : pointer to this channels L2CAP ccb data.
2038ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2039ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns      true if successful
2040ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2041ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2042911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_GetConnectionConfig(uint16_t lcid, uint16_t* mtu, uint16_t* rcid,
2043911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              uint16_t* handle) {
2044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
2045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  ;
204647b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule
2047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("%s CID: 0x%04x", __func__, lcid);
204847b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule
2049911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb) {
2050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *mtu = L2CAP_MTU_SIZE;
2051911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_ccb->our_cfg.mtu_present) *mtu = p_ccb->our_cfg.mtu;
205247b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule
2053911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *rcid = p_ccb->remote_cid;
2054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    *handle = p_ccb->p_lcb->handle;
2055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return true;
2056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
205747b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule
2058911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_ERROR("%s No CCB for CID:0x%04x", __func__, lcid);
2059911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return false;
206047b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule}
206147b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule
206247b4310e6aa9a508b47e6cd4631327c53b464440Abhijit Adsule/*******************************************************************************
2063ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2064ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_RegForNoCPEvt
2065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Register callback for Number of Completed Packets event.
2067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Input Param      p_cb - callback for Number of completed packets event
2069ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  p_bda - BT address of remote device
2070ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2071ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if registered OK, else false
2072ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2073ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2074a484a888196ddf8bcbf1ad3226d6451bc735a94bJakub Pawlowskibool L2CA_RegForNoCPEvt(tL2CA_NOCP_CB* p_cb, const RawAddress& p_bda) {
2075911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
20765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the link that is associated with this remote bdaddr */
2078911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_BR_EDR);
20795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If no link for this handle, nothing to do. */
2081911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (!p_lcb) return false;
20825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2083911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_lcb->p_nocp_cb = p_cb;
20845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return true;
20865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
20875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
20885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_DataWrite
2091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2092ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to write data.
2093ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2094ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          L2CAP_DW_SUCCESS, if data accepted, else false
20959ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  L2CAP_DW_CONGESTED, if data accepted and the channel is
20969ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      congested
2097ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_DW_FAILED, if error
2098ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2099ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
2101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_DataWrite()  CID: 0x%04x  Len: %d", cid, p_data->len);
2102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return l2c_data_write(cid, p_data, L2CAP_FLUSHABLE_CH_BASED);
21035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2106ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2107ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_SetChnlFlushability
2108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to set a channels
2110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  flushability flags
2111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2112ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          true if CID found, else false
2113ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2114ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2115911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool L2CA_SetChnlFlushability(uint16_t cid, bool is_flushable) {
21165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
21175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2118911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
21195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2120911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Find the channel control block. We don't know the link it is on. */
2121911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, cid);
2122911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb == NULL) {
2123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_SetChnlFlushability, CID: %d",
2124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                        cid);
2125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (false);
2126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb->is_flushable = is_flushable;
21295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_SetChnlFlushability()  CID: 0x%04x  is_flushable: %d",
2131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  cid, is_flushable);
21325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
21345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (true);
21365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function         L2CA_DataWriteEx
2141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description      Higher layers call this function to write data with extended
2143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  flags.
2144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  flags : L2CAP_FLUSHABLE_CH_BASED
2145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                          L2CAP_FLUSHABLE_PKT
2146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                          L2CAP_NON_FLUSHABLE_PKT
2147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns          L2CAP_DW_SUCCESS, if data accepted, else false
21499ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                  L2CAP_DW_CONGESTED, if data accepted and the channel is
21509ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson *                                      congested
2151ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *                  L2CAP_DW_FAILED, if error
2152ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2153ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2154911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint8_t L2CA_DataWriteEx(uint16_t cid, BT_HDR* p_data, uint16_t flags) {
2155911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_API("L2CA_DataWriteEx()  CID: 0x%04x  Len: %d Flags:0x%04X", cid,
2156911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                  p_data->len, flags);
2157911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return l2c_data_write(cid, p_data, flags);
21585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
21595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
21605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2161ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2162ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function     L2CA_FlushChannel
2163ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2164ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description  This function flushes none, some or all buffers queued up
2165ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              for xmission for a particular CID. If called with
2166ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              L2CAP_FLUSH_CHANS_GET (0), it simply returns the number
2167ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              of buffers queued for that CID L2CAP_FLUSH_CHANS_ALL (0xffff)
2168ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              flushes all buffers.  All other values specifies the maximum
2169ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *              buffers to flush.
2170ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2171ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns      Number of buffers left queued for that CID
2172ee96a3c60fca590d38025925c072d264e06493c4Myles Watson *
2173ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t L2CA_FlushChannel(uint16_t lcid, uint16_t num_to_flush) {
2175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_CCB* p_ccb;
2176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  tL2C_LCB* p_lcb;
2177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  uint16_t num_left = 0, num_flushed1 = 0, num_flushed2 = 0;
21785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2179911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  p_ccb = l2cu_find_ccb_by_cid(NULL, lcid);
2180911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2181f9c5752344ec459def74765f512d28fa0f402168Marie Janssen  if (!p_ccb || (p_ccb->p_lcb == NULL)) {
2182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_WARNING(
2183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CA_FlushChannel()  abnormally returning 0  CID: 0x%04x", lcid);
2184911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    return (0);
2185911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
2186f9c5752344ec459def74765f512d28fa0f402168Marie Janssen  p_lcb = p_ccb->p_lcb;
2187911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (num_to_flush != L2CAP_FLUSH_CHANS_GET) {
2189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_API(
2190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "L2CA_FlushChannel (FLUSH)  CID: 0x%04x  NumToFlush: %d  QC: %u  "
2191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        "pFirst: 0x%08x",
2192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        lcid, num_to_flush, fixed_queue_length(p_ccb->xmit_hold_q),
2193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        fixed_queue_try_peek_first(p_ccb->xmit_hold_q));
2194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  } else {
2195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    L2CAP_TRACE_API("L2CA_FlushChannel (QUERY)  CID: 0x%04x", lcid);
2196911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
21975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Cannot flush eRTM buffers once they have a sequence number */
2199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) {
2200d19e0785e662e640191a075eda07acce61c2aedaMarie Janssen#if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
2201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (num_to_flush != L2CAP_FLUSH_CHANS_GET) {
2202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      /* If the controller supports enhanced flush, flush the data queued at the
2203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       * controller */
2204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((HCI_NON_FLUSHABLE_PB_SUPPORTED(BTM_ReadLocalFeatures())) &&
2205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          (BTM_GetNumScoLinks() == 0)) {
2206b749ebde2c6a55569e4e480abda3a4ee3afe2d72Myles Watson        if (!l2cb.is_flush_active) {
2207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          l2cb.is_flush_active = true;
2208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson
2209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          /* The only packet type defined - 0 - Automatically-Flushable Only */
2210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson          btsnd_hcic_enhanced_flush(p_lcb->handle, 0);
22115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project        }
2212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
2213911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    }
22145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
22155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // Iterate though list and flush the amount requested from
2217911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    // the transmit data queue that satisfy the layer and event conditions.
2218911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    for (const list_node_t* node = list_begin(p_lcb->link_xmit_data_q);
2219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson         (num_to_flush > 0) && node != list_end(p_lcb->link_xmit_data_q);) {
2220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      BT_HDR* p_buf = (BT_HDR*)list_node(node);
2221911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      node = list_next(node);
2222911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if ((p_buf->layer_specific == 0) && (p_buf->event == lcid)) {
2223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        num_to_flush--;
2224911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        num_flushed1++;
22255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        list_remove(p_lcb->link_xmit_data_q, p_buf);
2227cceb430489a70add1b996d54289867c17f4ac0fdPavlin Radoslavov        osi_free(p_buf);
2228911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      }
22295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
2230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2232911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If needed, flush buffers in the CCB xmit hold queue */
2233911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  while ((num_to_flush != 0) && (!fixed_queue_is_empty(p_ccb->xmit_hold_q))) {
2234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    BT_HDR* p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->xmit_hold_q);
2235911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    osi_free(p_buf);
2236911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    num_to_flush--;
2237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    num_flushed2++;
2238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If app needs to track all packets, call him */
2241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if ((p_ccb->p_rcb) && (p_ccb->p_rcb->api.pL2CA_TxComplete_Cb) &&
2242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      (num_flushed2))
2243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    (*p_ccb->p_rcb->api.pL2CA_TxComplete_Cb)(p_ccb->local_cid, num_flushed2);
22445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2245911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Now count how many are left */
2246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  for (const list_node_t* node = list_begin(p_lcb->link_xmit_data_q);
2247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson       node != list_end(p_lcb->link_xmit_data_q); node = list_next(node)) {
2248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    BT_HDR* p_buf = (BT_HDR*)list_node(node);
2249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (p_buf->event == lcid) num_left++;
2250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  }
22515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Add in the number in the CCB xmit queue */
2253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  num_left += fixed_queue_length(p_ccb->xmit_hold_q);
22545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* Return the local number of buffers left for the CID */
2256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  L2CAP_TRACE_DEBUG("L2CA_FlushChannel()  flushed: %u + %u,  num_left: %u",
2257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                    num_flushed1, num_flushed2, num_left);
22585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  /* If we were congested, and now we are not, tell the app */
2260911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  l2cu_check_channel_congestion(p_ccb);
22615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  return (num_left);
22635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2264