1 /******************************************************************************
2 *
3 * Copyright 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 #include <base/strings/stringprintf.h>
20 #include <string.h>
21 #include "bt_target.h"
22 #include "bt_utils.h"
23 #include "btm_int.h"
24 #include "btu.h"
25 #include "device/include/controller.h"
26 #include "gap_api.h"
27 #include "l2c_int.h"
28 #include "l2cdefs.h"
29 #include "osi/include/fixed_queue.h"
30 #include "osi/include/mutex.h"
31
32 using base::StringPrintf;
33
34 /* Define the GAP Connection Control Block */
35 typedef struct {
36 #define GAP_CCB_STATE_IDLE 0
37 #define GAP_CCB_STATE_LISTENING 1
38 #define GAP_CCB_STATE_CONN_SETUP 2
39 #define GAP_CCB_STATE_CFG_SETUP 3
40 #define GAP_CCB_STATE_WAIT_SEC 4
41 #define GAP_CCB_STATE_CONNECTED 5
42 uint8_t con_state;
43
44 #define GAP_CCB_FLAGS_IS_ORIG 0x01
45 #define GAP_CCB_FLAGS_HIS_CFG_DONE 0x02
46 #define GAP_CCB_FLAGS_MY_CFG_DONE 0x04
47 #define GAP_CCB_FLAGS_SEC_DONE 0x08
48 #define GAP_CCB_FLAGS_CONN_DONE 0x0E
49 uint8_t con_flags;
50
51 uint8_t service_id; /* Used by BTM */
52 uint16_t gap_handle; /* GAP handle */
53 uint16_t connection_id; /* L2CAP CID */
54 bool rem_addr_specified;
55 uint8_t chan_mode_mask; /* Supported channel modes (FCR) */
56 RawAddress rem_dev_address;
57 uint16_t psm;
58 uint16_t rem_mtu_size;
59
60 bool is_congested;
61 fixed_queue_t* tx_queue; /* Queue of buffers waiting to be sent */
62 fixed_queue_t* rx_queue; /* Queue of buffers waiting to be read */
63
64 uint32_t rx_queue_size; /* Total data count in rx_queue */
65
66 tGAP_CONN_CALLBACK* p_callback; /* Users callback function */
67
68 tL2CAP_CFG_INFO cfg; /* Configuration */
69 tL2CAP_ERTM_INFO ertm_info; /* Pools and modes for ertm */
70 tBT_TRANSPORT transport; /* Transport channel BR/EDR or BLE */
71 tL2CAP_LE_CFG_INFO local_coc_cfg; /* local configuration for LE Coc */
72 tL2CAP_LE_CFG_INFO peer_coc_cfg; /* local configuration for LE Coc */
73 } tGAP_CCB;
74
75 typedef struct {
76 tL2CAP_APPL_INFO reg_info; /* L2CAP Registration info */
77 tGAP_CCB ccb_pool[GAP_MAX_CONNECTIONS];
78 } tGAP_CONN;
79
80 namespace {
81 tGAP_CONN conn;
82 }
83
84 /******************************************************************************/
85 /* L O C A L F U N C T I O N P R O T O T Y P E S */
86 /******************************************************************************/
87 static void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
88 uint16_t psm, uint8_t l2cap_id);
89 static void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result);
90 static void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
91 static void gap_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg);
92 static void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed);
93 static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg);
94 static void gap_congestion_ind(uint16_t lcid, bool is_congested);
95 static void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent);
96 static void gap_credits_received_cb(uint16_t l2cap_cid,
97 uint16_t credits_received,
98 uint16_t credit_count);
99
100 static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid);
101 static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle);
102 static tGAP_CCB* gap_allocate_ccb(void);
103 static void gap_release_ccb(tGAP_CCB* p_ccb);
104 static void gap_checks_con_flags(tGAP_CCB* p_ccb);
105
106 /*******************************************************************************
107 *
108 * Function gap_conn_init
109 *
110 * Description This function is called to initialize GAP connection
111 * management
112 *
113 * Returns void
114 *
115 ******************************************************************************/
gap_conn_init(void)116 void gap_conn_init(void) {
117 memset(&conn, 0, sizeof(tGAP_CONN));
118 conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
119 conn.reg_info.pL2CA_ConnectCfm_Cb = gap_connect_cfm;
120 conn.reg_info.pL2CA_ConnectPnd_Cb = NULL;
121 conn.reg_info.pL2CA_ConfigInd_Cb = gap_config_ind;
122 conn.reg_info.pL2CA_ConfigCfm_Cb = gap_config_cfm;
123 conn.reg_info.pL2CA_DisconnectInd_Cb = gap_disconnect_ind;
124 conn.reg_info.pL2CA_DisconnectCfm_Cb = NULL;
125 conn.reg_info.pL2CA_QoSViolationInd_Cb = NULL;
126 conn.reg_info.pL2CA_DataInd_Cb = gap_data_ind;
127 conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
128 conn.reg_info.pL2CA_TxComplete_Cb = gap_tx_complete_ind;
129 conn.reg_info.pL2CA_CreditsReceived_Cb = gap_credits_received_cb;
130 }
131
132 /*******************************************************************************
133 *
134 * Function GAP_ConnOpen
135 *
136 * Description This function is called to open an L2CAP connection.
137 *
138 * Parameters: is_server - If true, the connection is not created
139 * but put into a "listen" mode waiting for
140 * the remote side to connect.
141 *
142 * service_id - Unique service ID from
143 * BTM_SEC_SERVICE_FIRST_EMPTY (6)
144 * to BTM_SEC_MAX_SERVICE_RECORDS (32)
145 *
146 * p_rem_bda - Pointer to remote BD Address.
147 * If a server, and we don't care about the
148 * remote BD Address, then NULL should be passed.
149 *
150 * psm - the PSM used for the connection
151 * le_mps - Maximum PDU Size for LE CoC
152 *
153 * p_config - Optional pointer to configuration structure.
154 * If NULL, the default GAP configuration will
155 * be used.
156 *
157 * security - security flags
158 * chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC,
159 * GAP_FCR_CHAN_OPT_ERTM,
160 * GAP_FCR_CHAN_OPT_STREAM)
161 *
162 * p_cb - Pointer to callback function for events.
163 *
164 * Returns handle of the connection if successful, else
165 * GAP_INVALID_HANDLE
166 *
167 ******************************************************************************/
GAP_ConnOpen(const char * p_serv_name,uint8_t service_id,bool is_server,const RawAddress * p_rem_bda,uint16_t psm,uint16_t le_mps,tL2CAP_CFG_INFO * p_cfg,tL2CAP_ERTM_INFO * ertm_info,uint16_t security,uint8_t chan_mode_mask,tGAP_CONN_CALLBACK * p_cb,tBT_TRANSPORT transport)168 uint16_t GAP_ConnOpen(const char* p_serv_name, uint8_t service_id,
169 bool is_server, const RawAddress* p_rem_bda, uint16_t psm,
170 uint16_t le_mps, tL2CAP_CFG_INFO* p_cfg,
171 tL2CAP_ERTM_INFO* ertm_info, uint16_t security,
172 uint8_t chan_mode_mask, tGAP_CONN_CALLBACK* p_cb,
173 tBT_TRANSPORT transport) {
174 tGAP_CCB* p_ccb;
175 uint16_t cid;
176
177 DVLOG(1) << "GAP_CONN - Open Request";
178
179 /* Allocate a new CCB. Return if none available. */
180 p_ccb = gap_allocate_ccb();
181 if (p_ccb == NULL) return (GAP_INVALID_HANDLE);
182
183 /* update the transport */
184 p_ccb->transport = transport;
185
186 /* The service_id must be set before calling gap_release_ccb(). */
187 p_ccb->service_id = service_id;
188
189 /* If caller specified a BD address, save it */
190 if (p_rem_bda) {
191 /* the bd addr is not RawAddress::kAny, then a bd address was specified */
192 if (*p_rem_bda != RawAddress::kAny) p_ccb->rem_addr_specified = true;
193
194 p_ccb->rem_dev_address = *p_rem_bda;
195 } else if (!is_server) {
196 /* remore addr is not specified and is not a server -> bad */
197 return (GAP_INVALID_HANDLE);
198 }
199
200 /* A client MUST have specified a bd addr to connect with */
201 if (!p_ccb->rem_addr_specified && !is_server) {
202 gap_release_ccb(p_ccb);
203 LOG(ERROR)
204 << "GAP ERROR: Client must specify a remote BD ADDR to connect to!";
205 return (GAP_INVALID_HANDLE);
206 }
207
208 /* Check if configuration was specified */
209 if (p_cfg) p_ccb->cfg = *p_cfg;
210
211 /* Configure L2CAP COC, if transport is LE */
212 if (transport == BT_TRANSPORT_LE) {
213 p_ccb->local_coc_cfg.credits = L2CAP_LE_CREDIT_DEFAULT;
214 p_ccb->local_coc_cfg.mtu = p_cfg->mtu;
215
216 uint16_t max_mps = controller_get_interface()->get_acl_data_size_ble();
217 if (le_mps > max_mps) {
218 LOG(INFO) << "Limiting MPS to one buffer size - " << max_mps;
219 le_mps = max_mps;
220 }
221 p_ccb->local_coc_cfg.mps = le_mps;
222
223 VLOG(2) << __func__ << ": credits=" << p_ccb->local_coc_cfg.credits
224 << ", mps=" << p_ccb->local_coc_cfg.mps
225 << ", mtu=" << p_ccb->local_coc_cfg.mtu;
226 }
227
228 p_ccb->p_callback = p_cb;
229
230 /* If originator, use a dynamic PSM */
231 if (!is_server)
232 conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
233 else
234 conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
235
236 /* Register the PSM with L2CAP */
237 if (transport == BT_TRANSPORT_BR_EDR) {
238 p_ccb->psm = L2CA_REGISTER(
239 psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
240 if (p_ccb->psm == 0) {
241 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
242 psm);
243 gap_release_ccb(p_ccb);
244 return (GAP_INVALID_HANDLE);
245 }
246 }
247
248 if (transport == BT_TRANSPORT_LE) {
249 p_ccb->psm = L2CA_REGISTER_COC(
250 psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
251 if (p_ccb->psm == 0) {
252 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
253 psm);
254 gap_release_ccb(p_ccb);
255 return (GAP_INVALID_HANDLE);
256 }
257 }
258
259 /* Register with Security Manager for the specific security level */
260 if (!BTM_SetSecurityLevel((uint8_t)!is_server, p_serv_name, p_ccb->service_id,
261 security, p_ccb->psm, 0, 0)) {
262 LOG(ERROR) << "GAP_CONN - Security Error";
263 gap_release_ccb(p_ccb);
264 return (GAP_INVALID_HANDLE);
265 }
266
267 /* Fill in eL2CAP parameter data */
268 if (p_ccb->cfg.fcr_present) {
269 if (ertm_info == NULL) {
270 p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
271 p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
272 p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
273 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
274 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
275 } else {
276 p_ccb->ertm_info = *ertm_info;
277 }
278 }
279
280 /* optional FCR channel modes */
281 if (ertm_info != NULL) {
282 p_ccb->ertm_info.allowed_modes =
283 (chan_mode_mask) ? chan_mode_mask : (uint8_t)L2CAP_FCR_CHAN_OPT_BASIC;
284 }
285
286 if (is_server) {
287 p_ccb->con_flags |=
288 GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
289 p_ccb->con_state = GAP_CCB_STATE_LISTENING;
290 return (p_ccb->gap_handle);
291 } else {
292 /* We are the originator of this connection */
293 p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
294
295 /* Transition to the next appropriate state, waiting for connection confirm.
296 */
297 p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
298
299 /* mark security done flag, when security is not required */
300 if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE |
301 BTM_SEC_OUT_ENCRYPT)) == 0)
302 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
303
304 /* Check if L2CAP started the connection process */
305 if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR)) {
306 cid = L2CA_CONNECT_REQ(p_ccb->psm, *p_rem_bda, &p_ccb->ertm_info);
307 if (cid != 0) {
308 p_ccb->connection_id = cid;
309 return (p_ccb->gap_handle);
310 }
311 }
312
313 if (p_rem_bda && (transport == BT_TRANSPORT_LE)) {
314 cid = L2CA_CONNECT_COC_REQ(p_ccb->psm, *p_rem_bda, &p_ccb->local_coc_cfg);
315 if (cid != 0) {
316 p_ccb->connection_id = cid;
317 return (p_ccb->gap_handle);
318 }
319 }
320
321 gap_release_ccb(p_ccb);
322 return (GAP_INVALID_HANDLE);
323 }
324 }
325
326 /*******************************************************************************
327 *
328 * Function GAP_ConnClose
329 *
330 * Description This function is called to close a connection.
331 *
332 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
333 *
334 * Returns BT_PASS - closed OK
335 * GAP_ERR_BAD_HANDLE - invalid handle
336 *
337 ******************************************************************************/
GAP_ConnClose(uint16_t gap_handle)338 uint16_t GAP_ConnClose(uint16_t gap_handle) {
339 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
340
341 DVLOG(1) << StringPrintf("GAP_CONN - close handle: 0x%x", gap_handle);
342
343 if (p_ccb) {
344 /* Check if we have a connection ID */
345 if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
346 L2CA_DISCONNECT_REQ(p_ccb->connection_id);
347
348 gap_release_ccb(p_ccb);
349
350 return (BT_PASS);
351 }
352
353 return (GAP_ERR_BAD_HANDLE);
354 }
355
356 /*******************************************************************************
357 *
358 * Function GAP_ConnReadData
359 *
360 * Description Normally not GKI aware application will call this function
361 * after receiving GAP_EVT_RXDATA event.
362 *
363 * Parameters: handle - Handle of the connection returned in the Open
364 * p_data - Data area
365 * max_len - Byte count requested
366 * p_len - Byte count received
367 *
368 * Returns BT_PASS - data read
369 * GAP_ERR_BAD_HANDLE - invalid handle
370 * GAP_NO_DATA_AVAIL - no data available
371 *
372 ******************************************************************************/
GAP_ConnReadData(uint16_t gap_handle,uint8_t * p_data,uint16_t max_len,uint16_t * p_len)373 uint16_t GAP_ConnReadData(uint16_t gap_handle, uint8_t* p_data,
374 uint16_t max_len, uint16_t* p_len) {
375 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
376 uint16_t copy_len;
377
378 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
379
380 *p_len = 0;
381
382 if (fixed_queue_is_empty(p_ccb->rx_queue)) return (GAP_NO_DATA_AVAIL);
383
384 mutex_global_lock();
385
386 while (max_len) {
387 BT_HDR* p_buf =
388 static_cast<BT_HDR*>(fixed_queue_try_peek_first(p_ccb->rx_queue));
389 if (p_buf == NULL) break;
390
391 copy_len = (p_buf->len > max_len) ? max_len : p_buf->len;
392 max_len -= copy_len;
393 *p_len += copy_len;
394 if (p_data) {
395 memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, copy_len);
396 p_data += copy_len;
397 }
398
399 if (p_buf->len > copy_len) {
400 p_buf->offset += copy_len;
401 p_buf->len -= copy_len;
402 break;
403 }
404 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
405 }
406
407 p_ccb->rx_queue_size -= *p_len;
408
409 mutex_global_unlock();
410
411 DVLOG(1) << StringPrintf(
412 "GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
413 p_ccb->rx_queue_size, *p_len);
414
415 return (BT_PASS);
416 }
417
418 /*******************************************************************************
419 *
420 * Function GAP_GetRxQueueCnt
421 *
422 * Description This function return number of bytes on the rx queue.
423 *
424 * Parameters: handle - Handle returned in the GAP_ConnOpen
425 * p_rx_queue_count - Pointer to return queue count in.
426 *
427 *
428 ******************************************************************************/
GAP_GetRxQueueCnt(uint16_t handle,uint32_t * p_rx_queue_count)429 int GAP_GetRxQueueCnt(uint16_t handle, uint32_t* p_rx_queue_count) {
430 tGAP_CCB* p_ccb;
431 int rc = BT_PASS;
432
433 /* Check that handle is valid */
434 if (handle < GAP_MAX_CONNECTIONS) {
435 p_ccb = &conn.ccb_pool[handle];
436
437 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
438 *p_rx_queue_count = p_ccb->rx_queue_size;
439 } else
440 rc = GAP_INVALID_HANDLE;
441 } else
442 rc = GAP_INVALID_HANDLE;
443
444 DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
445 rc, *p_rx_queue_count);
446
447 return (rc);
448 }
449
450 /*******************************************************************************
451 *
452 * Function GAP_ConnBTRead
453 *
454 * Description Bluetooth-aware applications will call this function after
455 * receiving GAP_EVT_RXDATA event.
456 *
457 * Parameters: handle - Handle of the connection returned in the Open
458 * pp_buf - pointer to address of buffer with data,
459 *
460 * Returns BT_PASS - data read
461 * GAP_ERR_BAD_HANDLE - invalid handle
462 * GAP_NO_DATA_AVAIL - no data available
463 *
464 ******************************************************************************/
GAP_ConnBTRead(uint16_t gap_handle,BT_HDR ** pp_buf)465 uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) {
466 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
467 BT_HDR* p_buf;
468
469 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
470
471 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rx_queue);
472
473 if (p_buf) {
474 *pp_buf = p_buf;
475
476 p_ccb->rx_queue_size -= p_buf->len;
477 return (BT_PASS);
478 } else {
479 *pp_buf = NULL;
480 return (GAP_NO_DATA_AVAIL);
481 }
482 }
483
484 /* Try to write the queued data to l2ca. Return true on success, or if queue is
485 * congested. False if error occured when writing. */
gap_try_write_queued_data(tGAP_CCB * p_ccb)486 static bool gap_try_write_queued_data(tGAP_CCB* p_ccb) {
487 if (p_ccb->is_congested) return true;
488
489 /* Send the buffer through L2CAP */
490 BT_HDR* p_buf;
491 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
492 uint8_t status = L2CA_DATA_WRITE(p_ccb->connection_id, p_buf);
493
494 if (status == L2CAP_DW_CONGESTED) {
495 p_ccb->is_congested = true;
496 return true;
497 } else if (status != L2CAP_DW_SUCCESS)
498 return false;
499 }
500 return true;
501 }
502
503 /*******************************************************************************
504 *
505 * Function GAP_ConnWriteData
506 *
507 * Description Normally not GKI aware application will call this function
508 * to send data to the connection.
509 *
510 * Parameters: handle - Handle of the connection returned in the Open
511 * msg - pointer to single SDU to send. This function
512 * will take ownership of it.
513 *
514 * Returns BT_PASS - data read
515 * GAP_ERR_BAD_HANDLE - invalid handle
516 * GAP_ERR_BAD_STATE - connection not established
517 * GAP_CONGESTION - system is congested
518 *
519 ******************************************************************************/
GAP_ConnWriteData(uint16_t gap_handle,BT_HDR * msg)520 uint16_t GAP_ConnWriteData(uint16_t gap_handle, BT_HDR* msg) {
521 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
522
523 if (!p_ccb) {
524 osi_free(msg);
525 return GAP_ERR_BAD_HANDLE;
526 }
527
528 if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
529 osi_free(msg);
530 return GAP_ERR_BAD_STATE;
531 }
532
533 if (msg->len > p_ccb->rem_mtu_size) {
534 osi_free(msg);
535 return GAP_ERR_ILL_PARM;
536 }
537
538 DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", msg->len);
539
540 fixed_queue_enqueue(p_ccb->tx_queue, msg);
541
542 if (!gap_try_write_queued_data(p_ccb)) return GAP_ERR_BAD_STATE;
543
544 return (BT_PASS);
545 }
546
547 /*******************************************************************************
548 *
549 * Function GAP_ConnReconfig
550 *
551 * Description Applications can call this function to reconfigure the
552 * connection.
553 *
554 * Parameters: handle - Handle of the connection
555 * p_cfg - Pointer to new configuration
556 *
557 * Returns BT_PASS - config process started
558 * GAP_ERR_BAD_HANDLE - invalid handle
559 *
560 ******************************************************************************/
GAP_ConnReconfig(uint16_t gap_handle,tL2CAP_CFG_INFO * p_cfg)561 uint16_t GAP_ConnReconfig(uint16_t gap_handle, tL2CAP_CFG_INFO* p_cfg) {
562 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
563
564 if (!p_ccb) 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 * Function GAP_ConnSetIdleTimeout
577 *
578 * Description Higher layers call this function to set the idle timeout for
579 * a connection, or for all future connections. The "idle
580 * timeout" is the amount of time that a connection can remain
581 * up with no L2CAP channels on it. A timeout of zero means
582 * that the connection will be torn down immediately when the
583 * last channel is removed. A timeout of 0xFFFF means no
584 * timeout. Values are in seconds.
585 *
586 * Parameters: handle - Handle of the connection
587 * timeout - in secs
588 * 0 = immediate disconnect when last channel is
589 * removed
590 * 0xFFFF = no idle timeout
591 *
592 * Returns BT_PASS - config process started
593 * GAP_ERR_BAD_HANDLE - invalid handle
594 *
595 ******************************************************************************/
GAP_ConnSetIdleTimeout(uint16_t gap_handle,uint16_t timeout)596 uint16_t GAP_ConnSetIdleTimeout(uint16_t gap_handle, uint16_t timeout) {
597 tGAP_CCB* p_ccb;
598
599 p_ccb = gap_find_ccb_by_handle(gap_handle);
600 if (p_ccb == NULL) return (GAP_ERR_BAD_HANDLE);
601
602 if (L2CA_SetIdleTimeout(p_ccb->connection_id, timeout, false))
603 return (BT_PASS);
604 else
605 return (GAP_ERR_BAD_HANDLE);
606 }
607
608 /*******************************************************************************
609 *
610 * Function GAP_ConnGetRemoteAddr
611 *
612 * Description This function is called to get the remote BD address
613 * of a connection.
614 *
615 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
616 *
617 * Returns BT_PASS - closed OK
618 * GAP_ERR_BAD_HANDLE - invalid handle
619 *
620 ******************************************************************************/
GAP_ConnGetRemoteAddr(uint16_t gap_handle)621 const RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) {
622 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
623
624 DVLOG(1) << __func__ << " gap_handle = " << gap_handle;
625
626 if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) {
627 DVLOG(1) << __func__ << " BDA: " << p_ccb->rem_dev_address;
628 return &p_ccb->rem_dev_address;
629 } else {
630 DVLOG(1) << __func__ << " return Error ";
631 return nullptr;
632 }
633 }
634
635 /*******************************************************************************
636 *
637 * Function GAP_ConnGetRemMtuSize
638 *
639 * Description Returns the remote device's MTU size
640 *
641 * Parameters: handle - Handle of the connection
642 *
643 * Returns uint16_t - maximum size buffer that can be transmitted to
644 * the peer
645 *
646 ******************************************************************************/
GAP_ConnGetRemMtuSize(uint16_t gap_handle)647 uint16_t GAP_ConnGetRemMtuSize(uint16_t gap_handle) {
648 tGAP_CCB* p_ccb;
649
650 p_ccb = gap_find_ccb_by_handle(gap_handle);
651 if (p_ccb == NULL) return (0);
652
653 return (p_ccb->rem_mtu_size);
654 }
655
656 /*******************************************************************************
657 *
658 * Function GAP_ConnGetL2CAPCid
659 *
660 * Description Returns the L2CAP channel id
661 *
662 * Parameters: handle - Handle of the connection
663 *
664 * Returns uint16_t - The L2CAP channel id
665 * 0, if error
666 *
667 ******************************************************************************/
GAP_ConnGetL2CAPCid(uint16_t gap_handle)668 uint16_t GAP_ConnGetL2CAPCid(uint16_t gap_handle) {
669 tGAP_CCB* p_ccb;
670
671 p_ccb = gap_find_ccb_by_handle(gap_handle);
672 if (p_ccb == NULL) return (0);
673
674 return (p_ccb->connection_id);
675 }
676
677 /*******************************************************************************
678 *
679 * Function gap_tx_connect_ind
680 *
681 * Description Sends out GAP_EVT_TX_EMPTY when transmission has been
682 * completed.
683 *
684 * Returns void
685 *
686 ******************************************************************************/
gap_tx_complete_ind(uint16_t l2cap_cid,uint16_t sdu_sent)687 void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent) {
688 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
689 if (p_ccb == NULL) return;
690
691 if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) {
692 DVLOG(1) << StringPrintf("%s: GAP_EVT_TX_EMPTY", __func__);
693 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY, nullptr);
694 }
695 }
696
gap_credits_received_cb(uint16_t l2cap_cid,uint16_t credits_received,uint16_t credit_count)697 void gap_credits_received_cb(uint16_t l2cap_cid, uint16_t credits_received,
698 uint16_t credit_count) {
699 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
700 if (!p_ccb) return;
701
702 tGAP_CB_DATA data{.coc_credits = {.credits_received = credits_received,
703 .credit_count = credit_count}};
704 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_LE_COC_CREDITS, &data);
705 }
706
707 /*******************************************************************************
708 *
709 * Function gap_connect_ind
710 *
711 * Description This function handles an inbound connection indication
712 * from L2CAP. This is the case where we are acting as a
713 * server.
714 *
715 * Returns void
716 *
717 ******************************************************************************/
gap_connect_ind(const RawAddress & bd_addr,uint16_t l2cap_cid,uint16_t psm,uint8_t l2cap_id)718 static void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
719 uint16_t psm, uint8_t l2cap_id) {
720 uint16_t xx;
721 tGAP_CCB* p_ccb;
722
723 /* See if we have a CCB listening for the connection */
724 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
725 if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) && (p_ccb->psm == psm) &&
726 (!p_ccb->rem_addr_specified || (bd_addr == p_ccb->rem_dev_address)))
727 break;
728 }
729
730 if (xx == GAP_MAX_CONNECTIONS) {
731 LOG(WARNING) << "*******";
732 LOG(WARNING) << "WARNING: GAP Conn Indication for Unexpected Bd "
733 "Addr...Disconnecting";
734 LOG(WARNING) << "*******";
735
736 /* Disconnect because it is an unexpected connection */
737 L2CA_DISCONNECT_REQ(l2cap_cid);
738 return;
739 }
740
741 /* Transition to the next appropriate state, waiting for config setup. */
742 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
743 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
744
745 /* Save the BD Address and Channel ID. */
746 p_ccb->rem_dev_address = bd_addr;
747 p_ccb->connection_id = l2cap_cid;
748
749 /* Send response to the L2CAP layer. */
750 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
751 L2CA_CONNECT_RSP(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK,
752 &p_ccb->ertm_info);
753
754 if (p_ccb->transport == BT_TRANSPORT_LE) {
755 L2CA_CONNECT_COC_RSP(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK,
756 L2CAP_CONN_OK, &p_ccb->local_coc_cfg);
757
758 /* get the remote coc configuration */
759 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg);
760 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
761
762 /* configuration is not required for LE COC */
763 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
764 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
765 gap_checks_con_flags(p_ccb);
766 }
767
768 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x",
769 p_ccb->connection_id);
770
771 /* Send a Configuration Request. */
772 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
773 L2CA_CONFIG_REQ(l2cap_cid, &p_ccb->cfg);
774 }
775
776 /*******************************************************************************
777 *
778 * Function gap_checks_con_flags
779 *
780 * Description This function processes the L2CAP configuration indication
781 * event.
782 *
783 * Returns void
784 *
785 ******************************************************************************/
gap_checks_con_flags(tGAP_CCB * p_ccb)786 static void gap_checks_con_flags(tGAP_CCB* p_ccb) {
787 DVLOG(1) << __func__ << " conn_flags:0x" << +p_ccb->con_flags;
788 /* if all the required con_flags are set, report the OPEN event now */
789 if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
790 p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
791
792 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED, nullptr);
793 }
794 }
795
796 /*******************************************************************************
797 *
798 * Function gap_sec_check_complete
799 *
800 * Description The function called when Security Manager finishes
801 * verification of the service side connection
802 *
803 * Returns void
804 *
805 ******************************************************************************/
gap_sec_check_complete(const RawAddress *,tBT_TRANSPORT,void * p_ref_data,uint8_t res)806 static void gap_sec_check_complete(const RawAddress*, tBT_TRANSPORT,
807 void* p_ref_data, uint8_t res) {
808 tGAP_CCB* p_ccb = (tGAP_CCB*)p_ref_data;
809
810 DVLOG(1) << StringPrintf(
811 "gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
812 p_ccb->con_state, p_ccb->con_flags, res);
813 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) return;
814
815 if (res == BTM_SUCCESS) {
816 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
817 gap_checks_con_flags(p_ccb);
818 } else {
819 /* security failed - disconnect the channel */
820 L2CA_DISCONNECT_REQ(p_ccb->connection_id);
821 }
822 }
823
824 /*******************************************************************************
825 *
826 * Function gap_connect_cfm
827 *
828 * Description This function handles the connect confirm events
829 * from L2CAP. This is the case when we are acting as a
830 * client and have sent a connect request.
831 *
832 * Returns void
833 *
834 ******************************************************************************/
gap_connect_cfm(uint16_t l2cap_cid,uint16_t result)835 static void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result) {
836 tGAP_CCB* p_ccb;
837
838 /* Find CCB based on CID */
839 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
840 if (p_ccb == NULL) return;
841
842 /* initiate security process, if needed */
843 if ((p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 &&
844 p_ccb->transport != BT_TRANSPORT_LE) {
845 btm_sec_mx_access_request(p_ccb->rem_dev_address, p_ccb->psm, true, 0, 0,
846 &gap_sec_check_complete, p_ccb);
847 }
848
849 /* If the connection response contains success status, then */
850 /* Transition to the next state and startup the timer. */
851 if ((result == L2CAP_CONN_OK) &&
852 (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) {
853 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) {
854 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
855
856 /* Send a Configuration Request. */
857 L2CA_CONFIG_REQ(l2cap_cid, &p_ccb->cfg);
858 }
859
860 if (p_ccb->transport == BT_TRANSPORT_LE) {
861 /* get the remote coc configuration */
862 L2CA_GET_PEER_COC_CONFIG(l2cap_cid, &p_ccb->peer_coc_cfg);
863 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
864
865 /* configuration is not required for LE COC */
866 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
867 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
868 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
869 gap_checks_con_flags(p_ccb);
870 }
871 } else {
872 /* Tell the user if he has a callback */
873 if (p_ccb->p_callback)
874 (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
875
876 gap_release_ccb(p_ccb);
877 }
878 }
879
880 /*******************************************************************************
881 *
882 * Function gap_config_ind
883 *
884 * Description This function processes the L2CAP configuration indication
885 * event.
886 *
887 * Returns void
888 *
889 ******************************************************************************/
gap_config_ind(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)890 static void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
891 tGAP_CCB* p_ccb;
892 uint16_t local_mtu_size;
893
894 /* Find CCB based on CID */
895 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
896 if (p_ccb == NULL) return;
897
898 /* Remember the remote MTU size */
899
900 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
901 local_mtu_size =
902 p_ccb->ertm_info.user_tx_buf_size - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
903 } else
904 local_mtu_size = L2CAP_MTU_SIZE;
905
906 if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) {
907 p_ccb->rem_mtu_size = local_mtu_size;
908 } else
909 p_ccb->rem_mtu_size = p_cfg->mtu;
910
911 /* For now, always accept configuration from the other side */
912 p_cfg->flush_to_present = false;
913 p_cfg->mtu_present = false;
914 p_cfg->result = L2CAP_CFG_OK;
915 p_cfg->fcs_present = false;
916
917 L2CA_CONFIG_RSP(l2cap_cid, p_cfg);
918
919 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
920
921 gap_checks_con_flags(p_ccb);
922 }
923
924 /*******************************************************************************
925 *
926 * Function gap_config_cfm
927 *
928 * Description This function processes the L2CAP configuration confirmation
929 * event.
930 *
931 * Returns void
932 *
933 ******************************************************************************/
gap_config_cfm(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)934 static void gap_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
935 tGAP_CCB* p_ccb;
936
937 /* Find CCB based on CID */
938 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
939 if (p_ccb == NULL) return;
940
941 if (p_cfg->result == L2CAP_CFG_OK) {
942 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
943
944 if (p_ccb->cfg.fcr_present)
945 p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
946 else
947 p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
948
949 gap_checks_con_flags(p_ccb);
950 } else {
951 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
952 gap_release_ccb(p_ccb);
953 }
954 }
955
956 /*******************************************************************************
957 *
958 * Function gap_disconnect_ind
959 *
960 * Description This function handles a disconnect event from L2CAP. If
961 * requested to, we ack the disconnect before dropping the CCB
962 *
963 * Returns void
964 *
965 ******************************************************************************/
gap_disconnect_ind(uint16_t l2cap_cid,bool ack_needed)966 static void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
967 tGAP_CCB* p_ccb;
968
969 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
970
971 /* Find CCB based on CID */
972 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
973 if (p_ccb == NULL) return;
974
975 if (ack_needed) L2CA_DISCONNECT_RSP(l2cap_cid);
976
977 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
978 gap_release_ccb(p_ccb);
979 }
980
981 /*******************************************************************************
982 *
983 * Function gap_data_ind
984 *
985 * Description This function is called when data is received from L2CAP.
986 *
987 * Returns void
988 *
989 ******************************************************************************/
gap_data_ind(uint16_t l2cap_cid,BT_HDR * p_msg)990 static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
991 tGAP_CCB* p_ccb;
992
993 /* Find CCB based on CID */
994 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
995 if (p_ccb == NULL) {
996 osi_free(p_msg);
997 return;
998 }
999
1000 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
1001 fixed_queue_enqueue(p_ccb->rx_queue, p_msg);
1002
1003 p_ccb->rx_queue_size += p_msg->len;
1004 /*
1005 DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d",
1006 p_ccb->rx_queue_size, p_msg->len);
1007 */
1008
1009 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
1010 } else {
1011 osi_free(p_msg);
1012 }
1013 }
1014
1015 /*******************************************************************************
1016 *
1017 * Function gap_congestion_ind
1018 *
1019 * Description This is a callback function called by L2CAP when
1020 * data L2CAP congestion status changes
1021 *
1022 ******************************************************************************/
gap_congestion_ind(uint16_t lcid,bool is_congested)1023 static void gap_congestion_ind(uint16_t lcid, bool is_congested) {
1024 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
1025 is_congested, lcid);
1026
1027 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(lcid); /* Find CCB based on CID */
1028 if (!p_ccb) return;
1029
1030 p_ccb->is_congested = is_congested;
1031
1032 p_ccb->p_callback(
1033 p_ccb->gap_handle,
1034 (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED,
1035 nullptr);
1036
1037 gap_try_write_queued_data(p_ccb);
1038 }
1039
1040 /*******************************************************************************
1041 *
1042 * Function gap_find_ccb_by_cid
1043 *
1044 * Description This function searches the CCB table for an entry with the
1045 * passed CID.
1046 *
1047 * Returns the CCB address, or NULL if not found.
1048 *
1049 ******************************************************************************/
gap_find_ccb_by_cid(uint16_t cid)1050 static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid) {
1051 uint16_t xx;
1052 tGAP_CCB* p_ccb;
1053
1054 /* Look through each connection control block */
1055 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1056 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) &&
1057 (p_ccb->connection_id == cid))
1058 return (p_ccb);
1059 }
1060
1061 /* If here, not found */
1062 return (NULL);
1063 }
1064
1065 /*******************************************************************************
1066 *
1067 * Function gap_find_ccb_by_handle
1068 *
1069 * Description This function searches the CCB table for an entry with the
1070 * passed handle.
1071 *
1072 * Returns the CCB address, or NULL if not found.
1073 *
1074 ******************************************************************************/
gap_find_ccb_by_handle(uint16_t handle)1075 static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle) {
1076 tGAP_CCB* p_ccb;
1077
1078 /* Check that handle is valid */
1079 if (handle < GAP_MAX_CONNECTIONS) {
1080 p_ccb = &conn.ccb_pool[handle];
1081
1082 if (p_ccb->con_state != GAP_CCB_STATE_IDLE) return (p_ccb);
1083 }
1084
1085 /* If here, handle points to invalid connection */
1086 return (NULL);
1087 }
1088
1089 /*******************************************************************************
1090 *
1091 * Function gap_allocate_ccb
1092 *
1093 * Description This function allocates a new CCB.
1094 *
1095 * Returns CCB address, or NULL if none available.
1096 *
1097 ******************************************************************************/
gap_allocate_ccb(void)1098 static tGAP_CCB* gap_allocate_ccb(void) {
1099 uint16_t xx;
1100 tGAP_CCB* p_ccb;
1101
1102 /* Look through each connection control block for a free one */
1103 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1104 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
1105 memset(p_ccb, 0, sizeof(tGAP_CCB));
1106 p_ccb->tx_queue = fixed_queue_new(SIZE_MAX);
1107 p_ccb->rx_queue = fixed_queue_new(SIZE_MAX);
1108
1109 p_ccb->gap_handle = xx;
1110 p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
1111
1112 return (p_ccb);
1113 }
1114 }
1115
1116 /* If here, no free CCB found */
1117 return (NULL);
1118 }
1119
1120 /*******************************************************************************
1121 *
1122 * Function gap_release_ccb
1123 *
1124 * Description This function releases a CCB.
1125 *
1126 * Returns void
1127 *
1128 ******************************************************************************/
gap_release_ccb(tGAP_CCB * p_ccb)1129 static void gap_release_ccb(tGAP_CCB* p_ccb) {
1130 /* Drop any buffers we may be holding */
1131 p_ccb->rx_queue_size = 0;
1132
1133 while (!fixed_queue_is_empty(p_ccb->rx_queue))
1134 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
1135 fixed_queue_free(p_ccb->rx_queue, NULL);
1136 p_ccb->rx_queue = NULL;
1137
1138 while (!fixed_queue_is_empty(p_ccb->tx_queue))
1139 osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue));
1140 fixed_queue_free(p_ccb->tx_queue, NULL);
1141 p_ccb->tx_queue = NULL;
1142
1143 p_ccb->con_state = GAP_CCB_STATE_IDLE;
1144
1145 /* If no-one else is using the PSM, deregister from L2CAP */
1146 tGAP_CCB* p_ccb_local = conn.ccb_pool;
1147 for (uint16_t i = 0; i < GAP_MAX_CONNECTIONS; i++, p_ccb_local++) {
1148 if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) &&
1149 (p_ccb_local->psm == p_ccb->psm)) {
1150 DVLOG(1) << __func__ << " : " << +p_ccb_local->psm
1151 << " PSM is still in use, do not deregister";
1152 return;
1153 }
1154 }
1155
1156 /* Free the security record for this PSM */
1157 BTM_SecClrService(p_ccb->service_id);
1158 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) L2CA_DEREGISTER(p_ccb->psm);
1159 if (p_ccb->transport == BT_TRANSPORT_LE) L2CA_DEREGISTER_COC(p_ccb->psm);
1160 }
1161
1162 extern void gap_attr_db_init(void);
1163
1164 /*
1165 * This routine should not be called except once per stack invocation.
1166 */
GAP_Init(void)1167 void GAP_Init(void) {
1168 gap_conn_init();
1169 gap_attr_db_init();
1170 }
1171