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