• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(psm, &conn.reg_info, false /* enable_snoop */);
239     if (p_ccb->psm == 0) {
240       LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
241                                  psm);
242       gap_release_ccb(p_ccb);
243       return (GAP_INVALID_HANDLE);
244     }
245   }
246 
247   if (transport == BT_TRANSPORT_LE) {
248     p_ccb->psm = L2CA_REGISTER_COC(
249         psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
250     if (p_ccb->psm == 0) {
251       LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
252                                  psm);
253       gap_release_ccb(p_ccb);
254       return (GAP_INVALID_HANDLE);
255     }
256   }
257 
258   /* Register with Security Manager for the specific security level */
259   if (!BTM_SetSecurityLevel((uint8_t)!is_server, p_serv_name, p_ccb->service_id,
260                             security, p_ccb->psm, 0, 0)) {
261     LOG(ERROR) << "GAP_CONN - Security Error";
262     gap_release_ccb(p_ccb);
263     return (GAP_INVALID_HANDLE);
264   }
265 
266   /* Fill in eL2CAP parameter data */
267   if (p_ccb->cfg.fcr_present) {
268     if (ertm_info == NULL) {
269       p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
270       p_ccb->ertm_info.user_rx_buf_size = GAP_DATA_BUF_SIZE;
271       p_ccb->ertm_info.user_tx_buf_size = GAP_DATA_BUF_SIZE;
272       p_ccb->ertm_info.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
273       p_ccb->ertm_info.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
274     } else {
275       p_ccb->ertm_info = *ertm_info;
276     }
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_CONNECT_REQ(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_CONNECT_COC_REQ(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_DISCONNECT_REQ(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_DATA_WRITE(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_CONFIG_REQ(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_DISCONNECT_REQ(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_CONNECT_RSP(bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK,
751                      &p_ccb->ertm_info);
752 
753   if (p_ccb->transport == BT_TRANSPORT_LE) {
754     L2CA_CONNECT_COC_RSP(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_GET_PEER_COC_CONFIG(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_CONFIG_REQ(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_DISCONNECT_REQ(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_CONFIG_REQ(l2cap_cid, &p_ccb->cfg);
857     }
858 
859     if (p_ccb->transport == BT_TRANSPORT_LE) {
860       /* get the remote coc configuration */
861       L2CA_GET_PEER_COC_CONFIG(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 he has 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_CONFIG_RSP(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_DISCONNECT_RSP(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_DEREGISTER_COC(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