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, 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*******************************************************************************/
122UINT16 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*******************************************************************************/
253UINT16 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*******************************************************************************/
292UINT16 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*******************************************************************************/
357int 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*******************************************************************************/
398UINT16 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*******************************************************************************/
437UINT16 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*******************************************************************************/
505UINT16 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*******************************************************************************/
585UINT16 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*******************************************************************************/
623UINT16 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*******************************************************************************/
651UINT8 *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*******************************************************************************/
683UINT16 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*******************************************************************************/
705UINT16 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*******************************************************************************/
727static 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*******************************************************************************/
780static 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*******************************************************************************/
802static 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*******************************************************************************/
836static 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*******************************************************************************/
880static 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*******************************************************************************/
930static 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*******************************************************************************/
968static 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*******************************************************************************/
995static 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*******************************************************************************/
1033static 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*******************************************************************************/
1080static 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*******************************************************************************/
1107static 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*******************************************************************************/
1134static 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*******************************************************************************/
1167static 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*******************************************************************************/
1207void 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*******************************************************************************/
1235void 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