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 /* Fill in eL2CAP parameter data */
237 if (p_ccb->cfg.fcr_present) {
238 if (ertm_info == NULL) {
239 p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
240 p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
241 p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
242 p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
243 p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
244 } else {
245 p_ccb->ertm_info = *ertm_info;
246 }
247 }
248
249 /* Register the PSM with L2CAP */
250 if (transport == BT_TRANSPORT_BR_EDR) {
251 p_ccb->psm = L2CA_Register(psm, &conn.reg_info, false /* enable_snoop */,
252 &p_ccb->ertm_info, L2CAP_MTU_SIZE);
253 if (p_ccb->psm == 0) {
254 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
255 psm);
256 gap_release_ccb(p_ccb);
257 return (GAP_INVALID_HANDLE);
258 }
259 }
260
261 if (transport == BT_TRANSPORT_LE) {
262 p_ccb->psm = L2CA_RegisterLECoc(psm, (tL2CAP_APPL_INFO*)&conn.reg_info);
263 if (p_ccb->psm == 0) {
264 LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
265 psm);
266 gap_release_ccb(p_ccb);
267 return (GAP_INVALID_HANDLE);
268 }
269 }
270
271 /* Register with Security Manager for the specific security level */
272 if (!BTM_SetSecurityLevel((uint8_t)!is_server, p_serv_name, p_ccb->service_id,
273 security, p_ccb->psm, 0, 0)) {
274 LOG(ERROR) << "GAP_CONN - Security Error";
275 gap_release_ccb(p_ccb);
276 return (GAP_INVALID_HANDLE);
277 }
278
279 /* optional FCR channel modes */
280 if (ertm_info != NULL) {
281 p_ccb->ertm_info.allowed_modes =
282 (chan_mode_mask) ? chan_mode_mask : (uint8_t)L2CAP_FCR_CHAN_OPT_BASIC;
283 }
284
285 if (is_server) {
286 p_ccb->con_flags |=
287 GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
288 p_ccb->con_state = GAP_CCB_STATE_LISTENING;
289 return (p_ccb->gap_handle);
290 } else {
291 /* We are the originator of this connection */
292 p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
293
294 /* Transition to the next appropriate state, waiting for connection confirm.
295 */
296 p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
297
298 /* mark security done flag, when security is not required */
299 if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE |
300 BTM_SEC_OUT_ENCRYPT)) == 0)
301 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
302
303 /* Check if L2CAP started the connection process */
304 if (p_rem_bda && (transport == BT_TRANSPORT_BR_EDR)) {
305 cid = L2CA_ErtmConnectReq(p_ccb->psm, *p_rem_bda, &p_ccb->ertm_info);
306 if (cid != 0) {
307 p_ccb->connection_id = cid;
308 return (p_ccb->gap_handle);
309 }
310 }
311
312 if (p_rem_bda && (transport == BT_TRANSPORT_LE)) {
313 cid = L2CA_ConnectLECocReq(p_ccb->psm, *p_rem_bda, &p_ccb->local_coc_cfg);
314 if (cid != 0) {
315 p_ccb->connection_id = cid;
316 return (p_ccb->gap_handle);
317 }
318 }
319
320 gap_release_ccb(p_ccb);
321 return (GAP_INVALID_HANDLE);
322 }
323 }
324
325 /*******************************************************************************
326 *
327 * Function GAP_ConnClose
328 *
329 * Description This function is called to close a connection.
330 *
331 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
332 *
333 * Returns BT_PASS - closed OK
334 * GAP_ERR_BAD_HANDLE - invalid handle
335 *
336 ******************************************************************************/
GAP_ConnClose(uint16_t gap_handle)337 uint16_t GAP_ConnClose(uint16_t gap_handle) {
338 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
339
340 DVLOG(1) << StringPrintf("GAP_CONN - close handle: 0x%x", gap_handle);
341
342 if (p_ccb) {
343 /* Check if we have a connection ID */
344 if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
345 L2CA_DisconnectReq(p_ccb->connection_id);
346
347 gap_release_ccb(p_ccb);
348
349 return (BT_PASS);
350 }
351
352 return (GAP_ERR_BAD_HANDLE);
353 }
354
355 /*******************************************************************************
356 *
357 * Function GAP_ConnReadData
358 *
359 * Description Normally not GKI aware application will call this function
360 * after receiving GAP_EVT_RXDATA event.
361 *
362 * Parameters: handle - Handle of the connection returned in the Open
363 * p_data - Data area
364 * max_len - Byte count requested
365 * p_len - Byte count received
366 *
367 * Returns BT_PASS - data read
368 * GAP_ERR_BAD_HANDLE - invalid handle
369 * GAP_NO_DATA_AVAIL - no data available
370 *
371 ******************************************************************************/
GAP_ConnReadData(uint16_t gap_handle,uint8_t * p_data,uint16_t max_len,uint16_t * p_len)372 uint16_t GAP_ConnReadData(uint16_t gap_handle, uint8_t* p_data,
373 uint16_t max_len, uint16_t* p_len) {
374 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
375 uint16_t copy_len;
376
377 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
378
379 *p_len = 0;
380
381 if (fixed_queue_is_empty(p_ccb->rx_queue)) return (GAP_NO_DATA_AVAIL);
382
383 mutex_global_lock();
384
385 while (max_len) {
386 BT_HDR* p_buf =
387 static_cast<BT_HDR*>(fixed_queue_try_peek_first(p_ccb->rx_queue));
388 if (p_buf == NULL) break;
389
390 copy_len = (p_buf->len > max_len) ? max_len : p_buf->len;
391 max_len -= copy_len;
392 *p_len += copy_len;
393 if (p_data) {
394 memcpy(p_data, (uint8_t*)(p_buf + 1) + p_buf->offset, copy_len);
395 p_data += copy_len;
396 }
397
398 if (p_buf->len > copy_len) {
399 p_buf->offset += copy_len;
400 p_buf->len -= copy_len;
401 break;
402 }
403 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
404 }
405
406 p_ccb->rx_queue_size -= *p_len;
407
408 mutex_global_unlock();
409
410 DVLOG(1) << StringPrintf(
411 "GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
412 p_ccb->rx_queue_size, *p_len);
413
414 return (BT_PASS);
415 }
416
417 /*******************************************************************************
418 *
419 * Function GAP_GetRxQueueCnt
420 *
421 * Description This function return number of bytes on the rx queue.
422 *
423 * Parameters: handle - Handle returned in the GAP_ConnOpen
424 * p_rx_queue_count - Pointer to return queue count in.
425 *
426 *
427 ******************************************************************************/
GAP_GetRxQueueCnt(uint16_t handle,uint32_t * p_rx_queue_count)428 int GAP_GetRxQueueCnt(uint16_t handle, uint32_t* p_rx_queue_count) {
429 tGAP_CCB* p_ccb;
430 int rc = BT_PASS;
431
432 /* Check that handle is valid */
433 if (handle < GAP_MAX_CONNECTIONS) {
434 p_ccb = &conn.ccb_pool[handle];
435
436 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
437 *p_rx_queue_count = p_ccb->rx_queue_size;
438 } else
439 rc = GAP_INVALID_HANDLE;
440 } else
441 rc = GAP_INVALID_HANDLE;
442
443 DVLOG(1) << StringPrintf("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
444 rc, *p_rx_queue_count);
445
446 return (rc);
447 }
448
449 /*******************************************************************************
450 *
451 * Function GAP_ConnBTRead
452 *
453 * Description Bluetooth-aware applications will call this function after
454 * receiving GAP_EVT_RXDATA event.
455 *
456 * Parameters: handle - Handle of the connection returned in the Open
457 * pp_buf - pointer to address of buffer with data,
458 *
459 * Returns BT_PASS - data read
460 * GAP_ERR_BAD_HANDLE - invalid handle
461 * GAP_NO_DATA_AVAIL - no data available
462 *
463 ******************************************************************************/
GAP_ConnBTRead(uint16_t gap_handle,BT_HDR ** pp_buf)464 uint16_t GAP_ConnBTRead(uint16_t gap_handle, BT_HDR** pp_buf) {
465 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
466 BT_HDR* p_buf;
467
468 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
469
470 p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->rx_queue);
471
472 if (p_buf) {
473 *pp_buf = p_buf;
474
475 p_ccb->rx_queue_size -= p_buf->len;
476 return (BT_PASS);
477 } else {
478 *pp_buf = NULL;
479 return (GAP_NO_DATA_AVAIL);
480 }
481 }
482
483 /* Try to write the queued data to l2ca. Return true on success, or if queue is
484 * congested. False if error occured when writing. */
gap_try_write_queued_data(tGAP_CCB * p_ccb)485 static bool gap_try_write_queued_data(tGAP_CCB* p_ccb) {
486 if (p_ccb->is_congested) return true;
487
488 /* Send the buffer through L2CAP */
489 BT_HDR* p_buf;
490 while ((p_buf = (BT_HDR*)fixed_queue_try_dequeue(p_ccb->tx_queue)) != NULL) {
491 uint8_t status = L2CA_DataWrite(p_ccb->connection_id, p_buf);
492
493 if (status == L2CAP_DW_CONGESTED) {
494 p_ccb->is_congested = true;
495 return true;
496 } else if (status != L2CAP_DW_SUCCESS)
497 return false;
498 }
499 return true;
500 }
501
502 /*******************************************************************************
503 *
504 * Function GAP_ConnWriteData
505 *
506 * Description Normally not GKI aware application will call this function
507 * to send data to the connection.
508 *
509 * Parameters: handle - Handle of the connection returned in the Open
510 * msg - pointer to single SDU to send. This function
511 * will take ownership of it.
512 *
513 * Returns BT_PASS - data read
514 * GAP_ERR_BAD_HANDLE - invalid handle
515 * GAP_ERR_BAD_STATE - connection not established
516 * GAP_CONGESTION - system is congested
517 *
518 ******************************************************************************/
GAP_ConnWriteData(uint16_t gap_handle,BT_HDR * msg)519 uint16_t GAP_ConnWriteData(uint16_t gap_handle, BT_HDR* msg) {
520 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
521
522 if (!p_ccb) {
523 osi_free(msg);
524 return GAP_ERR_BAD_HANDLE;
525 }
526
527 if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED) {
528 osi_free(msg);
529 return GAP_ERR_BAD_STATE;
530 }
531
532 if (msg->len > p_ccb->rem_mtu_size) {
533 osi_free(msg);
534 return GAP_ERR_ILL_PARM;
535 }
536
537 DVLOG(1) << StringPrintf("GAP_WriteData %d bytes", msg->len);
538
539 fixed_queue_enqueue(p_ccb->tx_queue, msg);
540
541 if (!gap_try_write_queued_data(p_ccb)) return GAP_ERR_BAD_STATE;
542
543 return (BT_PASS);
544 }
545
546 /*******************************************************************************
547 *
548 * Function GAP_ConnReconfig
549 *
550 * Description Applications can call this function to reconfigure the
551 * connection.
552 *
553 * Parameters: handle - Handle of the connection
554 * p_cfg - Pointer to new configuration
555 *
556 * Returns BT_PASS - config process started
557 * GAP_ERR_BAD_HANDLE - invalid handle
558 *
559 ******************************************************************************/
GAP_ConnReconfig(uint16_t gap_handle,tL2CAP_CFG_INFO * p_cfg)560 uint16_t GAP_ConnReconfig(uint16_t gap_handle, tL2CAP_CFG_INFO* p_cfg) {
561 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
562
563 if (!p_ccb) return (GAP_ERR_BAD_HANDLE);
564
565 p_ccb->cfg = *p_cfg;
566
567 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
568 L2CA_ConfigReq(p_ccb->connection_id, p_cfg);
569
570 return (BT_PASS);
571 }
572
573 /*******************************************************************************
574 *
575 * Function GAP_ConnSetIdleTimeout
576 *
577 * Description Higher layers call this function to set the idle timeout for
578 * a connection, or for all future connections. The "idle
579 * timeout" is the amount of time that a connection can remain
580 * up with no L2CAP channels on it. A timeout of zero means
581 * that the connection will be torn down immediately when the
582 * last channel is removed. A timeout of 0xFFFF means no
583 * timeout. Values are in seconds.
584 *
585 * Parameters: handle - Handle of the connection
586 * timeout - in secs
587 * 0 = immediate disconnect when last channel is
588 * removed
589 * 0xFFFF = no idle timeout
590 *
591 * Returns BT_PASS - config process started
592 * GAP_ERR_BAD_HANDLE - invalid handle
593 *
594 ******************************************************************************/
GAP_ConnSetIdleTimeout(uint16_t gap_handle,uint16_t timeout)595 uint16_t GAP_ConnSetIdleTimeout(uint16_t gap_handle, uint16_t timeout) {
596 tGAP_CCB* p_ccb;
597
598 p_ccb = gap_find_ccb_by_handle(gap_handle);
599 if (p_ccb == NULL) return (GAP_ERR_BAD_HANDLE);
600
601 if (L2CA_SetIdleTimeout(p_ccb->connection_id, timeout, false))
602 return (BT_PASS);
603 else
604 return (GAP_ERR_BAD_HANDLE);
605 }
606
607 /*******************************************************************************
608 *
609 * Function GAP_ConnGetRemoteAddr
610 *
611 * Description This function is called to get the remote BD address
612 * of a connection.
613 *
614 * Parameters: handle - Handle of the connection returned by GAP_ConnOpen
615 *
616 * Returns BT_PASS - closed OK
617 * GAP_ERR_BAD_HANDLE - invalid handle
618 *
619 ******************************************************************************/
GAP_ConnGetRemoteAddr(uint16_t gap_handle)620 const RawAddress* GAP_ConnGetRemoteAddr(uint16_t gap_handle) {
621 tGAP_CCB* p_ccb = gap_find_ccb_by_handle(gap_handle);
622
623 DVLOG(1) << __func__ << " gap_handle = " << gap_handle;
624
625 if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING)) {
626 DVLOG(1) << __func__ << " BDA: " << p_ccb->rem_dev_address;
627 return &p_ccb->rem_dev_address;
628 } else {
629 DVLOG(1) << __func__ << " return Error ";
630 return nullptr;
631 }
632 }
633
634 /*******************************************************************************
635 *
636 * Function GAP_ConnGetRemMtuSize
637 *
638 * Description Returns the remote device's MTU size
639 *
640 * Parameters: handle - Handle of the connection
641 *
642 * Returns uint16_t - maximum size buffer that can be transmitted to
643 * the peer
644 *
645 ******************************************************************************/
GAP_ConnGetRemMtuSize(uint16_t gap_handle)646 uint16_t GAP_ConnGetRemMtuSize(uint16_t gap_handle) {
647 tGAP_CCB* p_ccb;
648
649 p_ccb = gap_find_ccb_by_handle(gap_handle);
650 if (p_ccb == NULL) return (0);
651
652 return (p_ccb->rem_mtu_size);
653 }
654
655 /*******************************************************************************
656 *
657 * Function GAP_ConnGetL2CAPCid
658 *
659 * Description Returns the L2CAP channel id
660 *
661 * Parameters: handle - Handle of the connection
662 *
663 * Returns uint16_t - The L2CAP channel id
664 * 0, if error
665 *
666 ******************************************************************************/
GAP_ConnGetL2CAPCid(uint16_t gap_handle)667 uint16_t GAP_ConnGetL2CAPCid(uint16_t gap_handle) {
668 tGAP_CCB* p_ccb;
669
670 p_ccb = gap_find_ccb_by_handle(gap_handle);
671 if (p_ccb == NULL) return (0);
672
673 return (p_ccb->connection_id);
674 }
675
676 /*******************************************************************************
677 *
678 * Function gap_tx_connect_ind
679 *
680 * Description Sends out GAP_EVT_TX_EMPTY when transmission has been
681 * completed.
682 *
683 * Returns void
684 *
685 ******************************************************************************/
gap_tx_complete_ind(uint16_t l2cap_cid,uint16_t sdu_sent)686 void gap_tx_complete_ind(uint16_t l2cap_cid, uint16_t sdu_sent) {
687 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
688 if (p_ccb == NULL) return;
689
690 if ((p_ccb->con_state == GAP_CCB_STATE_CONNECTED) && (sdu_sent == 0xFFFF)) {
691 DVLOG(1) << StringPrintf("%s: GAP_EVT_TX_EMPTY", __func__);
692 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_TX_EMPTY, nullptr);
693 }
694 }
695
gap_credits_received_cb(uint16_t l2cap_cid,uint16_t credits_received,uint16_t credit_count)696 void gap_credits_received_cb(uint16_t l2cap_cid, uint16_t credits_received,
697 uint16_t credit_count) {
698 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(l2cap_cid);
699 if (!p_ccb) return;
700
701 tGAP_CB_DATA data{.coc_credits = {.credits_received = credits_received,
702 .credit_count = credit_count}};
703 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_LE_COC_CREDITS, &data);
704 }
705
706 /*******************************************************************************
707 *
708 * Function gap_connect_ind
709 *
710 * Description This function handles an inbound connection indication
711 * from L2CAP. This is the case where we are acting as a
712 * server.
713 *
714 * Returns void
715 *
716 ******************************************************************************/
gap_connect_ind(const RawAddress & bd_addr,uint16_t l2cap_cid,uint16_t psm,uint8_t l2cap_id)717 static void gap_connect_ind(const RawAddress& bd_addr, uint16_t l2cap_cid,
718 uint16_t psm, uint8_t l2cap_id) {
719 uint16_t xx;
720 tGAP_CCB* p_ccb;
721
722 /* See if we have a CCB listening for the connection */
723 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
724 if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING) && (p_ccb->psm == psm) &&
725 (!p_ccb->rem_addr_specified || (bd_addr == p_ccb->rem_dev_address)))
726 break;
727 }
728
729 if (xx == GAP_MAX_CONNECTIONS) {
730 LOG(WARNING) << "*******";
731 LOG(WARNING) << "WARNING: GAP Conn Indication for Unexpected Bd "
732 "Addr...Disconnecting";
733 LOG(WARNING) << "*******";
734
735 /* Disconnect because it is an unexpected connection */
736 L2CA_DisconnectReq(l2cap_cid);
737 return;
738 }
739
740 /* Transition to the next appropriate state, waiting for config setup. */
741 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
742 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
743
744 /* Save the BD Address and Channel ID. */
745 p_ccb->rem_dev_address = bd_addr;
746 p_ccb->connection_id = l2cap_cid;
747
748 /* Send response to the L2CAP layer. */
749 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
750 L2CA_ErtmConnectRsp(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK,
751 L2CAP_CONN_OK, &p_ccb->ertm_info);
752
753 if (p_ccb->transport == BT_TRANSPORT_LE) {
754 L2CA_ConnectLECocRsp(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK,
755 L2CAP_CONN_OK, &p_ccb->local_coc_cfg);
756
757 /* get the remote coc configuration */
758 L2CA_GetPeerLECocConfig(l2cap_cid, &p_ccb->peer_coc_cfg);
759 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
760
761 /* configuration is not required for LE COC */
762 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
763 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
764 gap_checks_con_flags(p_ccb);
765 }
766
767 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x",
768 p_ccb->connection_id);
769
770 /* Send a Configuration Request. */
771 if (p_ccb->transport == BT_TRANSPORT_BR_EDR)
772 L2CA_ConfigReq(l2cap_cid, &p_ccb->cfg);
773 }
774
775 /*******************************************************************************
776 *
777 * Function gap_checks_con_flags
778 *
779 * Description This function processes the L2CAP configuration indication
780 * event.
781 *
782 * Returns void
783 *
784 ******************************************************************************/
gap_checks_con_flags(tGAP_CCB * p_ccb)785 static void gap_checks_con_flags(tGAP_CCB* p_ccb) {
786 DVLOG(1) << __func__ << " conn_flags:0x" << +p_ccb->con_flags;
787 /* if all the required con_flags are set, report the OPEN event now */
788 if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE) {
789 p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
790
791 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_OPENED, nullptr);
792 }
793 }
794
795 /*******************************************************************************
796 *
797 * Function gap_sec_check_complete
798 *
799 * Description The function called when Security Manager finishes
800 * verification of the service side connection
801 *
802 * Returns void
803 *
804 ******************************************************************************/
gap_sec_check_complete(const RawAddress *,tBT_TRANSPORT,void * p_ref_data,uint8_t res)805 static void gap_sec_check_complete(const RawAddress*, tBT_TRANSPORT,
806 void* p_ref_data, uint8_t res) {
807 tGAP_CCB* p_ccb = (tGAP_CCB*)p_ref_data;
808
809 DVLOG(1) << StringPrintf(
810 "gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
811 p_ccb->con_state, p_ccb->con_flags, res);
812 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) return;
813
814 if (res == BTM_SUCCESS) {
815 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
816 gap_checks_con_flags(p_ccb);
817 } else {
818 /* security failed - disconnect the channel */
819 L2CA_DisconnectReq(p_ccb->connection_id);
820 }
821 }
822
823 /*******************************************************************************
824 *
825 * Function gap_connect_cfm
826 *
827 * Description This function handles the connect confirm events
828 * from L2CAP. This is the case when we are acting as a
829 * client and have sent a connect request.
830 *
831 * Returns void
832 *
833 ******************************************************************************/
gap_connect_cfm(uint16_t l2cap_cid,uint16_t result)834 static void gap_connect_cfm(uint16_t l2cap_cid, uint16_t result) {
835 tGAP_CCB* p_ccb;
836
837 /* Find CCB based on CID */
838 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
839 if (p_ccb == NULL) return;
840
841 /* initiate security process, if needed */
842 if ((p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0 &&
843 p_ccb->transport != BT_TRANSPORT_LE) {
844 btm_sec_mx_access_request(p_ccb->rem_dev_address, p_ccb->psm, true, 0, 0,
845 &gap_sec_check_complete, p_ccb);
846 }
847
848 /* If the connection response contains success status, then */
849 /* Transition to the next state and startup the timer. */
850 if ((result == L2CAP_CONN_OK) &&
851 (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP)) {
852 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) {
853 p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
854
855 /* Send a Configuration Request. */
856 L2CA_ConfigReq(l2cap_cid, &p_ccb->cfg);
857 }
858
859 if (p_ccb->transport == BT_TRANSPORT_LE) {
860 /* get the remote coc configuration */
861 L2CA_GetPeerLECocConfig(l2cap_cid, &p_ccb->peer_coc_cfg);
862 p_ccb->rem_mtu_size = p_ccb->peer_coc_cfg.mtu;
863
864 /* configuration is not required for LE COC */
865 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
866 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
867 p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
868 gap_checks_con_flags(p_ccb);
869 }
870 } else {
871 /* Tell the user if there is a callback */
872 if (p_ccb->p_callback)
873 (*p_ccb->p_callback)(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
874
875 gap_release_ccb(p_ccb);
876 }
877 }
878
879 /*******************************************************************************
880 *
881 * Function gap_config_ind
882 *
883 * Description This function processes the L2CAP configuration indication
884 * event.
885 *
886 * Returns void
887 *
888 ******************************************************************************/
gap_config_ind(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)889 static void gap_config_ind(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
890 tGAP_CCB* p_ccb;
891 uint16_t local_mtu_size;
892
893 /* Find CCB based on CID */
894 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
895 if (p_ccb == NULL) return;
896
897 /* Remember the remote MTU size */
898
899 if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE) {
900 local_mtu_size =
901 p_ccb->ertm_info.user_tx_buf_size - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
902 } else
903 local_mtu_size = L2CAP_MTU_SIZE;
904
905 if ((!p_cfg->mtu_present) || (p_cfg->mtu > local_mtu_size)) {
906 p_ccb->rem_mtu_size = local_mtu_size;
907 } else
908 p_ccb->rem_mtu_size = p_cfg->mtu;
909
910 /* For now, always accept configuration from the other side */
911 p_cfg->flush_to_present = false;
912 p_cfg->mtu_present = false;
913 p_cfg->result = L2CAP_CFG_OK;
914 p_cfg->fcs_present = false;
915
916 L2CA_ConfigRsp(l2cap_cid, p_cfg);
917
918 p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
919
920 gap_checks_con_flags(p_ccb);
921 }
922
923 /*******************************************************************************
924 *
925 * Function gap_config_cfm
926 *
927 * Description This function processes the L2CAP configuration confirmation
928 * event.
929 *
930 * Returns void
931 *
932 ******************************************************************************/
gap_config_cfm(uint16_t l2cap_cid,tL2CAP_CFG_INFO * p_cfg)933 static void gap_config_cfm(uint16_t l2cap_cid, tL2CAP_CFG_INFO* p_cfg) {
934 tGAP_CCB* p_ccb;
935
936 /* Find CCB based on CID */
937 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
938 if (p_ccb == NULL) return;
939
940 if (p_cfg->result == L2CAP_CFG_OK) {
941 p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
942
943 if (p_ccb->cfg.fcr_present)
944 p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
945 else
946 p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
947
948 gap_checks_con_flags(p_ccb);
949 } else {
950 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
951 gap_release_ccb(p_ccb);
952 }
953 }
954
955 /*******************************************************************************
956 *
957 * Function gap_disconnect_ind
958 *
959 * Description This function handles a disconnect event from L2CAP. If
960 * requested to, we ack the disconnect before dropping the CCB
961 *
962 * Returns void
963 *
964 ******************************************************************************/
gap_disconnect_ind(uint16_t l2cap_cid,bool ack_needed)965 static void gap_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
966 tGAP_CCB* p_ccb;
967
968 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
969
970 /* Find CCB based on CID */
971 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
972 if (p_ccb == NULL) return;
973
974 if (ack_needed) L2CA_DisconnectRsp(l2cap_cid);
975
976 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_CLOSED, nullptr);
977 gap_release_ccb(p_ccb);
978 }
979
980 /*******************************************************************************
981 *
982 * Function gap_data_ind
983 *
984 * Description This function is called when data is received from L2CAP.
985 *
986 * Returns void
987 *
988 ******************************************************************************/
gap_data_ind(uint16_t l2cap_cid,BT_HDR * p_msg)989 static void gap_data_ind(uint16_t l2cap_cid, BT_HDR* p_msg) {
990 tGAP_CCB* p_ccb;
991
992 /* Find CCB based on CID */
993 p_ccb = gap_find_ccb_by_cid(l2cap_cid);
994 if (p_ccb == NULL) {
995 osi_free(p_msg);
996 return;
997 }
998
999 if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED) {
1000 fixed_queue_enqueue(p_ccb->rx_queue, p_msg);
1001
1002 p_ccb->rx_queue_size += p_msg->len;
1003 /*
1004 DVLOG(1) << StringPrintf ("gap_data_ind - rx_queue_size=%d, msg len=%d",
1005 p_ccb->rx_queue_size, p_msg->len);
1006 */
1007
1008 p_ccb->p_callback(p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL, nullptr);
1009 } else {
1010 osi_free(p_msg);
1011 }
1012 }
1013
1014 /*******************************************************************************
1015 *
1016 * Function gap_congestion_ind
1017 *
1018 * Description This is a callback function called by L2CAP when
1019 * data L2CAP congestion status changes
1020 *
1021 ******************************************************************************/
gap_congestion_ind(uint16_t lcid,bool is_congested)1022 static void gap_congestion_ind(uint16_t lcid, bool is_congested) {
1023 DVLOG(1) << StringPrintf("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
1024 is_congested, lcid);
1025
1026 tGAP_CCB* p_ccb = gap_find_ccb_by_cid(lcid); /* Find CCB based on CID */
1027 if (!p_ccb) return;
1028
1029 p_ccb->is_congested = is_congested;
1030
1031 p_ccb->p_callback(
1032 p_ccb->gap_handle,
1033 (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED,
1034 nullptr);
1035
1036 gap_try_write_queued_data(p_ccb);
1037 }
1038
1039 /*******************************************************************************
1040 *
1041 * Function gap_find_ccb_by_cid
1042 *
1043 * Description This function searches the CCB table for an entry with the
1044 * passed CID.
1045 *
1046 * Returns the CCB address, or NULL if not found.
1047 *
1048 ******************************************************************************/
gap_find_ccb_by_cid(uint16_t cid)1049 static tGAP_CCB* gap_find_ccb_by_cid(uint16_t cid) {
1050 uint16_t xx;
1051 tGAP_CCB* p_ccb;
1052
1053 /* Look through each connection control block */
1054 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1055 if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) &&
1056 (p_ccb->connection_id == cid))
1057 return (p_ccb);
1058 }
1059
1060 /* If here, not found */
1061 return (NULL);
1062 }
1063
1064 /*******************************************************************************
1065 *
1066 * Function gap_find_ccb_by_handle
1067 *
1068 * Description This function searches the CCB table for an entry with the
1069 * passed handle.
1070 *
1071 * Returns the CCB address, or NULL if not found.
1072 *
1073 ******************************************************************************/
gap_find_ccb_by_handle(uint16_t handle)1074 static tGAP_CCB* gap_find_ccb_by_handle(uint16_t handle) {
1075 tGAP_CCB* p_ccb;
1076
1077 /* Check that handle is valid */
1078 if (handle < GAP_MAX_CONNECTIONS) {
1079 p_ccb = &conn.ccb_pool[handle];
1080
1081 if (p_ccb->con_state != GAP_CCB_STATE_IDLE) return (p_ccb);
1082 }
1083
1084 /* If here, handle points to invalid connection */
1085 return (NULL);
1086 }
1087
1088 /*******************************************************************************
1089 *
1090 * Function gap_allocate_ccb
1091 *
1092 * Description This function allocates a new CCB.
1093 *
1094 * Returns CCB address, or NULL if none available.
1095 *
1096 ******************************************************************************/
gap_allocate_ccb(void)1097 static tGAP_CCB* gap_allocate_ccb(void) {
1098 uint16_t xx;
1099 tGAP_CCB* p_ccb;
1100
1101 /* Look through each connection control block for a free one */
1102 for (xx = 0, p_ccb = conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++) {
1103 if (p_ccb->con_state == GAP_CCB_STATE_IDLE) {
1104 memset(p_ccb, 0, sizeof(tGAP_CCB));
1105 p_ccb->tx_queue = fixed_queue_new(SIZE_MAX);
1106 p_ccb->rx_queue = fixed_queue_new(SIZE_MAX);
1107
1108 p_ccb->gap_handle = xx;
1109 p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
1110
1111 return (p_ccb);
1112 }
1113 }
1114
1115 /* If here, no free CCB found */
1116 return (NULL);
1117 }
1118
1119 /*******************************************************************************
1120 *
1121 * Function gap_release_ccb
1122 *
1123 * Description This function releases a CCB.
1124 *
1125 * Returns void
1126 *
1127 ******************************************************************************/
gap_release_ccb(tGAP_CCB * p_ccb)1128 static void gap_release_ccb(tGAP_CCB* p_ccb) {
1129 /* Drop any buffers we may be holding */
1130 p_ccb->rx_queue_size = 0;
1131
1132 while (!fixed_queue_is_empty(p_ccb->rx_queue))
1133 osi_free(fixed_queue_try_dequeue(p_ccb->rx_queue));
1134 fixed_queue_free(p_ccb->rx_queue, NULL);
1135 p_ccb->rx_queue = NULL;
1136
1137 while (!fixed_queue_is_empty(p_ccb->tx_queue))
1138 osi_free(fixed_queue_try_dequeue(p_ccb->tx_queue));
1139 fixed_queue_free(p_ccb->tx_queue, NULL);
1140 p_ccb->tx_queue = NULL;
1141
1142 p_ccb->con_state = GAP_CCB_STATE_IDLE;
1143
1144 /* If no-one else is using the PSM, deregister from L2CAP */
1145 tGAP_CCB* p_ccb_local = conn.ccb_pool;
1146 for (uint16_t i = 0; i < GAP_MAX_CONNECTIONS; i++, p_ccb_local++) {
1147 if ((p_ccb_local->con_state != GAP_CCB_STATE_IDLE) &&
1148 (p_ccb_local->psm == p_ccb->psm)) {
1149 DVLOG(1) << __func__ << " : " << +p_ccb_local->psm
1150 << " PSM is still in use, do not deregister";
1151 return;
1152 }
1153 }
1154
1155 /* Free the security record for this PSM */
1156 BTM_SecClrService(p_ccb->service_id);
1157 if (p_ccb->transport == BT_TRANSPORT_BR_EDR) L2CA_Deregister(p_ccb->psm);
1158 if (p_ccb->transport == BT_TRANSPORT_LE) L2CA_DeregisterLECoc(p_ccb->psm);
1159 }
1160
1161 extern void gap_attr_db_init(void);
1162
1163 /*
1164 * This routine should not be called except once per stack invocation.
1165 */
GAP_Init(void)1166 void GAP_Init(void) {
1167 gap_conn_init();
1168 gap_attr_db_init();
1169 }
1170