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