18372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/****************************************************************************** 28372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * 38372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * Copyright (C) 2009-2013 Broadcom Corporation 48372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * 58372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * Licensed under the Apache License, Version 2.0 (the "License"); 68372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * you may not use this file except in compliance with the License. 78372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * You may obtain a copy of the License at: 88372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * 98372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * http://www.apache.org/licenses/LICENSE-2.0 108372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * 118372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * Unless required by applicable law or agreed to in writing, software 128372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * distributed under the License is distributed on an "AS IS" BASIS, 138372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * See the License for the specific language governing permissions and 158372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * limitations under the License. 168372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz * 178372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz ******************************************************************************/ 188372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 190f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski#include <base/strings/stringprintf.h> 20911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <string.h> 218372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz#include "bt_target.h" 228372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz#include "bt_utils.h" 234dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#include "btm_int.h" 248372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz#include "btu.h" 254dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#include "gap_api.h" 268372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz#include "l2c_int.h" 27911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include "l2cdefs.h" 284dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#include "osi/include/fixed_queue.h" 291eb1ea0cf2da992a3193506806e571dcbe3ec947Pavlin Radoslavov#include "osi/include/mutex.h" 308372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 310f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowskiusing base::StringPrintf; 320f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski 334dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski/* Define the GAP Connection Control Block */ 344dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowskitypedef struct { 354dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_IDLE 0 364dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_LISTENING 1 374dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_CONN_SETUP 2 384dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_CFG_SETUP 3 394dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_WAIT_SEC 4 404dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_STATE_CONNECTED 5 414dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint8_t con_state; 424dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 434dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_FLAGS_IS_ORIG 0x01 444dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02 454dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_FLAGS_MY_CFG_DONE 0x04 464dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_FLAGS_SEC_DONE 0x08 474dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski#define GAP_CCB_FLAGS_CONN_DONE 0x0E 484dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint8_t con_flags; 494dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 504dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint8_t service_id; /* Used by BTM */ 514dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint16_t gap_handle; /* GAP handle */ 524dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint16_t connection_id; /* L2CAP CID */ 534dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski bool rem_addr_specified; 544dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint8_t chan_mode_mask; /* Supported channel modes (FCR) */ 559e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski RawAddress rem_dev_address; 564dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint16_t psm; 574dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint16_t rem_mtu_size; 584dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 594dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski bool is_congested; 604dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski fixed_queue_t* tx_queue; /* Queue of buffers waiting to be sent */ 614dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski fixed_queue_t* rx_queue; /* Queue of buffers waiting to be read */ 624dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 634dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski uint32_t rx_queue_size; /* Total data count in rx_queue */ 644dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 654dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tGAP_CONN_CALLBACK* p_callback; /* Users callback function */ 664dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 674dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tL2CAP_CFG_INFO cfg; /* Configuration */ 684dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tL2CAP_ERTM_INFO ertm_info; /* Pools and modes for ertm */ 694dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tBT_TRANSPORT transport; /* Transport channel BR/EDR or BLE */ 704dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tL2CAP_LE_CFG_INFO local_coc_cfg; /* local configuration for LE Coc */ 714dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tL2CAP_LE_CFG_INFO peer_coc_cfg; /* local configuration for LE Coc */ 724dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski} tGAP_CCB; 734dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 744dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowskitypedef struct { 754dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */ 764dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS]; 774dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski} tGAP_CONN; 784dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 794dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowskinamespace { 804dfce229dedc81c448042b8848ca7e11de4ed2edJakub PawlowskitGAP_CONN conn; 814dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski} 824dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 83ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/ 849ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson/* L O C A L F U N C T I O N P R O T O T Y P E S */ 85ee96a3c60fca590d38025925c072d264e06493c4Myles Watson/******************************************************************************/ 869e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskistatic void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid, 87c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski uint16_t psm, uint8_t l2cap_id); 88911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result); 89911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg); 90911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg); 91911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed); 92911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg); 93911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_congestion_ind(uint16_t lcid, bool is_congested); 94911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent); 95911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 96911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid); 97911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle); 98911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_allocate_ccb(void); 99911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_release_ccb(tGAP_CCB* p_ccb); 100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_checks_con_flags(tGAP_CCB* p_ccb); 1018372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1028372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 103ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 104ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_conn_init 105ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1069ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description This function is called to initialize GAP connection 1079ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * management 108ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 109ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 110ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 111ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 112911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid gap_conn_init(void) { 1134dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski memset(&conn, 0, sizeof(tGAP_CONN)); 1144dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; 1154dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm; 1164dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConnectPnd_Cb = NULL; 1174dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind; 1184dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm; 1194dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind; 1204dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL; 1214dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL; 1224dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind; 1234dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind; 1244dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind; 1258372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 1268372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1278372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 128ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 129ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnOpen 130ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 131ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called to open an L2CAP connection. 132ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 133ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: is_server - If true, the connection is not created 134ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * but put into a "listen" mode waiting for 135ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * the remote side to connect. 136ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 137ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * service_id - Unique service ID from 138ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * BTM_SEC_SERVICE_FIRST_EMPTY (6) 139ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to BTM_SEC_MAX_SERVICE_RECORDS (32) 140ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 141ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_rem_bda - Pointer to remote BD Address. 142ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If a server, and we don't care about the 143ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * remote BD Address, then NULL should be passed. 144ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 145ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * psm - the PSM used for the connection 146ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 147ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_config - Optional pointer to configuration structure. 148ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * If NULL, the default GAP configuration will 149ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * be used. 150ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 151ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * security - security flags 1529ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, 1539ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * GAP_FCR_CHAN_OPT_ERTM, 154ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_FCR_CHAN_OPT_STREAM) 155ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 156ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_cb - Pointer to callback function for events. 157ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1589ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns handle of the connection if successful, else 1599ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * GAP_INVALID_HANDLE 160ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 161ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 162911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id, 1639e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski bool is_server, const RawAddress* p_rem_bda, uint16_t psm, 1649e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski tL2CAP_CFG_INFO* p_cfg, tL2CAP_ERTM_INFO* ertm_info, 1659e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski uint16_t security, uint8_t chan_mode_mask, 1669e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski tGAP_CONN_CALLBACK* p_cb, tBT_TRANSPORT transport) { 167911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 168911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t cid; 169911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1700f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << "GAP_CONN - Open Request"; 171911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 172911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Allocate a new CCB. Return if none available. */ 173911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_allocate_ccb(); 174911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (GAP_INVALID_HANDLE); 175911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 176911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* update the transport */ 177911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->transport = transport; 178911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1794023c6731d5e991c6202d4e499b9dd43d642fb3cMyles Watson /* The service_id must be set before calling gap_release_ccb(). */ 1804023c6731d5e991c6202d4e499b9dd43d642fb3cMyles Watson p_ccb->service_id = service_id; 1814023c6731d5e991c6202d4e499b9dd43d642fb3cMyles Watson 182911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If caller specified a BD address, save it */ 183911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rem_bda) { 184aaa50649b95c0ab2cd84e67fab77596bbb24d095Jakub Pawlowski /* the bd addr is not RawAddress::kAny, then a bd address was specified */ 185aaa50649b95c0ab2cd84e67fab77596bbb24d095Jakub Pawlowski if (*p_rem_bda != RawAddress::kAny) p_ccb->rem_addr_specified = true; 186911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 187c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski p_ccb->rem_dev_address = *p_rem_bda; 188911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (!is_server) { 189911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* remore addr is not specified and is not a server -> bad */ 190911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 191911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 192911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 193911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* A client MUST have specified a bd addr to connect with */ 194911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb->rem_addr_specified && !is_server) { 195911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 1964dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski LOG(ERROR) 1974dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski << "GAP ERROR: Client must specify a remote BD ADDR to connect to!"; 198911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 199911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 200911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 201911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if configuration was specified */ 202911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg) p_ccb->cfg = *p_cfg; 203911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 204911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Configure L2CAP COC, if transport is LE */ 205911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (transport == BT_TRANSPORT_LE) { 206911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT; 207911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_coc_cfg.mtu = p_cfg->mtu; 208911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->local_coc_cfg.mps = L2CAP_LE_DEFAULT_MPS; 209911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 210911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 211911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback = p_cb; 212911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 213a66ea61996dfea52c2340877f4e3926ad850e48fJakub Pawlowski /* If originator, use a dynamic PSM */ 214911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!is_server) 2154dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConnectInd_Cb = NULL; 216911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 2174dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind; 2188372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 219911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Register the PSM with L2CAP */ 220911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (transport == BT_TRANSPORT_BR_EDR) { 2214dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski p_ccb->psm = L2CA_REGISTER( 2224dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE); 223911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->psm == 0) { 2244dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__, 2254dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski psm); 226911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 227911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 2286721232129f137ab024d9b95fc1094a714bc4c01Navin Kochar } 229911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 230911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 231911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (transport == BT_TRANSPORT_LE) { 2324dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski p_ccb->psm = L2CA_REGISTER_COC( 2334dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE); 234911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->psm == 0) { 2354dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__, 2364dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski psm); 237911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 238911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 2398372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 240911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 241911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 242911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Register with Security Manager for the specific security level */ 243911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!BTM_SetSecurityLevel((uint8_t)!is_server, p_serv_name, p_ccb->service_id, 244911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson security, p_ccb->psm, 0, 0)) { 2450f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski LOG(ERROR) << "GAP_CONN - Security Error"; 246911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 247911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 248911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 249911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 250911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Fill in eL2CAP parameter data */ 251911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->cfg.fcr_present) { 252911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ertm_info == NULL) { 253911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode; 254911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE; 255911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE; 256911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE; 257911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE; 258911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 259911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info = *ertm_info; 2608372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 261911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 262911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 263911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* optional FCR channel modes */ 264911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ertm_info != NULL) { 265911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.allowed_modes = 266911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (chan_mode_mask) ? chan_mode_mask : (uint8_t)L2CAP_FCR_CHAN_OPT_BASIC; 267911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 268911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 269911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (is_server) { 270911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= 271911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */ 272911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_LISTENING; 273911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb->gap_handle); 274911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 275911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* We are the originator of this connection */ 276911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG; 277911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 278911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Transition to the next appropriate state, waiting for connection confirm. 279911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 280911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP; 281911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 282911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* mark security done flag, when security is not required */ 283911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | 284911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BTM_SEC_OUT_ENCRYPT)) == 0) 285911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 286911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 287911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if L2CAP started the connection process */ 288911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR)) { 289c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski cid = L2CA_CONNECT_REQ(p_ccb->psm, *p_rem_bda, &p_ccb->ertm_info); 290911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (cid != 0) { 291911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->connection_id = cid; 292911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb->gap_handle); 293911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 2948372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 2958372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 296911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_rem_bda && (transport == BT_TRANSPORT_LE)) { 297c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski cid = L2CA_CONNECT_COC_REQ(p_ccb->psm, *p_rem_bda, &p_ccb->local_coc_cfg); 298911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (cid != 0) { 299911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->connection_id = cid; 3008372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz return (p_ccb->gap_handle); 301911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3028372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 3038372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 304911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 305911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_INVALID_HANDLE); 306911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 307911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 3088372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 3098372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 310ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 311ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnClose 312ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 313ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called to close a connection. 314ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 3159ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Parameters: handle - Handle of the connection returned by GAP_ConnOpen 316ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 317ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - closed OK 318ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 319ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 320ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 321911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnClose(uint16_t gap_handle) { 322911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 3238372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 3240f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_CONN - close handle: 0x%x", gap_handle); 3258372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 326911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb) { 327911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check if we have a connection ID */ 328911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state != GAP_CCB_STATE_LISTENING) 329911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_DISCONNECT_REQ(p_ccb->connection_id); 3308372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 331911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 3328372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 333911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 334911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3358372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 336911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_ERR_BAD_HANDLE); 3378372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 3388372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 3398372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 340ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 341ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnReadData 342ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 343ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Normally not GKI aware application will call this function 344ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * after receiving GAP_EVT_RXDATA event. 345ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 346ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection returned in the Open 347ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_data - Data area 348ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * max_len - Byte count requested 349ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_len - Byte count received 350ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 351ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - data read 352ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 353ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_NO_DATA_AVAIL - no data available 354ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 355ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 356911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnReadData(uint16_t gap_handle, uint8_t* p_data, 357911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_len, uint16_t* p_len) { 358911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 359911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t copy_len; 360911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 361911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return (GAP_ERR_BAD_HANDLE); 362911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 363911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len = 0; 364911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 365911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (fixed_queue_is_empty(p_ccb->rx_queue)) return (GAP_NO_DATA_AVAIL); 366911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 367911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mutex_global_lock(); 368911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 369911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (max_len) { 370911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf = 371911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson static_cast<BT_HDR*>(fixed_queue_try_peek_first(p_ccb->rx_queue)); 372911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf == NULL) break; 373911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 374911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson copy_len = (p_buf->len > max_len) ? max_len : p_buf->len; 375911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_len -= copy_len; 376911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len += copy_len; 377911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_data) { 378911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, copy_len); 379911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data += copy_len; 380911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 381911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 382911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf->len > copy_len) { 383911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset += copy_len; 384911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len -= copy_len; 385911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 3868372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 387911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue)); 388911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 3898372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 390911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size -= *p_len; 3918372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 392911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson mutex_global_unlock(); 3938372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 3940f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d", 395911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size, *p_len); 3968372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 397911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 3988372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 3998372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 4008372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 401ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 402ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_GetRxQueueCnt 403ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 404ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function return number of bytes on the rx queue. 405ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 406ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle returned in the GAP_ConnOpen 407ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_rx_queue_count - Pointer to return queue count in. 408ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 409ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 410ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 411911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonint GAP_GetRxQueueCnt(uint16_t handle, uint32_t* p_rx_queue_count) { 412911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 413911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson int rc = BT_PASS; 414911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 415911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check that handle is valid */ 416911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (handle < GAP_MAX_CONNECTIONS) { 4174dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski p_ccb = &conn.ccb_pool[handle]; 418911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 419911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) { 420911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_rx_queue_count = p_ccb->rx_queue_size; 421911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 422911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson rc = GAP_INVALID_HANDLE; 423911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 424911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson rc = GAP_INVALID_HANDLE; 4258372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 4260f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d", rc, 427911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_rx_queue_count); 4288372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 429911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (rc); 4308372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 4318372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 4328372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 433ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 434ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnBTRead 435ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 4369ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Bluetooth-aware applications will call this function after 4379ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * receiving GAP_EVT_RXDATA event. 438ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 439ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection returned in the Open 440ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * pp_buf - pointer to address of buffer with data, 441ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 442ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - data read 443ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 444ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_NO_DATA_AVAIL - no data available 445ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 446ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 447911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) { 448911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 449911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 4508372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 451911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return (GAP_ERR_BAD_HANDLE); 4528372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 453911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rx_queue); 4548372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 455911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_buf) { 456911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *pp_buf = p_buf; 4578372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size -= p_buf->len; 459911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 460911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 461911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *pp_buf = NULL; 462911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_NO_DATA_AVAIL); 463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 4648372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 4658372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 4668372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 467ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 468ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnWriteData 469ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 470ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Normally not GKI aware application will call this function 471ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * to send data to the connection. 472ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 473ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection returned in the Open 474ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_data - Data area 475ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * max_len - Byte count requested 476ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_len - Byte count received 477ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 478ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - data read 479ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 480ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_STATE - connection not established 481ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_CONGESTION - system is congested 482ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 483ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 484911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnWriteData(uint16_t gap_handle, uint8_t* p_data, 485911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t max_len, uint16_t* p_len) { 486911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 487911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 4888372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 489911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len = 0; 4908372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 491911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return (GAP_ERR_BAD_HANDLE); 4928372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 493911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) return (GAP_ERR_BAD_STATE); 4948372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 495911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (max_len) { 496911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) 497911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE); 498911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 499911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf = (BT_HDR*)osi_malloc(GAP_DATA_BUF_SIZE); 5008372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 501911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->offset = L2CAP_MIN_OFFSET; 502911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->len = 503911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len; 504911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_buf->event = BT_EVT_TO_BTU_SP_DATA; 5058372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 506911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memcpy((uint8_t*)(p_buf + 1) + p_buf->offset, p_data, p_buf->len); 5078372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 508911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson *p_len += p_buf->len; 509911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson max_len -= p_buf->len; 510911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_data += p_buf->len; 5118372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 5120f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", p_buf->len); 5138372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 514911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_ccb->tx_queue, p_buf); 515911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 5168372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 517911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->is_congested) { 518911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 519911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 5208372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 521911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Send the buffer through L2CAP */ 522911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) { 523911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf); 524a1a32078bafd5a99704db22806285293d1f3183aAndre Eisenbach 525911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (status == L2CAP_DW_CONGESTED) { 526911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_congested = true; 527911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 528911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (status != L2CAP_DW_SUCCESS) 529911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_ERR_BAD_STATE); 530911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 5318372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 532911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 533911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 5348372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 5358372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 536ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 537ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnReconfig 538ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 5399ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Description Applications can call this function to reconfigure the 5409ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * connection. 541ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 542ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection 543ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * p_cfg - Pointer to new configuration 544ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 545ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - config process started 546ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 547ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 548ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 549911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnReconfig(uint16_t gap_handle, tL2CAP_CFG_INFO* p_cfg) { 550911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 5518372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 552911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!p_ccb) return (GAP_ERR_BAD_HANDLE); 5538372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 554911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cfg = *p_cfg; 5558372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 556911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) 557911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONFIG_REQ(p_ccb->connection_id, p_cfg); 5588372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 559911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 5608372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 5618372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 5628372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 563ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 564ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnSetIdleTimeout 565ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 566ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Higher layers call this function to set the idle timeout for 5679ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * a connection, or for all future connections. The "idle 5689ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * timeout" is the amount of time that a connection can remain 5699ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * up with no L2CAP channels on it. A timeout of zero means 5709ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * that the connection will be torn down immediately when the 5719ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * last channel is removed. A timeout of 0xFFFF means no 5729ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * timeout. Values are in seconds. 573ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 574ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection 575ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * timeout - in secs 5769ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * 0 = immediate disconnect when last channel is 5779ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * removed 578ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 0xFFFF = no idle timeout 579ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 580ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - config process started 581ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 582ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 583ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 584911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnSetIdleTimeout(uint16_t gap_handle, uint16_t timeout) { 585911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 5868372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 587911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_handle(gap_handle); 588911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (GAP_ERR_BAD_HANDLE); 5898372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 590911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (L2CA_SetIdleTimeout(p_ccb->connection_id, timeout, false)) 591911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (BT_PASS); 592911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson else 593911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (GAP_ERR_BAD_HANDLE); 5948372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 5958372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 5968372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 597ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 598ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnGetRemoteAddr 599ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 600ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called to get the remote BD address 601ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * of a connection. 602ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 6039ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Parameters: handle - Handle of the connection returned by GAP_ConnOpen 604ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 605ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns BT_PASS - closed OK 606ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * GAP_ERR_BAD_HANDLE - invalid handle 607ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 608ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 6099e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskiconst RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) { 610911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle); 611911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 612c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski DVLOG(1) << __func__ << " gap_handle = " << gap_handle; 613911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 614911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) { 615c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski DVLOG(1) << __func__ << " BDA: " << p_ccb->rem_dev_address; 616c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski return &p_ccb->rem_dev_address; 617911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 618c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski DVLOG(1) << __func__ << " return Error "; 619c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski return nullptr; 620911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 6218372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 6228372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 6238372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 624ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 625ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnGetRemMtuSize 626ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 627ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Returns the remote device's MTU size 628ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 629ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection 630ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 6319ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * Returns uint16_t - maximum size buffer that can be transmitted to 6329ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson * the peer 633ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 634ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 635911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnGetRemMtuSize(uint16_t gap_handle) { 636911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 6378372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 638911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_handle(gap_handle); 639911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (0); 6408372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 641911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb->rem_mtu_size); 6428372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 6438372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 6448372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 645ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 646ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function GAP_ConnGetL2CAPCid 647ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 648ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Returns the L2CAP channel id 649ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 650ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Parameters: handle - Handle of the connection 651ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 652ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns uint16_t - The L2CAP channel id 653ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 0, if error 654ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 655ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 656911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonuint16_t GAP_ConnGetL2CAPCid(uint16_t gap_handle) { 657911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 6588372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 659911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_handle(gap_handle); 660911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return (0); 6618372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 662911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb->connection_id); 6638372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 6648372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 6654e972d8c24ecfb808757ef5c81eb3877ebc93027Srinu Jella/******************************************************************************* 666ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 667ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_tx_connect_ind 668ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 669ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description Sends out GAP_EVT_TX_EMPTY when transmission has been 670ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * completed. 671ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 672ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 673ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 674ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 675911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent) { 676911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid); 677911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 678911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 679911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) { 6800f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("%s: GAP_EVT_TX_EMPTY", __func__); 681911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY); 682911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 6834e972d8c24ecfb808757ef5c81eb3877ebc93027Srinu Jella} 6848372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 6858372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 686ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 687ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_connect_ind 688ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 689ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function handles an inbound connection indication 690ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * from L2CAP. This is the case where we are acting as a 691ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * server. 692ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 693ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 694ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 695ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 6969e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskistatic void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid, 697c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski uint16_t psm, uint8_t l2cap_id) { 698911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 699911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 700911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 701911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* See if we have a CCB listening for the connection */ 7024dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) { 703911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) && (p_ccb->psm == psm) && 704911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson ((p_ccb->rem_addr_specified == false) || 705c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski (bd_addr == p_ccb->rem_dev_address))) 706911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 707911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 708911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (xx == GAP_MAX_CONNECTIONS) { 7100f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski LOG(WARNING) << "*******"; 7114dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski LOG(WARNING) << "WARNING: GAP Conn Indication for Unexpected Bd " 7124dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski "Addr...Disconnecting"; 7134dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski LOG(WARNING) << "*******"; 714911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 715911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Disconnect because it is an unexpected connection */ 716911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_DISCONNECT_REQ(l2cap_cid); 717911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 718911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 719911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 720911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Transition to the next appropriate state, waiting for config setup. */ 721911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 722911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP; 723911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 724911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Save the BD Address and Channel ID. */ 725c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski p_ccb->rem_dev_address = bd_addr; 726911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->connection_id = l2cap_cid; 727911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 728911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Send response to the L2CAP layer. */ 729911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 730911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONNECT_RSP(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, 731911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson &p_ccb->ertm_info); 732911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 733911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_LE) { 734911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONNECT_COC_RSP(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, 735911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CAP_CONN_OK, &p_ccb->local_coc_cfg); 736911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 737911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* get the remote coc configuration */ 738911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg); 739911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu; 740911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 741911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* configuration is not required for LE COC */ 742911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 743911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 744911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_checks_con_flags(p_ccb); 745911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 7468372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 7470f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", 748911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->connection_id); 7498372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 750911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Send a Configuration Request. */ 751911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_BR_EDR) 752911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONFIG_REQ(l2cap_cid, &p_ccb->cfg); 7538372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 7548372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 7558372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 756ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 757ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_checks_con_flags 758ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 759ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function processes the L2CAP configuration indication 760ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * event. 761ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 762ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 763ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 764ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 765911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_checks_con_flags(tGAP_CCB* p_ccb) { 7660f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << __func__ << " conn_flags:0x" << +p_ccb->con_flags; 767911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* if all the required con_flags are set, report the OPEN event now */ 768911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) { 769911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_CONNECTED; 770911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 771911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED); 772911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 7738372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 7748372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 7758372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 776ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 777ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_sec_check_complete 778ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 779ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description The function called when Security Manager finishes 780ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * verification of the service side connection 781ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 782ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 783ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 784ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 7859e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowskistatic void gap_sec_check_complete(const RawAddress*, tBT_TRANSPORT, 786c2276b06572ab6fc1f900fbb1f41087e77d47e2aJakub Pawlowski void* p_ref_data, uint8_t res) { 787911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb = (tGAP_CCB*)p_ref_data; 788911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 7890f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf( 790911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson "gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d", 791911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state, p_ccb->con_flags, res); 792911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state == GAP_CCB_STATE_IDLE) return; 793911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 794911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (res == BTM_SUCCESS) { 795911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 796911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_checks_con_flags(p_ccb); 797911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 798911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* security failed - disconnect the channel */ 799911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_DISCONNECT_REQ(p_ccb->connection_id); 800911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8018372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 8028372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 8038372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 804ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 805ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_connect_cfm 806ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 807ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function handles the connect confirm events 808ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * from L2CAP. This is the case when we are acting as a 809ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * client and have sent a connect request. 810ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 811ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 812ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 813ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 814911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result) { 815911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 816911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 817911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 818911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(l2cap_cid); 819911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 820911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 821911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* initiate security process, if needed */ 822911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 && 823911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->transport != BT_TRANSPORT_LE) { 824911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson btm_sec_mx_access_request(p_ccb->rem_dev_address, p_ccb->psm, true, 0, 0, 825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson &gap_sec_check_complete, p_ccb); 826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 827911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 828911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If the connection response contains success status, then */ 829911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Transition to the next state and startup the timer. */ 830911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((result == L2CAP_CONN_OK) && 831911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) { 832911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_BR_EDR) { 833911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP; 834911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 835911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Send a Configuration Request. */ 836911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONFIG_REQ(l2cap_cid, &p_ccb->cfg); 8378372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 8388372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 839911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->transport == BT_TRANSPORT_LE) { 840911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* get the remote coc configuration */ 841911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg); 842911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu; 8438372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 844911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* configuration is not required for LE COC */ 845911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 846911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; 848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_checks_con_flags(p_ccb); 8498372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 850911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 851911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Tell the user if he has a callback */ 852911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->p_callback) 853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 855911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 856911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 8578372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 8588372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 8598372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 860ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 861ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_config_ind 862ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 863ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function processes the L2CAP configuration indication 864ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * event. 865ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 866ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 867ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 868ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 869911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) { 870911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 871911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t local_mtu_size; 8728372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 873911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 874911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(l2cap_cid); 875911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 8768372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 877911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Remember the remote MTU size */ 8788372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 879911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) { 880911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson local_mtu_size = 881911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->ertm_info.user_tx_buf_size - sizeof(BT_HDR) - L2CAP_MIN_OFFSET; 882911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 883911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson local_mtu_size = L2CAP_MTU_SIZE; 8848372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 885911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) { 886911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rem_mtu_size = local_mtu_size; 887911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else 888911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rem_mtu_size = p_cfg->mtu; 8898372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 890911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* For now, always accept configuration from the other side */ 891911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->flush_to_present = false; 892911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->mtu_present = false; 893911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->result = L2CAP_CFG_OK; 894911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_cfg->fcs_present = false; 8958372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 896911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson L2CA_CONFIG_RSP(l2cap_cid, p_cfg); 8978372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 898911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE; 8998372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 900911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_checks_con_flags(p_ccb); 9018372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 9028372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 9038372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 904ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 905ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_config_cfm 906ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 907ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function processes the L2CAP configuration confirmation 908ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * event. 909ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 910ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 911ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 912ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 913911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) { 914911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 9158372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 916911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 917911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(l2cap_cid); 918911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 9198372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 920911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_cfg->result == L2CAP_CFG_OK) { 921911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE; 9228372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 923911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->cfg.fcr_present) 924911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cfg.fcr.mode = p_cfg->fcr.mode; 9258372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz else 926911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 9278372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 928911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_checks_con_flags(p_ccb); 929911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 930911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 931911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 932911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 933911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson} 9348372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 9358372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 936ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 937ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_disconnect_ind 938ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 939ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function handles a disconnect event from L2CAP. If 940ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * requested to, we ack the disconnect before dropping the CCB 941ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 942ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 943ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 944ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 945911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) { 946911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 9478372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 9480f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); 9498372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 950911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 951911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(l2cap_cid); 952911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 9538372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 954911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (ack_needed) L2CA_DISCONNECT_RSP(l2cap_cid); 9558372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 956911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED); 957911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson gap_release_ccb(p_ccb); 9588372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 9598372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 9608372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 961ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 962ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_data_ind 963ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 964ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function is called when data is received from L2CAP. 965ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 966ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns void 967ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 968ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 969911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) { 970911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 971911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 972911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 973911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(l2cap_cid); 974911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) { 975911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_msg); 976911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return; 977911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 978911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 979911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) { 980911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_enqueue(p_ccb->rx_queue, p_msg); 981911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 982911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size += p_msg->len; 983911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* 9840f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d", 985911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size, p_msg->len); 986911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson */ 987911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL); 989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else { 990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(p_msg); 991911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 9928372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 9938372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 9948372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 995ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 996ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_congestion_ind 997ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 998ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This is a callback function called by L2CAP when 999ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * data L2CAP congestion status changes 1000ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1001ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1002911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_congestion_ind(uint16_t lcid, bool is_congested) { 1003911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 1004911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t event; 1005911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson BT_HDR* p_buf; 1006911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint8_t status; 1007911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 10080f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x", 1009911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson is_congested, lcid); 1010911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1011911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Find CCB based on CID */ 1012911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb = gap_find_ccb_by_cid(lcid); 1013911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb == NULL) return; 1014911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1015911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_congested = is_congested; 1016911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1017911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED; 1018911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->p_callback(p_ccb->gap_handle, event); 1019911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1020911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (!is_congested) { 1021911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != 1022911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson NULL) { 1023911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf); 1024911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1025911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (status == L2CAP_DW_CONGESTED) { 1026911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->is_congested = true; 1027911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 1028911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } else if (status != L2CAP_DW_SUCCESS) 1029911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson break; 10308372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 1031911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10328372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 10338372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 10348372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 1035ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1036ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_find_ccb_by_cid 1037ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1038ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function searches the CCB table for an entry with the 1039ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * passed CID. 1040ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1041ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns the CCB address, or NULL if not found. 1042ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1043ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1044911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid) { 1045911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 1046911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 1047911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1048911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Look through each connection control block */ 10494dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) { 1050911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && 1051911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson (p_ccb->connection_id == cid)) 1052911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb); 1053911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 1054911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1055911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, not found */ 1056911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 10578372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 10588372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 10598372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 1060ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1061ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_find_ccb_by_handle 1062ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1063ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function searches the CCB table for an entry with the 1064ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * passed handle. 1065ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1066ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns the CCB address, or NULL if not found. 1067ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1068ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1069911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle) { 1070911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 10718372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1072911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Check that handle is valid */ 1073911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (handle < GAP_MAX_CONNECTIONS) { 10744dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski p_ccb = &conn.ccb_pool[handle]; 10758372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1076911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state != GAP_CCB_STATE_IDLE) return (p_ccb); 1077911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 10788372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1079911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, handle points to invalid connection */ 1080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 10818372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 10828372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 10838372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 1084ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1085ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Function gap_allocate_ccb 1086ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1087ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Description This function allocates a new CCB. 1088ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1089ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * Returns CCB address, or NULL if none available. 1090ee96a3c60fca590d38025925c072d264e06493c4Myles Watson * 1091ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/ 1092911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic tGAP_CCB* gap_allocate_ccb(void) { 1093911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson uint16_t xx; 1094911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson tGAP_CCB* p_ccb; 1095911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1096911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Look through each connection control block for a free one */ 10974dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) { 1098911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson if (p_ccb->con_state == GAP_CCB_STATE_IDLE) { 1099911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson memset(p_ccb, 0, sizeof(tGAP_CCB)); 1100911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_queue = fixed_queue_new(SIZE_MAX); 1101911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue = fixed_queue_new(SIZE_MAX); 1102911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1103911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->gap_handle = xx; 1104911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rem_mtu_size = L2CAP_MTU_SIZE; 1105911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1106911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (p_ccb); 11078372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz } 1108911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11098372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1110911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If here, no free CCB found */ 1111911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson return (NULL); 11128372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 11138372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 11148372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz/******************************************************************************* 11150ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * 11160ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * Function gap_release_ccb 11170ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * 11180ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * Description This function releases a CCB. 11190ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * 11200ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * Returns void 11210ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson * 11220ec947509d38d15b75bc899b6b7720de4c4fea4fMyles Watson ******************************************************************************/ 1123911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonstatic void gap_release_ccb(tGAP_CCB* p_ccb) { 1124911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Drop any buffers we may be holding */ 1125911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue_size = 0; 1126911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1127911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (!fixed_queue_is_empty(p_ccb->rx_queue)) 1128911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue)); 1129911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_ccb->rx_queue, NULL); 1130911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->rx_queue = NULL; 1131911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1132911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson while (!fixed_queue_is_empty(p_ccb->tx_queue)) 1133911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue)); 1134911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson fixed_queue_free(p_ccb->tx_queue, NULL); 1135911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->tx_queue = NULL; 1136911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1137911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson p_ccb->con_state = GAP_CCB_STATE_IDLE; 1138911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson 1139911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* If no-one else is using the PSM, deregister from L2CAP */ 11404dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski tGAP_CCB* p_ccb_local = conn.ccb_pool; 1141e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao for (uint16_t i = 0; i < GAP_MAX_CONNECTIONS; i++, p_ccb_local++) { 1142e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) && 1143e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao (p_ccb_local->psm == p_ccb->psm)) { 11440f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski DVLOG(1) << __func__ << " : " << +p_ccb_local->psm 11450f3d3fe65b774056940d15975fe1e565ef6245feJakub Pawlowski << " PSM is still in use, do not deregister"; 1146e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao return; 1147e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao } 1148911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson } 11498372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz 1150911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson /* Free the security record for this PSM */ 1151e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao BTM_SecClrService(p_ccb->service_id); 1152e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao if (p_ccb->transport == BT_TRANSPORT_BR_EDR) L2CA_DEREGISTER(p_ccb->psm); 1153e2866764bbdcca7bcfaafce0a659077f5feb00d1Venkata Ramana Rao if (p_ccb->transport == BT_TRANSPORT_LE) L2CA_DEREGISTER_COC(p_ccb->psm); 11548372aa5fa535ee4f09c09981b6125b54ace31fe2Kim Schulz} 11554dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 11564dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowskiextern void gap_attr_db_init(void); 11574dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski 11584dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski/* 11594dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski * This routine should not be called except once per stack invocation. 11604dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski */ 11614dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowskivoid GAP_Init(void) { 11624dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski gap_conn_init(); 11634dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski gap_attr_db_init(); 11644dfce229dedc81c448042b8848ca7e11de4ed2edJakub Pawlowski} 1165