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