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