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