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