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