blob: 399002e5ee8357f82feb01827f1b0d2218ee9663 [file] [log] [blame]
Kim Schulz8372aa52015-03-25 10:39:40 +01001/******************************************************************************
2 *
3 * Copyright (C) 2009-2013 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19
20#include "bt_target.h"
21#include "bt_utils.h"
22#include "btu.h"
23#include "gap_int.h"
24#include "l2cdefs.h"
25#include "l2c_int.h"
26#include <string.h>
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -070027#include "osi/include/mutex.h"
Marie Janssend19e0782016-07-15 12:48:27 -070028#if (GAP_CONN_INCLUDED == TRUE)
Kim Schulz8372aa52015-03-25 10:39:40 +010029#include "btm_int.h"
30
31/********************************************************************************/
32/* L O C A L F U N C T I O N P R O T O T Y P E S */
33/********************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -070034static void gap_connect_ind (BD_ADDR bd_addr, uint16_t l2cap_cid, uint16_t psm, uint8_t l2cap_id);
35static void gap_connect_cfm (uint16_t l2cap_cid, uint16_t result);
36static void gap_config_ind (uint16_t l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
37static void gap_config_cfm (uint16_t l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
38static void gap_disconnect_ind (uint16_t l2cap_cid, bool ack_needed);
39static void gap_data_ind (uint16_t l2cap_cid, BT_HDR *p_msg);
40static void gap_congestion_ind (uint16_t lcid, bool is_congested);
41static void gap_tx_complete_ind (uint16_t l2cap_cid, uint16_t sdu_sent);
Kim Schulz8372aa52015-03-25 10:39:40 +010042
Marie Janssend19e0782016-07-15 12:48:27 -070043static tGAP_CCB *gap_find_ccb_by_cid (uint16_t cid);
44static tGAP_CCB *gap_find_ccb_by_handle (uint16_t handle);
Kim Schulz8372aa52015-03-25 10:39:40 +010045static tGAP_CCB *gap_allocate_ccb (void);
46static void gap_release_ccb (tGAP_CCB *p_ccb);
Navin Kochar67212322016-03-09 23:11:53 +053047static void gap_checks_con_flags (tGAP_CCB *p_ccb);
Kim Schulz8372aa52015-03-25 10:39:40 +010048
49/*******************************************************************************
50**
51** Function gap_conn_init
52**
53** Description This function is called to initialize GAP connection management
54**
55** Returns void
56**
57*******************************************************************************/
58void gap_conn_init (void)
59{
Marie Janssend19e0782016-07-15 12:48:27 -070060#if (AMP_INCLUDED == TRUE)
Kim Schulz8372aa52015-03-25 10:39:40 +010061 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
62 gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb = gap_connect_cfm;
63 gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb = NULL;
64 gap_cb.conn.reg_info.pAMP_ConfigInd_Cb = gap_config_ind;
65 gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb = gap_config_cfm;
66 gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb = gap_disconnect_ind;
67 gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb = NULL;
68 gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb = NULL;
69 gap_cb.conn.reg_info.pAMP_DataInd_Cb = gap_data_ind;
70 gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb = gap_congestion_ind;
71 gap_cb.conn.reg_info.pAMP_TxComplete_Cb = NULL;
72 gap_cb.conn.reg_info.pAMP_MoveInd_Cb = NULL;
73 gap_cb.conn.reg_info.pAMP_MoveRsp_Cb = NULL;
74 gap_cb.conn.reg_info.pAMP_MoveCfm_Cb = NULL; //gap_move_cfm
75 gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb = NULL; //gap_move_cfm_rsp
76
77#else
78 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
79 gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
80 gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
81 gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
82 gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
83 gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
84 gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
85 gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
86 gap_cb.conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
87 gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
Srinu Jella4e972d82016-02-16 20:22:16 +053088 gap_cb.conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;
Kim Schulz8372aa52015-03-25 10:39:40 +010089#endif
90}
91
92
93/*******************************************************************************
94**
95** Function GAP_ConnOpen
96**
97** Description This function is called to open an L2CAP connection.
98**
Marie Janssend19e0782016-07-15 12:48:27 -070099** Parameters: is_server - If true, the connection is not created
Kim Schulz8372aa52015-03-25 10:39:40 +0100100** but put into a "listen" mode waiting for
101** the remote side to connect.
102**
103** service_id - Unique service ID from
104** BTM_SEC_SERVICE_FIRST_EMPTY (6)
105** to BTM_SEC_MAX_SERVICE_RECORDS (32)
106**
107** p_rem_bda - Pointer to remote BD Address.
108** If a server, and we don't care about the
109** remote BD Address, then NULL should be passed.
110**
111** psm - the PSM used for the connection
112**
113** p_config - Optional pointer to configuration structure.
114** If NULL, the default GAP configuration will
115** be used.
116**
117** security - security flags
118** chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM,
119** GAP_FCR_CHAN_OPT_STREAM)
120**
121** p_cb - Pointer to callback function for events.
122**
123** Returns handle of the connection if successful, else GAP_INVALID_HANDLE
124**
125*******************************************************************************/
Pavlin Radoslavovb2a292b2016-10-14 19:34:48 -0700126uint16_t GAP_ConnOpen(const char *p_serv_name, uint8_t service_id, bool is_server,
Marie Janssend19e0782016-07-15 12:48:27 -0700127 BD_ADDR p_rem_bda, uint16_t psm, tL2CAP_CFG_INFO *p_cfg,
128 tL2CAP_ERTM_INFO *ertm_info, uint16_t security, uint8_t chan_mode_mask,
Navin Kochar67212322016-03-09 23:11:53 +0530129 tGAP_CONN_CALLBACK *p_cb, tBT_TRANSPORT transport)
Kim Schulz8372aa52015-03-25 10:39:40 +0100130{
131 tGAP_CCB *p_ccb;
Marie Janssend19e0782016-07-15 12:48:27 -0700132 uint16_t cid;
Kim Schulz8372aa52015-03-25 10:39:40 +0100133
134 GAP_TRACE_EVENT ("GAP_CONN - Open Request");
135
136 /* Allocate a new CCB. Return if none available. */
137 if ((p_ccb = gap_allocate_ccb()) == NULL)
138 return (GAP_INVALID_HANDLE);
139
Navin Kochar67212322016-03-09 23:11:53 +0530140 /* update the transport */
141 p_ccb->transport = transport;
142
Kim Schulz8372aa52015-03-25 10:39:40 +0100143 /* If caller specified a BD address, save it */
144 if (p_rem_bda)
145 {
146 /* the bd addr is not BT_BD_ANY, then a bd address was specified */
147 if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN))
Marie Janssend19e0782016-07-15 12:48:27 -0700148 p_ccb->rem_addr_specified = true;
Kim Schulz8372aa52015-03-25 10:39:40 +0100149
150 memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
151 }
152 else if (!is_server)
153 {
154 /* remore addr is not specified and is not a server -> bad */
155 return (GAP_INVALID_HANDLE);
156 }
157
158 /* A client MUST have specified a bd addr to connect with */
159 if (!p_ccb->rem_addr_specified && !is_server)
160 {
161 gap_release_ccb (p_ccb);
162 GAP_TRACE_ERROR ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
163 return (GAP_INVALID_HANDLE);
164 }
165
166 /* Check if configuration was specified */
167 if (p_cfg)
168 p_ccb->cfg = *p_cfg;
169
Navin Kochar67212322016-03-09 23:11:53 +0530170 /* Configure L2CAP COC, if transport is LE */
171 if (transport == BT_TRANSPORT_LE)
172 {
173 p_ccb->local_coc_cfg.credits = L2CAP_LE_DEFAULT_CREDIT;
174 p_ccb->local_coc_cfg.mtu = p_cfg->mtu;
175 p_ccb->local_coc_cfg.mps = L2CAP_LE_DEFAULT_MPS;
176 }
177
Kim Schulz8372aa52015-03-25 10:39:40 +0100178 p_ccb->p_callback = p_cb;
179
180 /* If originator, use a dynamic PSM */
Marie Janssend19e0782016-07-15 12:48:27 -0700181#if (AMP_INCLUDED == TRUE)
Kim Schulz8372aa52015-03-25 10:39:40 +0100182 if (!is_server)
183 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = NULL;
184 else
185 gap_cb.conn.reg_info.pAMP_ConnectInd_Cb = gap_connect_ind;
186#else
187 if (!is_server)
188 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
189 else
190 gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
191#endif
192
193 /* Register the PSM with L2CAP */
Navin Kochar67212322016-03-09 23:11:53 +0530194 if (transport == BT_TRANSPORT_BR_EDR)
Kim Schulz8372aa52015-03-25 10:39:40 +0100195 {
Navin Kochar67212322016-03-09 23:11:53 +0530196 p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info,
197 AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE);
198 if (p_ccb->psm == 0)
199 {
200 GAP_TRACE_ERROR ("%s: Failure registering PSM 0x%04x", __func__, psm);
201 gap_release_ccb (p_ccb);
202 return (GAP_INVALID_HANDLE);
203 }
204 }
205
206 if (transport == BT_TRANSPORT_LE)
207 {
208 p_ccb->psm = L2CA_REGISTER_COC (psm, &gap_cb.conn.reg_info,
209 AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE);
210 if (p_ccb->psm == 0)
211 {
212 GAP_TRACE_ERROR ("%s: Failure registering PSM 0x%04x", __func__, psm);
213 gap_release_ccb (p_ccb);
214 return (GAP_INVALID_HANDLE);
215 }
Kim Schulz8372aa52015-03-25 10:39:40 +0100216 }
217
218 /* Register with Security Manager for the specific security level */
219 p_ccb->service_id = service_id;
Marie Janssend19e0782016-07-15 12:48:27 -0700220 if (!BTM_SetSecurityLevel ((uint8_t)!is_server, p_serv_name,
Kim Schulz8372aa52015-03-25 10:39:40 +0100221 p_ccb->service_id, security, p_ccb->psm, 0, 0))
222 {
223 GAP_TRACE_ERROR ("GAP_CONN - Security Error");
224 gap_release_ccb (p_ccb);
225 return (GAP_INVALID_HANDLE);
226 }
227
228 /* Fill in eL2CAP parameter data */
229 if( p_ccb->cfg.fcr_present )
230 {
231 if(ertm_info == NULL) {
232 p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
Pavlin Radoslavov1d5b8592015-09-23 10:08:20 -0700233 p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
234 p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
235 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
236 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
Kim Schulz8372aa52015-03-25 10:39:40 +0100237 } else {
238 p_ccb->ertm_info = *ertm_info;
239 }
240 }
241
242 /* optional FCR channel modes */
243 if(ertm_info != NULL) {
244 p_ccb->ertm_info.allowed_modes =
Marie Janssend19e0782016-07-15 12:48:27 -0700245 (chan_mode_mask) ? chan_mode_mask : (uint8_t)L2CAP_FCR_CHAN_OPT_BASIC;
Kim Schulz8372aa52015-03-25 10:39:40 +0100246 }
247
248 if (is_server)
249 {
250 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
251 p_ccb->con_state = GAP_CCB_STATE_LISTENING;
252 return (p_ccb->gap_handle);
253 }
254 else
255 {
256 /* We are the originator of this connection */
257 p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
258
259 /* Transition to the next appropriate state, waiting for connection confirm. */
260 p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
261
262 /* mark security done flag, when security is not required */
263 if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0)
264 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
265
266 /* Check if L2CAP started the connection process */
Navin Kochar67212322016-03-09 23:11:53 +0530267 if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR))
Kim Schulz8372aa52015-03-25 10:39:40 +0100268 {
Navin Kochar67212322016-03-09 23:11:53 +0530269 cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info);
270 if (cid != 0)
271 {
272 p_ccb->connection_id = cid;
273 return (p_ccb->gap_handle);
274 }
Kim Schulz8372aa52015-03-25 10:39:40 +0100275 }
Navin Kochar67212322016-03-09 23:11:53 +0530276
277 if (p_rem_bda && (transport == BT_TRANSPORT_LE))
Kim Schulz8372aa52015-03-25 10:39:40 +0100278 {
Navin Kochar67212322016-03-09 23:11:53 +0530279 cid = L2CA_CONNECT_COC_REQ (p_ccb->psm, p_rem_bda, &p_ccb->local_coc_cfg);
280 if (cid != 0)
281 {
282 p_ccb->connection_id = cid;
283 return (p_ccb->gap_handle);
284 }
Kim Schulz8372aa52015-03-25 10:39:40 +0100285 }
Navin Kochar67212322016-03-09 23:11:53 +0530286
287 gap_release_ccb (p_ccb);
288 return (GAP_INVALID_HANDLE);
Kim Schulz8372aa52015-03-25 10:39:40 +0100289 }
290}
291
292
293/*******************************************************************************
294**
295** Function GAP_ConnClose
296**
297** Description This function is called to close a connection.
298**
299** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
300**
301** Returns BT_PASS - closed OK
302** GAP_ERR_BAD_HANDLE - invalid handle
303**
304*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700305uint16_t GAP_ConnClose (uint16_t gap_handle)
Kim Schulz8372aa52015-03-25 10:39:40 +0100306{
307 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
308
309 GAP_TRACE_EVENT ("GAP_CONN - close handle: 0x%x", gap_handle);
310
311 if (p_ccb)
312 {
313 /* Check if we have a connection ID */
314 if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
315 L2CA_DISCONNECT_REQ (p_ccb->connection_id);
316
317 gap_release_ccb (p_ccb);
318
319 return (BT_PASS);
320 }
321
322 return (GAP_ERR_BAD_HANDLE);
323}
324
325
326
327/*******************************************************************************
328**
329** Function GAP_ConnReadData
330**
331** Description Normally not GKI aware application will call this function
332** after receiving GAP_EVT_RXDATA event.
333**
334** Parameters: handle - Handle of the connection returned in the Open
335** p_data - Data area
336** max_len - Byte count requested
337** p_len - Byte count received
338**
339** Returns BT_PASS - data read
340** GAP_ERR_BAD_HANDLE - invalid handle
341** GAP_NO_DATA_AVAIL - no data available
342**
343*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700344uint16_t GAP_ConnReadData (uint16_t gap_handle, uint8_t *p_data, uint16_t max_len, uint16_t *p_len)
Kim Schulz8372aa52015-03-25 10:39:40 +0100345{
346 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
Marie Janssend19e0782016-07-15 12:48:27 -0700347 uint16_t copy_len;
Kim Schulz8372aa52015-03-25 10:39:40 +0100348
349 if (!p_ccb)
350 return (GAP_ERR_BAD_HANDLE);
351
352 *p_len = 0;
353
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700354 if (fixed_queue_is_empty(p_ccb->rx_queue))
Kim Schulz8372aa52015-03-25 10:39:40 +0100355 return (GAP_NO_DATA_AVAIL);
356
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700357 mutex_global_lock();
Kim Schulz8372aa52015-03-25 10:39:40 +0100358
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700359 while (max_len)
Kim Schulz8372aa52015-03-25 10:39:40 +0100360 {
Pavlin Radoslavovb2a292b2016-10-14 19:34:48 -0700361 BT_HDR *p_buf =
362 static_cast<BT_HDR *>(fixed_queue_try_peek_first(p_ccb->rx_queue));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700363 if (p_buf == NULL)
364 break;
365
Kim Schulz8372aa52015-03-25 10:39:40 +0100366 copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
367 max_len -= copy_len;
368 *p_len += copy_len;
369 if (p_data)
370 {
Marie Janssend19e0782016-07-15 12:48:27 -0700371 memcpy (p_data, (uint8_t *)(p_buf + 1) + p_buf->offset, copy_len);
Kim Schulz8372aa52015-03-25 10:39:40 +0100372 p_data += copy_len;
373 }
374
375 if (p_buf->len > copy_len)
376 {
377 p_buf->offset += copy_len;
378 p_buf->len -= copy_len;
379 break;
380 }
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800381 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
Kim Schulz8372aa52015-03-25 10:39:40 +0100382 }
383
384 p_ccb->rx_queue_size -= *p_len;
385
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700386 mutex_global_unlock();
Kim Schulz8372aa52015-03-25 10:39:40 +0100387
388 GAP_TRACE_EVENT ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
389 p_ccb->rx_queue_size, *p_len);
390
391 return (BT_PASS);
392}
393
394/*******************************************************************************
395**
396** Function GAP_GetRxQueueCnt
397**
398** Description This function return number of bytes on the rx queue.
399**
400** Parameters: handle - Handle returned in the GAP_ConnOpen
401** p_rx_queue_count - Pointer to return queue count in.
402**
403**
404*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700405int GAP_GetRxQueueCnt (uint16_t handle, uint32_t *p_rx_queue_count)
Kim Schulz8372aa52015-03-25 10:39:40 +0100406{
407 tGAP_CCB *p_ccb;
408 int rc = BT_PASS;
409
410 /* Check that handle is valid */
411 if (handle < GAP_MAX_CONNECTIONS)
412 {
413 p_ccb = &gap_cb.conn.ccb_pool[handle];
414
415 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
416 {
417 *p_rx_queue_count = p_ccb->rx_queue_size;
418 }
419 else
420 rc = GAP_INVALID_HANDLE;
421 }
422 else
423 rc = GAP_INVALID_HANDLE;
424
425 GAP_TRACE_EVENT ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
426 rc , *p_rx_queue_count);
427
428 return (rc);
429}
430
431/*******************************************************************************
432**
433** Function GAP_ConnBTRead
434**
435** Description Bluetooth aware applications will call this function after receiving
436** GAP_EVT_RXDATA event.
437**
438** Parameters: handle - Handle of the connection returned in the Open
439** pp_buf - pointer to address of buffer with data,
440**
441** Returns BT_PASS - data read
442** GAP_ERR_BAD_HANDLE - invalid handle
443** GAP_NO_DATA_AVAIL - no data available
444**
445*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700446uint16_t GAP_ConnBTRead (uint16_t gap_handle, BT_HDR **pp_buf)
Kim Schulz8372aa52015-03-25 10:39:40 +0100447{
448 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
449 BT_HDR *p_buf;
450
451 if (!p_ccb)
452 return (GAP_ERR_BAD_HANDLE);
453
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700454 p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->rx_queue);
Kim Schulz8372aa52015-03-25 10:39:40 +0100455
456 if (p_buf)
457 {
458 *pp_buf = p_buf;
459
460 p_ccb->rx_queue_size -= p_buf->len;
461 return (BT_PASS);
462 }
463 else
464 {
465 *pp_buf = NULL;
466 return (GAP_NO_DATA_AVAIL);
467 }
468}
469
Kim Schulz8372aa52015-03-25 10:39:40 +0100470/*******************************************************************************
471**
472** Function GAP_ConnWriteData
473**
474** Description Normally not GKI aware application will call this function
475** to send data to the connection.
476**
477** Parameters: handle - Handle of the connection returned in the Open
478** p_data - Data area
479** max_len - Byte count requested
480** p_len - Byte count received
481**
482** Returns BT_PASS - data read
483** GAP_ERR_BAD_HANDLE - invalid handle
484** GAP_ERR_BAD_STATE - connection not established
485** GAP_CONGESTION - system is congested
486**
487*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700488uint16_t GAP_ConnWriteData (uint16_t gap_handle, uint8_t *p_data, uint16_t max_len, uint16_t *p_len)
Kim Schulz8372aa52015-03-25 10:39:40 +0100489{
490 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
491 BT_HDR *p_buf;
492
493 *p_len = 0;
494
495 if (!p_ccb)
496 return (GAP_ERR_BAD_HANDLE);
497
498 if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
499 return (GAP_ERR_BAD_STATE);
500
501 while (max_len)
502 {
503 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800504 p_buf = (BT_HDR *)osi_malloc(L2CAP_FCR_ERTM_BUF_SIZE);
Kim Schulz8372aa52015-03-25 10:39:40 +0100505 else
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -0800506 p_buf = (BT_HDR *)osi_malloc(GAP_DATA_BUF_SIZE);
Kim Schulz8372aa52015-03-25 10:39:40 +0100507
508 p_buf->offset = L2CAP_MIN_OFFSET;
509 p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
510 p_buf->event = BT_EVT_TO_BTU_SP_DATA;
511
Marie Janssend19e0782016-07-15 12:48:27 -0700512 memcpy ((uint8_t *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
Kim Schulz8372aa52015-03-25 10:39:40 +0100513
514 *p_len += p_buf->len;
515 max_len -= p_buf->len;
516 p_data += p_buf->len;
517
518 GAP_TRACE_EVENT ("GAP_WriteData %d bytes", p_buf->len);
519
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700520 fixed_queue_enqueue(p_ccb->tx_queue, p_buf);
Kim Schulz8372aa52015-03-25 10:39:40 +0100521 }
522
523 if (p_ccb->is_congested)
524 {
525 return (BT_PASS);
526 }
527
528 /* Send the buffer through L2CAP */
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -0700529 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL)
Kim Schulz8372aa52015-03-25 10:39:40 +0100530 {
Marie Janssend19e0782016-07-15 12:48:27 -0700531 uint8_t status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
Kim Schulz8372aa52015-03-25 10:39:40 +0100532
533 if (status == L2CAP_DW_CONGESTED)
534 {
Marie Janssend19e0782016-07-15 12:48:27 -0700535 p_ccb->is_congested = true;
Kim Schulz8372aa52015-03-25 10:39:40 +0100536 break;
537 }
538 else if (status != L2CAP_DW_SUCCESS)
539 return (GAP_ERR_BAD_STATE);
540 }
Andre Eisenbacha1a320782016-10-18 11:58:57 -0700541
Kim Schulz8372aa52015-03-25 10:39:40 +0100542 return (BT_PASS);
543}
544
545
546/*******************************************************************************
547**
548** Function GAP_ConnReconfig
549**
550** Description Applications can call this function to reconfigure the connection.
551**
552** Parameters: handle - Handle of the connection
553** p_cfg - Pointer to new configuration
554**
555** Returns BT_PASS - config process started
556** GAP_ERR_BAD_HANDLE - invalid handle
557**
558*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700559uint16_t GAP_ConnReconfig (uint16_t gap_handle, tL2CAP_CFG_INFO *p_cfg)
Kim Schulz8372aa52015-03-25 10:39:40 +0100560{
561 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
562
563 if (!p_ccb)
564 return (GAP_ERR_BAD_HANDLE);
565
566 p_ccb->cfg = *p_cfg;
567
568 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
569 L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
570
571 return (BT_PASS);
572}
573
574
575
576/*******************************************************************************
577**
578** Function GAP_ConnSetIdleTimeout
579**
580** Description Higher layers call this function to set the idle timeout for
581** a connection, or for all future connections. The "idle timeout"
582** is the amount of time that a connection can remain up with
583** no L2CAP channels on it. A timeout of zero means that the
584** connection will be torn down immediately when the last channel
585** is removed. A timeout of 0xFFFF means no timeout. Values are
586** in seconds.
587**
588** Parameters: handle - Handle of the connection
589** timeout - in secs
590** 0 = immediate disconnect when last channel is removed
591** 0xFFFF = no idle timeout
592**
593** Returns BT_PASS - config process started
594** GAP_ERR_BAD_HANDLE - invalid handle
595**
596*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700597uint16_t GAP_ConnSetIdleTimeout (uint16_t gap_handle, uint16_t timeout)
Kim Schulz8372aa52015-03-25 10:39:40 +0100598{
599 tGAP_CCB *p_ccb;
600
601 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
602 return (GAP_ERR_BAD_HANDLE);
603
Marie Janssend19e0782016-07-15 12:48:27 -0700604 if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, false))
Kim Schulz8372aa52015-03-25 10:39:40 +0100605 return (BT_PASS);
606 else
607 return (GAP_ERR_BAD_HANDLE);
608}
609
610
611
612/*******************************************************************************
613**
614** Function GAP_ConnGetRemoteAddr
615**
616** Description This function is called to get the remote BD address
617** of a connection.
618**
619** Parameters: handle - Handle of the connection returned by GAP_ConnOpen
620**
621** Returns BT_PASS - closed OK
622** GAP_ERR_BAD_HANDLE - invalid handle
623**
624*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700625uint8_t *GAP_ConnGetRemoteAddr (uint16_t gap_handle)
Kim Schulz8372aa52015-03-25 10:39:40 +0100626{
627 tGAP_CCB *p_ccb = gap_find_ccb_by_handle (gap_handle);
628
629 GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
630
631 if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING))
632 {
633 GAP_TRACE_EVENT("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
634 p_ccb->rem_dev_address[0],p_ccb->rem_dev_address[1],p_ccb->rem_dev_address[2],
635 p_ccb->rem_dev_address[3],p_ccb->rem_dev_address[4],p_ccb->rem_dev_address[5]);
636 return (p_ccb->rem_dev_address);
637 }
638 else
639 {
640 GAP_TRACE_EVENT ("GAP_ConnGetRemoteAddr return Error ");
641 return (NULL);
642 }
643}
644
645
646/*******************************************************************************
647**
648** Function GAP_ConnGetRemMtuSize
649**
650** Description Returns the remote device's MTU size
651**
652** Parameters: handle - Handle of the connection
653**
Marie Janssend19e0782016-07-15 12:48:27 -0700654** Returns uint16_t - maximum size buffer that can be transmitted to the peer
Kim Schulz8372aa52015-03-25 10:39:40 +0100655**
656*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700657uint16_t GAP_ConnGetRemMtuSize (uint16_t gap_handle)
Kim Schulz8372aa52015-03-25 10:39:40 +0100658{
659 tGAP_CCB *p_ccb;
660
661 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
662 return (0);
663
664 return (p_ccb->rem_mtu_size);
665}
666
667/*******************************************************************************
668**
669** Function GAP_ConnGetL2CAPCid
670**
671** Description Returns the L2CAP channel id
672**
673** Parameters: handle - Handle of the connection
674**
Marie Janssend19e0782016-07-15 12:48:27 -0700675** Returns uint16_t - The L2CAP channel id
Kim Schulz8372aa52015-03-25 10:39:40 +0100676** 0, if error
677**
678*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700679uint16_t GAP_ConnGetL2CAPCid (uint16_t gap_handle)
Kim Schulz8372aa52015-03-25 10:39:40 +0100680{
681 tGAP_CCB *p_ccb;
682
683 if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
684 return (0);
685
686 return (p_ccb->connection_id);
687}
688
Srinu Jella4e972d82016-02-16 20:22:16 +0530689/*******************************************************************************
690**
691** Function gap_tx_connect_ind
692**
693** Description Sends out GAP_EVT_TX_EMPTY when transmission has been
694** completed.
695**
696** Returns void
697**
698*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700699void gap_tx_complete_ind (uint16_t l2cap_cid, uint16_t sdu_sent)
Srinu Jella4e972d82016-02-16 20:22:16 +0530700{
701 tGAP_CCB *p_ccb = gap_find_ccb_by_cid (l2cap_cid);
702 if (p_ccb == NULL)
703 return;
704
705 if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF))
706 {
707 GAP_TRACE_EVENT("%s: GAP_EVT_TX_EMPTY", __func__);
708 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_TX_EMPTY);
709 }
710}
Kim Schulz8372aa52015-03-25 10:39:40 +0100711
712/*******************************************************************************
713**
714** Function gap_connect_ind
715**
716** Description This function handles an inbound connection indication
717** from L2CAP. This is the case where we are acting as a
718** server.
719**
720** Returns void
721**
722*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700723static void gap_connect_ind (BD_ADDR bd_addr, uint16_t l2cap_cid, uint16_t psm, uint8_t l2cap_id)
Kim Schulz8372aa52015-03-25 10:39:40 +0100724{
Marie Janssend19e0782016-07-15 12:48:27 -0700725 uint16_t xx;
Kim Schulz8372aa52015-03-25 10:39:40 +0100726 tGAP_CCB *p_ccb;
Kim Schulz8372aa52015-03-25 10:39:40 +0100727
728 /* See if we have a CCB listening for the connection */
729 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
730 {
731 if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
732 && (p_ccb->psm == psm)
Marie Janssend19e0782016-07-15 12:48:27 -0700733 && ((p_ccb->rem_addr_specified == false)
Kim Schulz8372aa52015-03-25 10:39:40 +0100734 || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN))))
735 break;
736 }
737
738 if (xx == GAP_MAX_CONNECTIONS)
739 {
740 GAP_TRACE_WARNING("*******");
741 GAP_TRACE_WARNING("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
742 GAP_TRACE_WARNING("*******");
743
744 /* Disconnect because it is an unexpected connection */
745 L2CA_DISCONNECT_REQ (l2cap_cid);
746 return;
747 }
748
749 /* Transition to the next appropriate state, waiting for config setup. */
Navin Kochar67212322016-03-09 23:11:53 +0530750 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
751 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
Kim Schulz8372aa52015-03-25 10:39:40 +0100752
753 /* Save the BD Address and Channel ID. */
754 memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
755 p_ccb->connection_id = l2cap_cid;
756
757 /* Send response to the L2CAP layer. */
Navin Kochar67212322016-03-09 23:11:53 +0530758 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
759 L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info);
760
761 if (p_ccb->transport == BT_TRANSPORT_LE)
762 {
763 L2CA_CONNECT_COC_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->local_coc_cfg);
764
765 /* get the remote coc configuration */
766 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg);
767 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
768
769 /* configuration is not required for LE COC */
770 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
771 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
772 gap_checks_con_flags (p_ccb);
773 }
Kim Schulz8372aa52015-03-25 10:39:40 +0100774
775 GAP_TRACE_EVENT("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
776
777 /* Send a Configuration Request. */
Navin Kochar67212322016-03-09 23:11:53 +0530778 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
779 L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
Kim Schulz8372aa52015-03-25 10:39:40 +0100780}
781
782/*******************************************************************************
783**
784** Function gap_checks_con_flags
785**
786** Description This function processes the L2CAP configuration indication
787** event.
788**
789** Returns void
790**
791*******************************************************************************/
792static void gap_checks_con_flags (tGAP_CCB *p_ccb)
793{
794 GAP_TRACE_EVENT ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
795 /* if all the required con_flags are set, report the OPEN event now */
796 if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE)
797 {
798 p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
799
800 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
801 }
802}
803
804/*******************************************************************************
805**
806** Function gap_sec_check_complete
807**
808** Description The function called when Security Manager finishes
809** verification of the service side connection
810**
811** Returns void
812**
813*******************************************************************************/
Myles Watsond35a6482016-10-27 08:52:16 -0700814static void gap_sec_check_complete (UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data,
815 uint8_t res)
Kim Schulz8372aa52015-03-25 10:39:40 +0100816{
817 tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
Kim Schulz8372aa52015-03-25 10:39:40 +0100818
819 GAP_TRACE_EVENT ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
820 p_ccb->con_state, p_ccb->con_flags, res);
821 if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
822 return;
823
824 if (res == BTM_SUCCESS)
825 {
826 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
827 gap_checks_con_flags (p_ccb);
828 }
829 else
830 {
831 /* security failed - disconnect the channel */
832 L2CA_DISCONNECT_REQ (p_ccb->connection_id);
833 }
834}
835
836/*******************************************************************************
837**
838** Function gap_connect_cfm
839**
840** Description This function handles the connect confirm events
841** from L2CAP. This is the case when we are acting as a
842** client and have sent a connect request.
843**
844** Returns void
845**
846*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700847static void gap_connect_cfm (uint16_t l2cap_cid, uint16_t result)
Kim Schulz8372aa52015-03-25 10:39:40 +0100848{
849 tGAP_CCB *p_ccb;
850
851 /* Find CCB based on CID */
852 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
853 return;
854
855 /* initiate security process, if needed */
Navin Kochar67212322016-03-09 23:11:53 +0530856 if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 && p_ccb->transport != BT_TRANSPORT_LE)
Kim Schulz8372aa52015-03-25 10:39:40 +0100857 {
Marie Janssend19e0782016-07-15 12:48:27 -0700858 btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, true,
Kim Schulz8372aa52015-03-25 10:39:40 +0100859 0, 0, &gap_sec_check_complete, p_ccb);
860 }
861
862 /* If the connection response contains success status, then */
863 /* Transition to the next state and startup the timer. */
864 if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP))
865 {
Navin Kochar67212322016-03-09 23:11:53 +0530866 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
867 {
868 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
Kim Schulz8372aa52015-03-25 10:39:40 +0100869
Navin Kochar67212322016-03-09 23:11:53 +0530870 /* Send a Configuration Request. */
871 L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
872 }
873
874 if (p_ccb->transport == BT_TRANSPORT_LE)
875 {
876 /* get the remote coc configuration */
877 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg);
878 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
879
880 /* configuration is not required for LE COC */
881 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
882 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
883 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
884 gap_checks_con_flags (p_ccb);
885 }
Kim Schulz8372aa52015-03-25 10:39:40 +0100886 }
887 else
888 {
889 /* Tell the user if he has a callback */
890 if (p_ccb->p_callback)
891 (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
892
893 gap_release_ccb (p_ccb);
894 }
895}
896
897/*******************************************************************************
898**
899** Function gap_config_ind
900**
901** Description This function processes the L2CAP configuration indication
902** event.
903**
904** Returns void
905**
906*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700907static void gap_config_ind (uint16_t l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
Kim Schulz8372aa52015-03-25 10:39:40 +0100908{
909 tGAP_CCB *p_ccb;
Marie Janssend19e0782016-07-15 12:48:27 -0700910 uint16_t local_mtu_size;
Kim Schulz8372aa52015-03-25 10:39:40 +0100911
912 /* Find CCB based on CID */
913 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
914 return;
915
916 /* Remember the remote MTU size */
917
918 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
919 {
Pavlin Radoslavov1d5b8592015-09-23 10:08:20 -0700920 local_mtu_size = p_ccb->ertm_info.user_tx_buf_size
Kim Schulz8372aa52015-03-25 10:39:40 +0100921 - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
922 }
923 else
924 local_mtu_size = L2CAP_MTU_SIZE;
925
926 if ((!p_cfg->mtu_present)||(p_cfg->mtu > local_mtu_size))
927 {
928 p_ccb->rem_mtu_size = local_mtu_size;
929 }
930 else
931 p_ccb->rem_mtu_size = p_cfg->mtu;
932
933 /* For now, always accept configuration from the other side */
Marie Janssend19e0782016-07-15 12:48:27 -0700934 p_cfg->flush_to_present = false;
935 p_cfg->mtu_present = false;
Kim Schulz8372aa52015-03-25 10:39:40 +0100936 p_cfg->result = L2CAP_CFG_OK;
Marie Janssend19e0782016-07-15 12:48:27 -0700937 p_cfg->fcs_present = false;
Kim Schulz8372aa52015-03-25 10:39:40 +0100938
939 L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
940
941 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
942
943 gap_checks_con_flags (p_ccb);
944}
945
946
947/*******************************************************************************
948**
949** Function gap_config_cfm
950**
951** Description This function processes the L2CAP configuration confirmation
952** event.
953**
954** Returns void
955**
956*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700957static void gap_config_cfm (uint16_t l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
Kim Schulz8372aa52015-03-25 10:39:40 +0100958{
959 tGAP_CCB *p_ccb;
960
961 /* Find CCB based on CID */
962 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
963 return;
964
965 if (p_cfg->result == L2CAP_CFG_OK)
966 {
967 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
968
969
970 if (p_ccb->cfg.fcr_present)
971 p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
972 else
973 p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
974
975 gap_checks_con_flags (p_ccb);
976 }
977 else
978 {
979 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
980 gap_release_ccb (p_ccb);
981 }
982}
983
984
985/*******************************************************************************
986**
987** Function gap_disconnect_ind
988**
989** Description This function handles a disconnect event from L2CAP. If
990** requested to, we ack the disconnect before dropping the CCB
991**
992** Returns void
993**
994*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -0700995static void gap_disconnect_ind (uint16_t l2cap_cid, bool ack_needed)
Kim Schulz8372aa52015-03-25 10:39:40 +0100996{
997 tGAP_CCB *p_ccb;
998
999 GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
1000
1001 /* Find CCB based on CID */
1002 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
1003 return;
1004
1005 if (ack_needed)
1006 L2CA_DISCONNECT_RSP (l2cap_cid);
1007
1008 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
1009 gap_release_ccb (p_ccb);
1010}
1011
1012
1013/*******************************************************************************
1014**
1015** Function gap_data_ind
1016**
1017** Description This function is called when data is received from L2CAP.
1018**
1019** Returns void
1020**
1021*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001022static void gap_data_ind (uint16_t l2cap_cid, BT_HDR *p_msg)
Kim Schulz8372aa52015-03-25 10:39:40 +01001023{
1024 tGAP_CCB *p_ccb;
1025
1026 /* Find CCB based on CID */
1027 if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
1028 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001029 osi_free(p_msg);
Kim Schulz8372aa52015-03-25 10:39:40 +01001030 return;
1031 }
1032
1033 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
1034 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001035 fixed_queue_enqueue(p_ccb->rx_queue, p_msg);
Kim Schulz8372aa52015-03-25 10:39:40 +01001036
1037 p_ccb->rx_queue_size += p_msg->len;
1038 /*
1039 GAP_TRACE_EVENT ("gap_data_ind - rx_queue_size=%d, msg len=%d",
1040 p_ccb->rx_queue_size, p_msg->len);
1041 */
1042
1043 p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
1044 }
1045 else
1046 {
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001047 osi_free(p_msg);
Kim Schulz8372aa52015-03-25 10:39:40 +01001048 }
1049}
1050
1051
1052/*******************************************************************************
1053**
1054** Function gap_congestion_ind
1055**
1056** Description This is a callback function called by L2CAP when
1057** data L2CAP congestion status changes
1058**
1059*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001060static void gap_congestion_ind (uint16_t lcid, bool is_congested)
Kim Schulz8372aa52015-03-25 10:39:40 +01001061{
1062 tGAP_CCB *p_ccb;
Marie Janssend19e0782016-07-15 12:48:27 -07001063 uint16_t event;
Kim Schulz8372aa52015-03-25 10:39:40 +01001064 BT_HDR *p_buf;
Marie Janssend19e0782016-07-15 12:48:27 -07001065 uint8_t status;
Kim Schulz8372aa52015-03-25 10:39:40 +01001066
1067 GAP_TRACE_EVENT ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
1068 is_congested, lcid);
1069
1070 /* Find CCB based on CID */
1071 if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL)
1072 return;
1073
1074 p_ccb->is_congested = is_congested;
1075
1076 event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
1077 p_ccb->p_callback (p_ccb->gap_handle, event);
1078
1079 if (!is_congested)
1080 {
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001081 while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL)
Kim Schulz8372aa52015-03-25 10:39:40 +01001082 {
1083 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
1084
1085 if (status == L2CAP_DW_CONGESTED)
1086 {
Marie Janssend19e0782016-07-15 12:48:27 -07001087 p_ccb->is_congested = true;
Kim Schulz8372aa52015-03-25 10:39:40 +01001088 break;
1089 }
1090 else if (status != L2CAP_DW_SUCCESS)
1091 break;
1092 }
1093 }
1094}
1095
1096
1097/*******************************************************************************
1098**
1099** Function gap_find_ccb_by_cid
1100**
1101** Description This function searches the CCB table for an entry with the
1102** passed CID.
1103**
1104** Returns the CCB address, or NULL if not found.
1105**
1106*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001107static tGAP_CCB *gap_find_ccb_by_cid (uint16_t cid)
Kim Schulz8372aa52015-03-25 10:39:40 +01001108{
Marie Janssend19e0782016-07-15 12:48:27 -07001109 uint16_t xx;
Kim Schulz8372aa52015-03-25 10:39:40 +01001110 tGAP_CCB *p_ccb;
1111
1112 /* Look through each connection control block */
1113 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
1114 {
1115 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid))
1116 return (p_ccb);
1117 }
1118
1119 /* If here, not found */
1120 return (NULL);
1121}
1122
1123
1124/*******************************************************************************
1125**
1126** Function gap_find_ccb_by_handle
1127**
1128** Description This function searches the CCB table for an entry with the
1129** passed handle.
1130**
1131** Returns the CCB address, or NULL if not found.
1132**
1133*******************************************************************************/
Marie Janssend19e0782016-07-15 12:48:27 -07001134static tGAP_CCB *gap_find_ccb_by_handle (uint16_t handle)
Kim Schulz8372aa52015-03-25 10:39:40 +01001135{
1136 tGAP_CCB *p_ccb;
1137
1138 /* Check that handle is valid */
1139 if (handle < GAP_MAX_CONNECTIONS)
1140 {
1141 p_ccb = &gap_cb.conn.ccb_pool[handle];
1142
1143 if (p_ccb->con_state != GAP_CCB_STATE_IDLE)
1144 return (p_ccb);
1145 }
1146
1147 /* If here, handle points to invalid connection */
1148 return (NULL);
1149}
1150
1151
1152/*******************************************************************************
1153**
1154** Function gap_allocate_ccb
1155**
1156** Description This function allocates a new CCB.
1157**
1158** Returns CCB address, or NULL if none available.
1159**
1160*******************************************************************************/
1161static tGAP_CCB *gap_allocate_ccb (void)
1162{
Marie Janssend19e0782016-07-15 12:48:27 -07001163 uint16_t xx;
Kim Schulz8372aa52015-03-25 10:39:40 +01001164 tGAP_CCB *p_ccb;
1165
1166 /* Look through each connection control block for a free one */
1167 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
1168 {
1169 if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
1170 {
1171 memset (p_ccb, 0, sizeof (tGAP_CCB));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001172 p_ccb->tx_queue = fixed_queue_new(SIZE_MAX);
1173 p_ccb->rx_queue = fixed_queue_new(SIZE_MAX);
Kim Schulz8372aa52015-03-25 10:39:40 +01001174
1175 p_ccb->gap_handle = xx;
1176 p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
1177
1178 return (p_ccb);
1179 }
1180 }
1181
1182 /* If here, no free CCB found */
1183 return (NULL);
1184}
1185
1186
1187/*******************************************************************************
1188**
1189** Function gap_release_ccb
1190**
1191** Description This function releases a CCB.
1192**
1193** Returns void
1194**
1195*******************************************************************************/
1196static void gap_release_ccb (tGAP_CCB *p_ccb)
1197{
Marie Janssend19e0782016-07-15 12:48:27 -07001198 uint16_t xx;
1199 uint16_t psm = p_ccb->psm;
1200 uint8_t service_id = p_ccb->service_id;
Kim Schulz8372aa52015-03-25 10:39:40 +01001201
1202 /* Drop any buffers we may be holding */
1203 p_ccb->rx_queue_size = 0;
1204
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001205 while (!fixed_queue_is_empty(p_ccb->rx_queue))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001206 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001207 fixed_queue_free(p_ccb->rx_queue, NULL);
1208 p_ccb->rx_queue = NULL;
Kim Schulz8372aa52015-03-25 10:39:40 +01001209
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001210 while (!fixed_queue_is_empty(p_ccb->tx_queue))
Pavlin Radoslavovcceb4302016-02-05 13:54:43 -08001211 osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue));
Pavlin Radoslavov1a3844f2015-09-25 11:21:15 -07001212 fixed_queue_free(p_ccb->tx_queue, NULL);
1213 p_ccb->tx_queue = NULL;
Kim Schulz8372aa52015-03-25 10:39:40 +01001214
1215 p_ccb->con_state = GAP_CCB_STATE_IDLE;
1216
1217 /* If no-one else is using the PSM, deregister from L2CAP */
1218 for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
1219 {
1220 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm))
1221 return;
1222 }
1223
1224 /* Free the security record for this PSM */
1225 BTM_SecClrService(service_id);
Navin Kochar67212322016-03-09 23:11:53 +05301226 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
1227 L2CA_DEREGISTER (psm);
1228
1229 if(p_ccb->transport == BT_TRANSPORT_LE)
1230 L2CA_DEREGISTER_COC (psm);
Kim Schulz8372aa52015-03-25 10:39:40 +01001231}
1232
Kim Schulz8372aa52015-03-25 10:39:40 +01001233#endif /* GAP_CONN_INCLUDED */