1/******************************************************************************
2 *
3 *  Copyright (C) 2009-2012 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 *
21 *  this file contains functions relating to BLE management.
22 *
23 ******************************************************************************/
24
25#include <string.h>
26#include "bt_target.h"
27#include "bt_utils.h"
28#include "l2cdefs.h"
29#include "l2c_int.h"
30#include "btu.h"
31#include "btm_int.h"
32#include "hcimsgs.h"
33#include "device/include/controller.h"
34#include "stack_config.h"
35
36#if (BLE_INCLUDED == TRUE)
37
38extern fixed_queue_t *btu_general_alarm_queue;
39
40static void l2cble_start_conn_update (tL2C_LCB *p_lcb);
41
42/*******************************************************************************
43**
44**  Function        L2CA_CancelBleConnectReq
45**
46**  Description     Cancel a pending connection attempt to a BLE device.
47**
48**  Parameters:     BD Address of remote
49**
50**  Return value:   TRUE if connection was cancelled
51**
52*******************************************************************************/
53BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
54{
55    tL2C_LCB *p_lcb;
56
57    /* There can be only one BLE connection request outstanding at a time */
58    if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
59    {
60        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
61        return(FALSE);
62    }
63
64    if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
65    {
66        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different  BDA Connecting: %08x%04x  Cancel: %08x%04x",
67                              (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
68                              (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
69                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
70
71        return(FALSE);
72    }
73
74    if (btsnd_hcic_ble_create_conn_cancel())
75    {
76        p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
77        /* Do not remove lcb if an LE link is already up as a peripheral */
78        if (p_lcb != NULL &&
79            !(p_lcb->link_role == HCI_ROLE_SLAVE && btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE) != NULL))
80        {
81            p_lcb->disc_reason = L2CAP_CONN_CANCEL;
82            l2cu_release_lcb (p_lcb);
83        }
84        /* update state to be cancel, wait for connection cancel complete */
85        btm_ble_set_conn_st (BLE_CONN_CANCEL);
86
87        return(TRUE);
88    }
89    else
90        return(FALSE);
91}
92
93/*******************************************************************************
94**
95**  Function        L2CA_UpdateBleConnParams
96**
97**  Description     Update BLE connection parameters.
98**
99**  Parameters:     BD Address of remote
100**
101**  Return value:   TRUE if update started
102**
103*******************************************************************************/
104BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
105                                            UINT16 latency, UINT16 timeout)
106{
107    tL2C_LCB            *p_lcb;
108    tACL_CONN           *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
109
110    /* See if we have a link control block for the remote device */
111    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
112
113    /* If we don't have one, create one and accept the connection. */
114    if (!p_lcb || !p_acl_cb)
115    {
116        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
117                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
118                              (rem_bda[4]<<8)+rem_bda[5]);
119        return(FALSE);
120    }
121
122    if (p_lcb->transport != BT_TRANSPORT_LE)
123    {
124        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
125                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
126                              (rem_bda[4]<<8)+rem_bda[5]);
127        return(FALSE);
128    }
129
130    p_lcb->min_interval = min_int;
131    p_lcb->max_interval = max_int;
132    p_lcb->latency = latency;
133    p_lcb->timeout = timeout;
134    p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
135
136    l2cble_start_conn_update(p_lcb);
137
138    return(TRUE);
139}
140
141
142/*******************************************************************************
143**
144**  Function        L2CA_EnableUpdateBleConnParams
145**
146**  Description     Enable or disable update based on the request from the peer
147**
148**  Parameters:     BD Address of remote
149**
150**  Return value:   TRUE if update started
151**
152*******************************************************************************/
153BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
154{
155    if (stack_config_get_interface()->get_pts_conn_updates_disabled())
156        return false;
157
158    tL2C_LCB            *p_lcb;
159
160    /* See if we have a link control block for the remote device */
161    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
162
163    if (!p_lcb)
164    {
165        L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
166            (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
167            (rem_bda[4]<<8)+rem_bda[5]);
168        return (FALSE);
169    }
170
171    L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
172        (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
173        (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);
174
175    if (p_lcb->transport != BT_TRANSPORT_LE)
176    {
177        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
178                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
179                              (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
180        return (FALSE);
181    }
182
183    if (enable)
184        p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
185    else
186        p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
187
188    l2cble_start_conn_update(p_lcb);
189
190    return (TRUE);
191}
192
193
194/*******************************************************************************
195**
196** Function         L2CA_GetBleConnRole
197**
198** Description      This function returns the connection role.
199**
200** Returns          link role.
201**
202*******************************************************************************/
203UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
204{
205    UINT8       role = HCI_ROLE_UNKNOWN;
206
207    tL2C_LCB *p_lcb;
208
209    if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL)
210        role = p_lcb->link_role;
211
212    return role;
213}
214/*******************************************************************************
215**
216** Function         L2CA_GetDisconnectReason
217**
218** Description      This function returns the disconnect reason code.
219**
220** Returns          disconnect reason
221**
222*******************************************************************************/
223UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
224{
225    tL2C_LCB            *p_lcb;
226    UINT16              reason = 0;
227
228    if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL)
229        reason = p_lcb->disc_reason;
230
231    L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ",reason);
232
233    return reason;
234}
235
236void l2cble_use_preferred_conn_params(BD_ADDR bda) {
237    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
238    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
239
240    /* If there are any preferred connection parameters, set them now */
241    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
242         (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
243         (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
244         (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
245         (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
246         (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
247         (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
248         ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
249          p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
250          (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
251          (p_lcb->latency > p_dev_rec->conn_params.slave_latency) ||
252          (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout)))
253    {
254        L2CAP_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__,
255                            p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
256                            p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
257
258        p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
259        p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
260        p_lcb->timeout      = p_dev_rec->conn_params.supervision_tout;
261        p_lcb->latency      = p_dev_rec->conn_params.slave_latency;
262
263        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
264                                           p_dev_rec->conn_params.min_conn_int,
265                                           p_dev_rec->conn_params.max_conn_int,
266                                           p_dev_rec->conn_params.slave_latency,
267                                           p_dev_rec->conn_params.supervision_tout,
268                                           0, 0);
269    }
270}
271
272/*******************************************************************************
273**
274** Function l2cble_notify_le_connection
275**
276** Description This function notifiy the l2cap connection to the app layer
277**
278** Returns none
279**
280*******************************************************************************/
281void l2cble_notify_le_connection (BD_ADDR bda)
282{
283    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
284    tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
285    tL2C_CCB *p_ccb;
286
287    if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED)
288    {
289        /* update link status */
290        btm_establish_continue(p_acl);
291        /* update l2cap link status and send callback */
292        p_lcb->link_state = LST_CONNECTED;
293        l2cu_process_fixed_chnl_resp (p_lcb);
294    }
295
296    if (p_lcb != NULL) {
297        /* For all channels, send the event through their FSMs */
298        for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
299        {
300            if (p_ccb->chnl_state == CST_CLOSED)
301                l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
302        }
303    }
304
305    l2cble_use_preferred_conn_params(bda);
306}
307
308/*******************************************************************************
309**
310** Function         l2cble_scanner_conn_comp
311**
312** Description      This function is called when an HCI Connection Complete
313**                  event is received while we are a scanner (so we are master).
314**
315** Returns          void
316**
317*******************************************************************************/
318void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
319                               UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
320{
321    tL2C_LCB            *p_lcb;
322    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
323
324    L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
325                        handle,  type, conn_interval, conn_latency, conn_timeout);
326
327    l2cb.is_ble_connecting = FALSE;
328
329    /* See if we have a link control block for the remote device */
330    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
331
332    /* If we don't have one, create one. this is auto connection complete. */
333    if (!p_lcb)
334    {
335        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
336        if (!p_lcb)
337        {
338            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
339            L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
340            return;
341        }
342        else
343        {
344            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
345            {
346                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
347                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
348                return ;
349            }
350        }
351    }
352    else if (p_lcb->link_state != LST_CONNECTING)
353    {
354        L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
355        return;
356    }
357    alarm_cancel(p_lcb->l2c_lcb_timer);
358
359    /* Save the handle */
360    p_lcb->handle = handle;
361
362    /* Connected OK. Change state to connected, we were scanning so we are master */
363    p_lcb->link_role  = HCI_ROLE_MASTER;
364    p_lcb->transport  = BT_TRANSPORT_LE;
365
366    /* update link parameter, set slave link as non-spec default upon link up */
367    p_lcb->min_interval =  p_lcb->max_interval = conn_interval;
368    p_lcb->timeout      =  conn_timeout;
369    p_lcb->latency      =  conn_latency;
370    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
371
372    /* Tell BTM Acl management about the link */
373    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
374
375    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
376
377    btm_ble_set_conn_st(BLE_CONN_IDLE);
378
379#if BLE_PRIVACY_SPT == TRUE
380    btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
381#endif
382}
383
384
385/*******************************************************************************
386**
387** Function         l2cble_advertiser_conn_comp
388**
389** Description      This function is called when an HCI Connection Complete
390**                  event is received while we are an advertiser (so we are slave).
391**
392** Returns          void
393**
394*******************************************************************************/
395void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
396                                  UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
397{
398    tL2C_LCB            *p_lcb;
399    tBTM_SEC_DEV_REC    *p_dev_rec;
400    UNUSED(type);
401    UNUSED(conn_interval);
402    UNUSED(conn_latency);
403    UNUSED(conn_timeout);
404
405    /* See if we have a link control block for the remote device */
406    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
407
408    /* If we don't have one, create one and accept the connection. */
409    if (!p_lcb)
410    {
411        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
412        if (!p_lcb)
413        {
414            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
415            L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
416            return;
417        }
418        else
419        {
420            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
421            {
422                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
423                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
424                return ;
425            }
426        }
427    }
428
429    /* Save the handle */
430    p_lcb->handle = handle;
431
432    /* Connected OK. Change state to connected, we were advertising, so we are slave */
433    p_lcb->link_role  = HCI_ROLE_SLAVE;
434    p_lcb->transport  = BT_TRANSPORT_LE;
435
436    /* update link parameter, set slave link as non-spec default upon link up */
437    p_lcb->min_interval = p_lcb->max_interval = conn_interval;
438    p_lcb->timeout      =  conn_timeout;
439    p_lcb->latency      =  conn_latency;
440    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
441
442    /* Tell BTM Acl management about the link */
443    p_dev_rec = btm_find_or_alloc_dev (bda);
444
445    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
446
447#if BLE_PRIVACY_SPT == TRUE
448    btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
449#endif
450
451    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
452
453    if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array))
454    {
455        p_lcb->link_state = LST_CONNECTED;
456        l2cu_process_fixed_chnl_resp (p_lcb);
457    }
458
459    /* when adv and initiating are both active, cancel the direct connection */
460    if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0)
461    {
462        L2CA_CancelBleConnectReq(bda);
463    }
464}
465
466/*******************************************************************************
467**
468** Function         l2cble_conn_comp
469**
470** Description      This function is called when an HCI Connection Complete
471**                  event is received.
472**
473** Returns          void
474**
475*******************************************************************************/
476void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
477                      UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
478{
479    btm_ble_update_link_topology_mask(role, TRUE);
480
481    if (role == HCI_ROLE_MASTER)
482    {
483        l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
484    }
485    else
486    {
487        l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
488    }
489}
490
491/*******************************************************************************
492**
493**  Function        l2cble_start_conn_update
494**
495**  Description     start BLE connection parameter update process based on status
496**
497**  Parameters:     lcb : l2cap link control block
498**
499**  Return value:   none
500**
501*******************************************************************************/
502static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
503{
504    UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
505    tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
506
507    // TODO(armansito): The return value of this call wasn't being used but the
508    // logic of this function might be depending on its side effects. We should
509    // verify if this call is needed at all and remove it otherwise.
510    btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
511
512    if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
513
514    if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
515    {
516        /* application requests to disable parameters update.
517           If parameters are already updated, lets set them
518           up to what has been requested during connection establishement */
519        if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
520            /* current connection interval is greater than default min */
521            p_lcb->min_interval > BTM_BLE_CONN_INT_MIN)
522        {
523            /* use 7.5 ms as fast connection parameter, 0 slave latency */
524            min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
525            slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
526            supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
527
528            /* if both side 4.1, or we are master device, send HCI command */
529            if (p_lcb->link_role == HCI_ROLE_MASTER
530#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
531                || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
532                    HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
533#endif
534                 )
535            {
536                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
537                                                  slave_latency, supervision_tout, 0, 0);
538                p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
539            }
540            else
541            {
542                l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
543            }
544            p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
545            p_lcb->conn_update_mask |=  L2C_BLE_NEW_CONN_PARAM;
546         }
547    }
548    else
549    {
550        /* application allows to do update, if we were delaying one do it now */
551        if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM)
552        {
553             /* if both side 4.1, or we are master device, send HCI command */
554            if (p_lcb->link_role == HCI_ROLE_MASTER
555#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
556                || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
557                    HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
558#endif
559                 )
560            {
561                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
562                    p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
563                p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
564            }
565            else
566            {
567                l2cu_send_peer_ble_par_req (p_lcb, p_lcb->min_interval, p_lcb->max_interval,
568                                            p_lcb->latency, p_lcb->timeout);
569            }
570            p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
571            p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
572        }
573    }
574}
575
576/*******************************************************************************
577**
578** Function         l2cble_process_conn_update_evt
579**
580** Description      This function enables the connection update request from remote
581**                  after a successful connection update response is received.
582**
583** Returns          void
584**
585*******************************************************************************/
586void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status,
587                  UINT16 interval, UINT16 latency, UINT16 timeout)
588{
589    L2CAP_TRACE_DEBUG("%s", __func__);
590
591    /* See if we have a link control block for the remote device */
592    tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
593    if (!p_lcb)
594    {
595        L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle);
596        return;
597    }
598
599    p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
600
601    if (status != HCI_SUCCESS)
602    {
603        L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status);
604    }
605
606    l2cble_start_conn_update(p_lcb);
607
608    L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, p_lcb->conn_update_mask);
609}
610
611/*******************************************************************************
612**
613** Function         l2cble_process_sig_cmd
614**
615** Description      This function is called when a signalling packet is received
616**                  on the BLE signalling CID
617**
618** Returns          void
619**
620*******************************************************************************/
621void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
622{
623    UINT8           *p_pkt_end;
624    UINT8           cmd_code, id;
625    UINT16          cmd_len;
626    UINT16          min_interval, max_interval, latency, timeout;
627    tL2C_CONN_INFO  con_info;
628    UINT16          lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0;
629    tL2C_CCB        *p_ccb = NULL, *temp_p_ccb = NULL;
630    tL2C_RCB        *p_rcb;
631    UINT16          credit;
632    p_pkt_end = p + pkt_len;
633
634    STREAM_TO_UINT8  (cmd_code, p);
635    STREAM_TO_UINT8  (id, p);
636    STREAM_TO_UINT16 (cmd_len, p);
637
638    /* Check command length does not exceed packet length */
639    if ((p + cmd_len) > p_pkt_end)
640    {
641        L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d  cmd_len: %d  code: %d", pkt_len, cmd_len, cmd_code);
642        return;
643    }
644
645    switch (cmd_code)
646    {
647        case L2CAP_CMD_REJECT:
648            p += 2;
649            break;
650
651        case L2CAP_CMD_ECHO_REQ:
652        case L2CAP_CMD_ECHO_RSP:
653        case L2CAP_CMD_INFO_RSP:
654        case L2CAP_CMD_INFO_REQ:
655            l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
656            break;
657
658        case L2CAP_CMD_BLE_UPDATE_REQ:
659            STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
660            STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
661            STREAM_TO_UINT16 (latency, p);  /* 0x0000 - 0x03E8 */
662            STREAM_TO_UINT16 (timeout, p);  /* 0x000A - 0x0C80 */
663            /* If we are a master, the slave wants to update the parameters */
664            if (p_lcb->link_role == HCI_ROLE_MASTER)
665            {
666                if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
667                    min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
668
669                if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
670                    max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
671                    latency  > BTM_BLE_CONN_LATENCY_MAX ||
672                    /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
673                    timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
674                    max_interval < min_interval)
675                {
676                    l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
677                }
678                else
679                {
680
681                    l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
682
683                     p_lcb->min_interval = min_interval;
684                     p_lcb->max_interval = max_interval;
685                     p_lcb->latency = latency;
686                     p_lcb->timeout = timeout;
687                     p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
688
689                     l2cble_start_conn_update(p_lcb);
690                }
691            }
692            else
693                l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
694            break;
695
696        case L2CAP_CMD_BLE_UPDATE_RSP:
697            p += 2;
698            break;
699
700        case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ:
701            STREAM_TO_UINT16 (con_info.psm, p);
702            STREAM_TO_UINT16 (rcid, p);
703            STREAM_TO_UINT16 (mtu, p);
704            STREAM_TO_UINT16 (mps, p);
705            STREAM_TO_UINT16 (initial_credit, p);
706
707            L2CAP_TRACE_DEBUG ("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ with "
708                    "mtu = %d, "
709                    "mps = %d, "
710                    "initial credit = %d", mtu, mps, initial_credit);
711
712            if ((p_rcb = l2cu_find_ble_rcb_by_psm (con_info.psm)) == NULL)
713            {
714                L2CAP_TRACE_WARNING ("L2CAP - rcvd conn req for unknown PSM: 0x%04x", con_info.psm);
715                l2cu_reject_ble_connection (p_lcb, id, L2CAP_LE_NO_PSM);
716                break;
717            }
718            else
719            {
720                if (!p_rcb->api.pL2CA_ConnectInd_Cb)
721                {
722                    L2CAP_TRACE_WARNING ("L2CAP - rcvd conn req for outgoing-only connection PSM: %d", con_info.psm);
723                    l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_PSM);
724                    break;
725                }
726            }
727
728            /* Allocate a ccb for this.*/
729            if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
730            {
731                L2CAP_TRACE_ERROR ("L2CAP - unable to allocate CCB");
732                l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_RESOURCES);
733                break;
734            }
735
736            /* validate the parameters */
737            if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS || mps > L2CAP_LE_MAX_MPS)
738            {
739                L2CAP_TRACE_ERROR ("L2CAP don't like the params");
740                l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_RESOURCES);
741                break;
742            }
743
744            p_ccb->remote_id = id;
745            p_ccb->p_rcb = p_rcb;
746            p_ccb->remote_cid = rcid;
747
748            p_ccb->peer_conn_cfg.mtu = mtu;
749            p_ccb->peer_conn_cfg.mps = mps;
750            p_ccb->peer_conn_cfg.credits = initial_credit;
751
752            p_ccb->tx_mps = mps;
753            p_ccb->ble_sdu = NULL;
754            p_ccb->ble_sdu_length = 0;
755            p_ccb->is_first_seg = TRUE;
756            p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
757
758            l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
759            break;
760
761        case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES:
762            L2CAP_TRACE_DEBUG ("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES");
763            /* For all channels, see whose identifier matches this id */
764            for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb; temp_p_ccb = temp_p_ccb->p_next_ccb)
765            {
766                if (temp_p_ccb->local_id == id)
767                {
768                    p_ccb = temp_p_ccb;
769                    break;
770                }
771            }
772            if (p_ccb)
773            {
774                L2CAP_TRACE_DEBUG ("I remember the connection req");
775                STREAM_TO_UINT16 (p_ccb->remote_cid, p);
776                STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.mtu, p);
777                STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.mps, p);
778                STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.credits, p);
779                STREAM_TO_UINT16 (con_info.l2cap_result, p);
780                con_info.remote_cid = p_ccb->remote_cid;
781
782                L2CAP_TRACE_DEBUG ("remote_cid = %d, "
783                        "mtu = %d, "
784                        "mps = %d, "
785                        "initial_credit = %d, "
786                        "con_info.l2cap_result = %d",
787                        p_ccb->remote_cid, p_ccb->peer_conn_cfg.mtu, p_ccb->peer_conn_cfg.mps,
788                        p_ccb->peer_conn_cfg.credits, con_info.l2cap_result);
789
790                /* validate the parameters */
791                if (p_ccb->peer_conn_cfg.mtu < L2CAP_LE_MIN_MTU ||
792                        p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
793                        p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS)
794                {
795                    L2CAP_TRACE_ERROR ("L2CAP don't like the params");
796                    con_info.l2cap_result = L2CAP_LE_NO_RESOURCES;
797                    l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
798                    break;
799                }
800
801                p_ccb->tx_mps = p_ccb->peer_conn_cfg.mps;
802                p_ccb->ble_sdu = NULL;
803                p_ccb->ble_sdu_length = 0;
804                p_ccb->is_first_seg = TRUE;
805                p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
806
807                if (con_info.l2cap_result == L2CAP_LE_CONN_OK)
808                    l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
809                else
810                    l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
811            }
812            else
813            {
814                L2CAP_TRACE_DEBUG ("I DO NOT remember the connection req");
815                con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID;
816                l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
817            }
818            break;
819
820        case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT:
821            STREAM_TO_UINT16(lcid, p);
822            if((p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, lcid)) == NULL)
823            {
824                L2CAP_TRACE_DEBUG ("%s Credit received for unknown channel id %d", __func__, lcid);
825                break;
826            }
827
828            STREAM_TO_UINT16(credit ,p);
829            l2c_csm_execute(p_ccb, L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT, &credit);
830            L2CAP_TRACE_DEBUG ("%s Credit received", __func__);
831            break;
832
833        case L2CAP_CMD_DISC_REQ:
834            STREAM_TO_UINT16 (lcid, p);
835            STREAM_TO_UINT16 (rcid, p);
836
837            if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL)
838            {
839                if (p_ccb->remote_cid == rcid)
840                {
841                    p_ccb->remote_id = id;
842                    l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL);
843                }
844            }
845            else
846                l2cu_send_peer_disc_rsp (p_lcb, id, lcid, rcid);
847
848            break;
849
850         case L2CAP_CMD_DISC_RSP:
851            STREAM_TO_UINT16 (rcid, p);
852            STREAM_TO_UINT16 (lcid, p);
853
854            if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL)
855            {
856                if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id))
857                    l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, NULL);
858            }
859            break;
860
861        default:
862            L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
863            l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
864            break;
865    }
866}
867
868/*******************************************************************************
869**
870** Function         l2cble_init_direct_conn
871**
872** Description      This function is to initate a direct connection
873**
874** Returns          TRUE connection initiated, FALSE otherwise.
875**
876*******************************************************************************/
877BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
878{
879    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
880    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
881    UINT16 scan_int;
882    UINT16 scan_win;
883    BD_ADDR peer_addr;
884    UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
885    UINT8 own_addr_type = BLE_ADDR_PUBLIC;
886
887    /* There can be only one BLE connection request outstanding at a time */
888    if (p_dev_rec == NULL)
889    {
890        L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
891        return(FALSE);
892    }
893
894    scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
895    scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
896
897    peer_addr_type = p_lcb->ble_addr_type;
898    memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
899
900#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
901    own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
902    if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
903    {
904        if (btm_cb.ble_ctr_cb.privacy_mode >=  BTM_PRIVACY_1_2)
905            own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
906
907        btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
908        btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
909    } else {
910        btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
911
912        // If we have a current RPA, use that instead.
913        if (!bdaddr_is_empty((const bt_bdaddr_t *)p_dev_rec->ble.cur_rand_addr)) {
914            memcpy(peer_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
915        }
916    }
917#endif
918
919    if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
920    {
921        l2cu_release_lcb (p_lcb);
922        L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
923        return FALSE;
924    }
925
926    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
927                                        scan_win, /* UINT16 scan_win      */
928                                        FALSE,                   /* UINT8 white_list     */
929                                        peer_addr_type,          /* UINT8 addr_type_peer */
930                                        peer_addr,               /* BD_ADDR bda_peer     */
931                                        own_addr_type,         /* UINT8 addr_type_own  */
932        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
933        p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
934        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
935        p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
936        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
937        p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
938        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
939        p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
940                                        0,                       /* UINT16 min_len       */
941                                        0))                      /* UINT16 max_len       */
942    {
943        l2cu_release_lcb (p_lcb);
944        L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
945        return (FALSE);
946    }
947    else
948    {
949        p_lcb->link_state = LST_CONNECTING;
950        l2cb.is_ble_connecting = TRUE;
951        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
952        alarm_set_on_queue(p_lcb->l2c_lcb_timer,
953                           L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
954                           l2c_lcb_timer_timeout, p_lcb,
955                           btu_general_alarm_queue);
956        btm_ble_set_conn_st (BLE_DIR_CONN);
957
958        return (TRUE);
959    }
960}
961
962/*******************************************************************************
963**
964** Function         l2cble_create_conn
965**
966** Description      This function initiates an acl connection via HCI
967**
968** Returns          TRUE if successful, FALSE if connection not started.
969**
970*******************************************************************************/
971BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
972{
973    tBTM_BLE_CONN_ST     conn_st = btm_ble_get_conn_st();
974    BOOLEAN         rt = FALSE;
975
976    /* There can be only one BLE connection request outstanding at a time */
977    if (conn_st == BLE_CONN_IDLE)
978    {
979        rt = l2cble_init_direct_conn(p_lcb);
980    }
981    else
982    {
983        L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
984
985        btm_ble_enqueue_direct_conn_req(p_lcb);
986
987        if (conn_st == BLE_BG_CONN)
988            btm_ble_suspend_bg_conn();
989
990        rt = TRUE;
991    }
992    return rt;
993}
994
995/*******************************************************************************
996**
997** Function         l2c_link_processs_ble_num_bufs
998**
999** Description      This function is called when a "controller buffer size"
1000**                  event is first received from the controller. It updates
1001**                  the L2CAP values.
1002**
1003** Returns          void
1004**
1005*******************************************************************************/
1006void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
1007{
1008    if (num_lm_ble_bufs == 0)
1009    {
1010        num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
1011        l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
1012    }
1013
1014    l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
1015}
1016
1017/*******************************************************************************
1018**
1019** Function         l2c_ble_link_adjust_allocation
1020**
1021** Description      This function is called when a link is created or removed
1022**                  to calculate the amount of packets each link may send to
1023**                  the HCI without an ack coming back.
1024**
1025**                  Currently, this is a simple allocation, dividing the
1026**                  number of Controller Packets by the number of links. In
1027**                  the future, QOS configuration should be examined.
1028**
1029** Returns          void
1030**
1031*******************************************************************************/
1032void l2c_ble_link_adjust_allocation (void)
1033{
1034    UINT16      qq, yy, qq_remainder;
1035    tL2C_LCB    *p_lcb;
1036    UINT16      hi_quota, low_quota;
1037    UINT16      num_lowpri_links = 0;
1038    UINT16      num_hipri_links  = 0;
1039    UINT16      controller_xmit_quota = l2cb.num_lm_ble_bufs;
1040    UINT16      high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
1041
1042    /* If no links active, reset buffer quotas and controller buffers */
1043    if (l2cb.num_ble_links_active == 0)
1044    {
1045        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
1046        l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
1047        return;
1048    }
1049
1050    /* First, count the links */
1051    for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
1052    {
1053        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
1054        {
1055            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1056                num_hipri_links++;
1057            else
1058                num_lowpri_links++;
1059        }
1060    }
1061
1062    /* now adjust high priority link quota */
1063    low_quota = num_lowpri_links ? 1 : 0;
1064    while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota )
1065        high_pri_link_quota--;
1066
1067
1068    /* Work out the xmit quota and buffer quota high and low priorities */
1069    hi_quota  = num_hipri_links * high_pri_link_quota;
1070    low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
1071
1072    /* Work out and save the HCI xmit quota for each low priority link */
1073
1074    /* If each low priority link cannot have at least one buffer */
1075    if (num_lowpri_links > low_quota)
1076    {
1077        l2cb.ble_round_robin_quota = low_quota;
1078        qq = qq_remainder = 0;
1079    }
1080    /* If each low priority link can have at least one buffer */
1081    else if (num_lowpri_links > 0)
1082    {
1083        l2cb.ble_round_robin_quota = 0;
1084        l2cb.ble_round_robin_unacked = 0;
1085        qq = low_quota / num_lowpri_links;
1086        qq_remainder = low_quota % num_lowpri_links;
1087    }
1088    /* If no low priority link */
1089    else
1090    {
1091        l2cb.ble_round_robin_quota = 0;
1092        l2cb.ble_round_robin_unacked = 0;
1093        qq = qq_remainder = 0;
1094    }
1095    L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
1096                        num_hipri_links, num_lowpri_links, low_quota,
1097                        l2cb.ble_round_robin_quota, qq);
1098
1099    /* Now, assign the quotas to each link */
1100    for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
1101    {
1102        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
1103        {
1104            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1105            {
1106                p_lcb->link_xmit_quota   = high_pri_link_quota;
1107            }
1108            else
1109            {
1110                /* Safety check in case we switched to round-robin with something outstanding */
1111                /* if sent_not_acked is added into round_robin_unacked then don't add it again */
1112                /* l2cap keeps updating sent_not_acked for exiting from round robin */
1113                if (( p_lcb->link_xmit_quota > 0 )&&( qq == 0 ))
1114                    l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
1115
1116                p_lcb->link_xmit_quota   = qq;
1117                if (qq_remainder > 0)
1118                {
1119                    p_lcb->link_xmit_quota++;
1120                    qq_remainder--;
1121                }
1122            }
1123
1124            L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation LCB %d   Priority: %d  XmitQuota: %d",
1125                                yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);
1126
1127            L2CAP_TRACE_EVENT("        SentNotAcked: %d  RRUnacked: %d",
1128                                p_lcb->sent_not_acked, l2cb.round_robin_unacked);
1129
1130            /* There is a special case where we have readjusted the link quotas and  */
1131            /* this link may have sent anything but some other link sent packets so  */
1132            /* so we may need a timer to kick off this link's transmissions.         */
1133            if ( (p_lcb->link_state == LST_CONNECTED)
1134              && (!list_is_empty(p_lcb->link_xmit_data_q))
1135                 && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) ) {
1136                alarm_set_on_queue(p_lcb->l2c_lcb_timer,
1137                                   L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS,
1138                                   l2c_lcb_timer_timeout, p_lcb,
1139                                   btu_general_alarm_queue);
1140            }
1141        }
1142    }
1143}
1144
1145#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
1146/*******************************************************************************
1147**
1148** Function         l2cble_process_rc_param_request_evt
1149**
1150** Description      process LE Remote Connection Parameter Request Event.
1151**
1152** Returns          void
1153**
1154*******************************************************************************/
1155void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
1156                                     UINT16 latency, UINT16 timeout)
1157{
1158    tL2C_LCB    *p_lcb = l2cu_find_lcb_by_handle (handle);
1159
1160    if (p_lcb != NULL)
1161    {
1162        p_lcb->min_interval = int_min;
1163        p_lcb->max_interval = int_max;
1164        p_lcb->latency = latency;
1165        p_lcb->timeout = timeout;
1166
1167        /* if update is enabled, always accept connection parameter update */
1168        if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0)
1169        {
1170            btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
1171        }
1172        else
1173        {
1174            L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
1175            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
1176            btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
1177        }
1178
1179    }
1180    else
1181    {
1182        L2CAP_TRACE_WARNING("No link to update connection parameter")
1183    }
1184}
1185#endif
1186
1187/*******************************************************************************
1188**
1189** Function         l2cble_update_data_length
1190**
1191** Description      This function update link tx data length if applicable
1192**
1193** Returns          void
1194**
1195*******************************************************************************/
1196void l2cble_update_data_length(tL2C_LCB *p_lcb)
1197{
1198    UINT16 tx_mtu = 0;
1199    UINT16 i = 0;
1200
1201    L2CAP_TRACE_DEBUG("%s", __FUNCTION__);
1202
1203    /* See if we have a link control block for the connection */
1204    if (p_lcb == NULL)
1205        return;
1206
1207    for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++)
1208    {
1209        if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID)
1210        {
1211            if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1212                    (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
1213                tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1214        }
1215    }
1216
1217    if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1218        tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1219
1220    /* update TX data length if changed */
1221    if (p_lcb->tx_data_len != tx_mtu)
1222        BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1223
1224}
1225
1226/*******************************************************************************
1227**
1228** Function         l2cble_process_data_length_change_evt
1229**
1230** Description      This function process the data length change event
1231**
1232** Returns          void
1233**
1234*******************************************************************************/
1235void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
1236{
1237    tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1238
1239    L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
1240    if (p_lcb == NULL)
1241        return;
1242
1243    if (tx_data_len > 0)
1244        p_lcb->tx_data_len = tx_data_len;
1245
1246    /* ignore rx_data len for now */
1247}
1248
1249/*******************************************************************************
1250**
1251** Function         l2cble_set_fixed_channel_tx_data_length
1252**
1253** Description      This function update max fixed channel tx data length if applicable
1254**
1255** Returns          void
1256**
1257*******************************************************************************/
1258void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
1259{
1260    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
1261    UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
1262
1263    L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);
1264
1265    if (!controller_get_interface()->supports_ble_packet_extension())
1266    {
1267        L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
1268        return;
1269    }
1270
1271    /* See if we have a link control block for the connection */
1272    if (p_lcb == NULL)
1273        return;
1274
1275    if (p_lcb->p_fixed_ccbs[cid] != NULL)
1276    {
1277        if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1278            tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1279
1280        p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
1281    }
1282
1283    l2cble_update_data_length(p_lcb);
1284}
1285
1286/*******************************************************************************
1287**
1288** Function         l2cble_credit_based_conn_req
1289**
1290** Description      This function sends LE Credit Based Connection Request for
1291**                  LE connection oriented channels.
1292**
1293** Returns          void
1294**
1295*******************************************************************************/
1296void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb)
1297{
1298    if (!p_ccb)
1299        return;
1300
1301    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1302    {
1303        L2CAP_TRACE_WARNING ("LE link doesn't exist");
1304        return;
1305    }
1306
1307    l2cu_send_peer_ble_credit_based_conn_req (p_ccb);
1308    return;
1309}
1310
1311/*******************************************************************************
1312**
1313** Function         l2cble_credit_based_conn_res
1314**
1315** Description      This function sends LE Credit Based Connection Response for
1316**                  LE connection oriented channels.
1317**
1318** Returns          void
1319**
1320*******************************************************************************/
1321void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
1322{
1323    if (!p_ccb)
1324        return;
1325
1326    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1327    {
1328        L2CAP_TRACE_WARNING ("LE link doesn't exist");
1329        return;
1330    }
1331
1332    l2cu_send_peer_ble_credit_based_conn_res (p_ccb, result);
1333    return;
1334}
1335
1336/*******************************************************************************
1337**
1338** Function         l2cble_send_flow_control_credit
1339**
1340** Description      This function sends flow control credits for
1341**                  LE connection oriented channels.
1342**
1343** Returns          void
1344**
1345*******************************************************************************/
1346void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
1347{
1348    if (!p_ccb)
1349        return;
1350
1351    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1352    {
1353        L2CAP_TRACE_WARNING ("LE link doesn't exist");
1354        return;
1355    }
1356
1357    l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
1358    return;
1359
1360}
1361
1362/*******************************************************************************
1363**
1364** Function         l2cble_send_peer_disc_req
1365**
1366** Description      This function sends disconnect request
1367**                  to the peer LE device
1368**
1369** Returns          void
1370**
1371*******************************************************************************/
1372void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb)
1373{
1374    L2CAP_TRACE_DEBUG ("%s",__func__);
1375    if (!p_ccb)
1376        return;
1377
1378    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1379    {
1380        L2CAP_TRACE_WARNING ("LE link doesn't exist");
1381        return;
1382    }
1383
1384    l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
1385    return;
1386}
1387
1388/*******************************************************************************
1389**
1390** Function         l2cble_sec_comp
1391**
1392** Description      This function is called when security procedure for an LE COC
1393**                  link is done
1394**
1395** Returns          void
1396**
1397*******************************************************************************/
1398void  l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
1399{
1400    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
1401    tL2CAP_SEC_DATA *p_buf = NULL;
1402    UINT8 sec_flag;
1403    UINT8 sec_act;
1404
1405    if (!p_lcb)
1406    {
1407        L2CAP_TRACE_WARNING ("%s security complete for unknown device", __func__);
1408        return;
1409    }
1410
1411    sec_act = p_lcb->sec_act;
1412    p_lcb->sec_act = 0;
1413
1414    if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1415    {
1416        p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1417        if (!p_buf)
1418        {
1419            L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP",
1420                    __func__);
1421            return;
1422        }
1423
1424        if (status != BTM_SUCCESS)
1425        {
1426            (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1427        }
1428        else
1429        {
1430            if (sec_act == BTM_SEC_ENCRYPT_MITM)
1431            {
1432                BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
1433                if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
1434                    (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1435                else
1436                {
1437                    L2CAP_TRACE_DEBUG ("%s MITM Protection Not present", __func__);
1438                    (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1439                            BTM_FAILED_ON_SECURITY);
1440                }
1441            }
1442            else
1443            {
1444                L2CAP_TRACE_DEBUG ("%s MITM Protection not required sec_act = %d",
1445                        __func__, p_lcb->sec_act);
1446
1447                (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1448            }
1449        }
1450    }
1451    else
1452    {
1453        L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP", __func__);
1454        return;
1455    }
1456    osi_free(p_buf);
1457
1458    while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1459    {
1460        p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1461
1462        if (status != BTM_SUCCESS)
1463            (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1464        else
1465            l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
1466                    p_buf->p_callback, p_buf->p_ref_data);
1467
1468       osi_free(p_buf);
1469    }
1470}
1471
1472/*******************************************************************************
1473**
1474** Function         l2ble_sec_access_req
1475**
1476** Description      This function is called by LE COC link to meet the
1477**                  security requirement for the link
1478**
1479** Returns          TRUE - security procedures are started
1480**                  FALSE - failure
1481**
1482*******************************************************************************/
1483BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data)
1484{
1485    L2CAP_TRACE_DEBUG ("%s", __func__);
1486    BOOLEAN status;
1487    tL2C_LCB *p_lcb = NULL;
1488
1489    if (!p_callback)
1490    {
1491        L2CAP_TRACE_ERROR("%s No callback function", __func__);
1492        return FALSE;
1493    }
1494
1495    p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
1496
1497    if (!p_lcb)
1498    {
1499        L2CAP_TRACE_ERROR ("%s Security check for unknown device", __func__);
1500        p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
1501        return FALSE;
1502    }
1503
1504    tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) osi_malloc((UINT16)sizeof(tL2CAP_SEC_DATA));
1505    if (!p_buf)
1506    {
1507        p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
1508        return FALSE;
1509    }
1510
1511    p_buf->psm = psm;
1512    p_buf->is_originator = is_originator;
1513    p_buf->p_callback = p_callback;
1514    p_buf->p_ref_data = p_ref_data;
1515    fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
1516    status = btm_ble_start_sec_check(bd_addr, psm, is_originator, &l2cble_sec_comp, p_ref_data);
1517
1518    return status;
1519}
1520#endif /* (BLE_INCLUDED == TRUE) */
1521