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