text:
/******************************************************************************
 *
 *  this file contains functions relating to BLE management.
 *
 ******************************************************************************/

#include <string.h>
#include "common/bt_target.h"
//#include "bt_utils.h"
#include "stack/l2cdefs.h"
#include "l2c_int.h"
#include "stack/btu.h"
#include "btm_int.h"
#include "stack/hcimsgs.h"
#include "device/controller.h"

#if (BLE_INCLUDED == TRUE)

#if (BLE_50_FEATURE_SUPPORT == TRUE)
const tHCI_ExtConnParams ext_conn_params = {
    .scan_interval = 0x40,
    .scan_window = 0x40,
    .conn_interval_min = 320, // 306-> 362Kbps
    .conn_interval_max = 320,
    .conn_latency = 0,
    .sup_timeout = 600,
    .min_ce_len  = 0,
    .max_ce_len = 0,
};
#define BLE_PHY_NO_PREF                  0
#define BLE_PHY_PREF_MASK                ((1 << 2) | (1 << 1) | (1 << 0))

#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)

static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb);
extern int64_t esp_system_get_time(void);

/*******************************************************************************
**
**  Function        L2CA_CancelBleConnectReq
**
**  Description     Cancel a pending connection attempt to a BLE device.
**
**  Parameters:     BD Address of remote
**
**  Return value:   TRUE if connection was cancelled
**
*******************************************************************************/
BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
{
    tL2C_LCB *p_lcb;

    /* There can be only one BLE connection request outstanding at a time */
    if (btm_ble_get_conn_st() == BLE_CONN_IDLE) {
        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
        return (FALSE);
    }

    if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN)) {
        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different  BDA Connecting: %08x%04x  Cancel: %08x%04x",
                             (l2cb.ble_connecting_bda[0] << 24) + (l2cb.ble_connecting_bda[1] << 16) + (l2cb.ble_connecting_bda[2] << 8) + l2cb.ble_connecting_bda[3],
                             (l2cb.ble_connecting_bda[4] << 8) + l2cb.ble_connecting_bda[5],
                             (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3], (rem_bda[4] << 8) + rem_bda[5]);

        return (FALSE);
    }

    if (btsnd_hcic_ble_create_conn_cancel()) {
        p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
        /* Do not remove lcb if an LE link is already up as a peripheral */
        if (p_lcb != NULL &&
                !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda))) {
            p_lcb->disc_reason = L2CAP_CONN_CANCEL;
            l2cu_release_lcb (p_lcb);
        }
        /* update state to be cancel, wait for connection cancel complete */
        btm_ble_set_conn_st (BLE_CONN_CANCEL);

        return (TRUE);
    } else {
        return (FALSE);
    }
}

/*******************************************************************************
**
**  Function        L2CA_UpdateBleConnParams
**
**  Description     Update BLE connection parameters.
**
**  Parameters:     BD Address of remote
**
**  Return value:   TRUE if update started
**
*******************************************************************************/
BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
                                  UINT16 latency, UINT16 timeout)
{
    tL2C_LCB            *p_lcb;
    tACL_CONN           *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);

    /* If we don't have one, create one and accept the connection. */
    if (!p_lcb || !p_acl_cb) {
        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
                             (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                             (rem_bda[4] << 8) + rem_bda[5]);
        return (FALSE);
    }

    if (p_lcb->transport != BT_TRANSPORT_LE) {
        L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
                             (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                             (rem_bda[4] << 8) + rem_bda[5]);
        return (FALSE);
    }

    if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL){
        UINT8 status = HCI_ERR_ILLEGAL_COMMAND;
        L2CAP_TRACE_ERROR("There are two connection parameter requests that are being updated, please try later ");
        if (conn_param_update_cb.update_conn_param_cb != NULL) {
            tBTM_LE_UPDATE_CONN_PRAMS update_param;
            update_param.max_conn_int = max_int;
            update_param.min_conn_int = min_int;
            update_param.conn_int = p_lcb->current_used_conn_interval;
            update_param.slave_latency = p_lcb->current_used_conn_latency;
            update_param.supervision_tout = p_lcb->current_used_conn_timeout;
            (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param);
        }
        return (FALSE);
    }

    p_lcb->waiting_update_conn_min_interval = min_int;
    p_lcb->waiting_update_conn_max_interval = max_int;
    p_lcb->waiting_update_conn_latency = latency;
    p_lcb->waiting_update_conn_timeout = timeout;

    p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;

    if(l2cble_start_conn_update(p_lcb) == TRUE) {
        UINT32 time = CalConnectParamTimeout(p_lcb);
        btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
    }

    return (TRUE);
}

/*******************************************************************************
**
**  Function        L2CA_EnableUpdateBleConnParams
**
**  Description     Enable or disable update based on the request from the peer
**
**  Parameters:     BD Address of remote
**
**  Return value:   TRUE if update started
**
*******************************************************************************/
BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
{
    tL2C_LCB            *p_lcb;

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);

    if (!p_lcb) {
        L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
                             (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                             (rem_bda[4] << 8) + rem_bda[5]);
        return (FALSE);
    }

    L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x", __FUNCTION__,
                     (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                     (rem_bda[4] << 8) + rem_bda[5], enable, p_lcb->conn_update_mask);

    if (p_lcb->transport != BT_TRANSPORT_LE) {
        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
                             (rem_bda[0] << 24) + (rem_bda[1] << 16) + (rem_bda[2] << 8) + rem_bda[3],
                             (rem_bda[4] << 8) + rem_bda[5], p_lcb->link_role);
        return (FALSE);
    }

    if (p_lcb->current_used_conn_interval <= BTM_BLE_CONN_INT_MAX_DEF && (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0){
        return (FALSE);
    }
    bool is_disable = (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE);
    if(l2cu_plcb_active_count() >1 && !(enable && is_disable)) {
        return FALSE;
    }

    if (enable) {
        p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
    } else {
        p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
    }

    if (l2cble_start_conn_update(p_lcb) == TRUE) {
        UINT32 time = CalConnectParamTimeout(p_lcb);
        btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
    }

    return (TRUE);
}

/*******************************************************************************
**
** Function         L2CA_GetBleConnRole
**
** Description      This function returns the connection role.
**
** Returns          link role.
**
*******************************************************************************/
UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
{
    UINT8       role = HCI_ROLE_UNKNOWN;

    tL2C_LCB *p_lcb;

    if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL) {
        role = p_lcb->link_role;
    }

    return role;
}

/*******************************************************************************
**
** Function l2cble_notify_le_connection
**
** Description This function notifiy the l2cap connection to the app layer
**
** Returns none
**
*******************************************************************************/
void l2cble_notify_le_connection (BD_ADDR bda)
{
    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
    tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;

    if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED) {

        if(p_acl->link_role == HCI_ROLE_SLAVE) {
            //clear p_cb->state, controller will stop adv when ble connected.
            tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
            if(p_cb) {
                p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
                p_cb->state = BTM_BLE_STOP_ADV;
            }
        }
        /* update link status */
        btm_establish_continue(p_acl);
        /* update l2cap link status and send callback */
        p_lcb->link_state = LST_CONNECTED;
        l2cu_process_fixed_chnl_resp (p_lcb);
    }
}

/*******************************************************************************
**
** Function         l2cble_scanner_conn_comp
**
** Description      This function is called when an HCI Connection Complete
**                  event is received while we are a scanner (so we are master).
**
** Returns          void
**
*******************************************************************************/
void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
                               UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
    tL2C_LCB            *p_lcb;
    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);

    L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
                       handle,  type, conn_interval, conn_latency, conn_timeout);

    l2cb.is_ble_connecting = FALSE;

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);

    /* If we don't have one, create one. this is auto connection complete. */
    if (!p_lcb) {
        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
        if (!p_lcb) {
#if (SMP_INCLUDED == TRUE)
            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
            L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
#endif  ///SMP_INCLUDED == TRUE
            return;
        } else {
            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) {
#if (SMP_INCLUDED == TRUE)
                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
#endif  ///SMP_INCLUDED == TRUE
                return ;
            }
        }
    } else if (p_lcb->link_state != LST_CONNECTING) {
        L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
        return;
    }
    btu_stop_timer(&p_lcb->timer_entry);

    /* Save the handle */
    p_lcb->handle = handle;

    /* Connected OK. Change state to connected, we were scanning so we are master */
    p_lcb->link_role  = HCI_ROLE_MASTER;
    p_lcb->transport  = BT_TRANSPORT_LE;

    /* update link parameter, set slave link as non-spec default upon link up */
    p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval;
    p_lcb->waiting_update_conn_timeout = p_lcb->current_used_conn_timeout = conn_timeout;
    p_lcb->waiting_update_conn_latency = p_lcb->current_used_conn_latency = conn_latency;
    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
    p_lcb->updating_param_flag = false;

    /* If there are any preferred connection parameters, set them now */
    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
            (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
            (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
            (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
            (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
            (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
            (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
            ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
              p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
             (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
             (conn_latency > p_dev_rec->conn_params.slave_latency) ||
             (conn_timeout > p_dev_rec->conn_params.supervision_tout))) {
        L2CAP_TRACE_ERROR ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d",
                           handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
                           p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);

        p_lcb->waiting_update_conn_min_interval = p_dev_rec->conn_params.min_conn_int;
        p_lcb->waiting_update_conn_max_interval = p_dev_rec->conn_params.max_conn_int;
        p_lcb->waiting_update_conn_timeout      = p_dev_rec->conn_params.supervision_tout;
        p_lcb->waiting_update_conn_latency      = p_dev_rec->conn_params.slave_latency;

        btsnd_hcic_ble_upd_ll_conn_params (handle,
                                           p_dev_rec->conn_params.min_conn_int,
                                           p_dev_rec->conn_params.max_conn_int,
                                           p_dev_rec->conn_params.slave_latency,
                                           p_dev_rec->conn_params.supervision_tout,
                                           BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
    }

    /* Tell BTM Acl management about the link */
    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);

    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;

    btm_ble_set_conn_st(BLE_CONN_IDLE);

#if BLE_PRIVACY_SPT == TRUE
    btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
#endif
}

/*******************************************************************************
**
** Function         l2cble_advertiser_conn_comp
**
** Description      This function is called when an HCI Connection Complete
**                  event is received while we are an advertiser (so we are slave).
**
** Returns          void
**
*******************************************************************************/
void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
                                  UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
    tL2C_LCB            *p_lcb;
    tBTM_SEC_DEV_REC    *p_dev_rec;
    UNUSED(type);
    UNUSED(conn_interval);
    UNUSED(conn_latency);
    UNUSED(conn_timeout);

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);

    /* If we don't have one, create one and accept the connection. */
    if (!p_lcb) {
        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
        if (!p_lcb) {
#if (SMP_INCLUDED == TRUE)
            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
#endif  ///SMP_INCLUDED == TRUE
            L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
            return;
        } else {
            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts)) {
#if (SMP_INCLUDED == TRUE)
                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
#endif  ///SMP_INCLUDED == TRUE
                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
                return ;
            }
        }
    }

    /* Save the handle */
    p_lcb->handle = handle;

    /* Connected OK. Change state to connected, we were advertising, so we are slave */
    p_lcb->link_role  = HCI_ROLE_SLAVE;
    p_lcb->transport  = BT_TRANSPORT_LE;

    /* update link parameter, set slave link as non-spec default upon link up */
    p_lcb->waiting_update_conn_min_interval = p_lcb->waiting_update_conn_max_interval = p_lcb->current_used_conn_interval = conn_interval;
    p_lcb->waiting_update_conn_timeout      =  p_lcb->current_used_conn_timeout = conn_timeout;
    p_lcb->waiting_update_conn_latency      =  p_lcb->current_used_conn_latency = conn_latency;
    p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
    p_lcb->updating_param_flag = false;

    /* Tell BTM Acl management about the link */
    p_dev_rec = btm_find_or_alloc_dev (bda);

    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);

#if BLE_PRIVACY_SPT == TRUE
    btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
#endif

    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;

    if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array)) {
        p_lcb->link_state = LST_CONNECTED;
        l2cu_process_fixed_chnl_resp (p_lcb);
    }

    /* when adv and initiating are both active, cancel the direct connection */
    if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0) {
        L2CA_CancelBleConnectReq(bda);
    }
}

/*******************************************************************************
**
** Function         l2cble_conn_comp
**
** Description      This function is called when an HCI Connection Complete
**                  event is received.
**
** Returns          void
**
*******************************************************************************/
void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
                      UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
{
    btm_ble_update_link_topology_mask(role, TRUE);

    if (role == HCI_ROLE_MASTER) {
        l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
    } else {
        l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
    }
}

/*******************************************************************************
**
**  Function        l2cble_start_conn_update
**
**  Description     start BLE connection parameter update process based on status
**
**  Parameters:     lcb : l2cap link control block
**
**  Return value:   true if successfully sending the request to peer device, else false.
**
*******************************************************************************/
static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb)
{
    UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
    tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
#endif    /* defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE */

    if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) {
        L2CAP_TRACE_WARNING("%s, the last connection update command still pending.", __func__);
        p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PARAM_FULL;
        return FALSE;
    }

    if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) {
        /* application requests to disable parameters update.
           If parameters are already updated, lets set them
           up to what has been requested during connection establishement */
        if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
                /* current connection interval is greater than default min */
                p_lcb->current_used_conn_interval > BTM_BLE_CONN_INT_MAX_DEF) {
            /* use 6 * 1.25 = 7.5 ms as fast connection parameter, 0 slave latency */
            min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
            slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
            supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;

            /* if both side 4.1, or we are master device, send HCI command */
            if (p_lcb->link_role == HCI_ROLE_MASTER
#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
                    || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
                        HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
#endif
               ) {
                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
                                                  slave_latency, supervision_tout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
            } else {
                l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
            }

            //cache save
            p_lcb->updating_conn_min_interval = min_conn_int;
            p_lcb->updating_conn_max_interval = max_conn_int;
            p_lcb->updating_param_flag = true;

            p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
            p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
            p_lcb->conn_update_mask |=  L2C_BLE_NEW_CONN_PARAM;
            return TRUE;
        }else {
            return FALSE;
        }
    } else {
        /* application allows to do update, if we were delaying one do it now */
        if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM) {
            /* if both side 4.1, or we are master device, send HCI command */
            if (p_lcb->link_role == HCI_ROLE_MASTER
#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE) && (BLE_SLAVE_UPD_CONN_PARAMS == TRUE)
                    || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
                        HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
#endif
               ) {
                btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->waiting_update_conn_min_interval,
                                                  p_lcb->waiting_update_conn_max_interval, p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
            } else {
                l2cu_send_peer_ble_par_req (p_lcb, p_lcb->waiting_update_conn_min_interval, p_lcb->waiting_update_conn_max_interval,
                                            p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout);
            }

            //cache save
            p_lcb->updating_conn_min_interval = p_lcb->waiting_update_conn_min_interval;
            p_lcb->updating_conn_max_interval = p_lcb->waiting_update_conn_max_interval;
            p_lcb->updating_param_flag = true;

            p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
            p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
            p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
            return TRUE;
        } else {
            return FALSE;
        }
    }
}

/*******************************************************************************
**
** Function         l2cble_process_conn_update_evt
**
** Description      This function enables the connection update request from remote
**                  after a successful connection update response is received.
**
** Returns          void
**
*******************************************************************************/
void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_interval,
                                                       UINT16 conn_latency, UINT16 conn_timeout)
{
    tL2C_LCB *p_lcb;

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_handle(handle);
    if (!p_lcb) {
        L2CAP_TRACE_WARNING("le con upd: inv hdl=%d", handle);
        return;
    }
    if (status == HCI_SUCCESS){
        p_lcb->current_used_conn_interval = conn_interval;
        p_lcb->current_used_conn_latency = conn_latency;
        p_lcb->current_used_conn_timeout = conn_timeout;
    }else{
        L2CAP_TRACE_WARNING("le con upd: err_stat=0x%x", status);
    }

    p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
    p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
    btu_stop_timer(&p_lcb->upda_con_timer);

    if (conn_param_update_cb.update_conn_param_cb != NULL) {
        l2c_send_update_conn_params_cb(p_lcb, status);
    }

    if (l2cble_start_conn_update(p_lcb) == TRUE) {
        UINT32 time = CalConnectParamTimeout(p_lcb);
        btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
    }

    btu_stop_timer (&p_lcb->timer_entry);

    L2CAP_TRACE_DEBUG("le con upd: conn_update_mask=%d", p_lcb->conn_update_mask);
}

/*******************************************************************************
**
** Function         l2cble_get_conn_param_format_err_from_contoller
**
** Description      This function is called when host get illegal connection paramrters
**                  format status from controller
**
** Returns          void
**
*******************************************************************************/
void l2cble_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle)
{
    tL2C_LCB *p_lcb;

    /* See if we have a link control block for the remote device */
    p_lcb = l2cu_find_lcb_by_handle(handle);
    if (!p_lcb) {
        L2CAP_TRACE_ERROR("%s: Invalid handle: %d", __FUNCTION__, handle);
        return;
    }

    p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;

    btu_stop_timer (&p_lcb->upda_con_timer);

    if (conn_param_update_cb.update_conn_param_cb != NULL) {
        l2c_send_update_conn_params_cb(p_lcb, status);
    }
    if ((p_lcb->conn_update_mask & L2C_BLE_UPDATE_PARAM_FULL) != 0){
        p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
        if (l2cble_start_conn_update(p_lcb) == TRUE) {
            UINT32 time = CalConnectParamTimeout(p_lcb);
            btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
        }
    }

}

/*******************************************************************************
**
** Function         l2cble_process_sig_cmd
**
** Description      This function is called when a signalling packet is received
**                  on the BLE signalling CID
**
** Returns          void
**
*******************************************************************************/
void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
{
    UINT8           *p_pkt_end;
    UINT8           cmd_code, id;
    UINT16          cmd_len;
    UINT16          min_interval, max_interval, latency, timeout;

    p_pkt_end = p + pkt_len;

    STREAM_TO_UINT8  (cmd_code, p);
    STREAM_TO_UINT8  (id, p);
    STREAM_TO_UINT16 (cmd_len, p);

    /* Check command length does not exceed packet length */
    if ((p + cmd_len) > p_pkt_end) {
        L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d  cmd_len: %d  code: %d", pkt_len, cmd_len, cmd_code);
        return;
    }

    switch (cmd_code) {
    case L2CAP_CMD_REJECT:
    case L2CAP_CMD_ECHO_RSP:
    case L2CAP_CMD_INFO_RSP:
        p += 2;
        break;
    case L2CAP_CMD_ECHO_REQ:
    case L2CAP_CMD_INFO_REQ:
        l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
        break;

    case L2CAP_CMD_BLE_UPDATE_REQ:
        STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
        STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
        STREAM_TO_UINT16 (latency, p);  /* 0x0000 - 0x03E8 */
        STREAM_TO_UINT16 (timeout, p);  /* 0x000A - 0x0C80 */
        /* If we are a master, the slave wants to update the parameters */
        if (p_lcb->link_role == HCI_ROLE_MASTER) {
            if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
                    max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
                    latency  > BTM_BLE_CONN_LATENCY_MAX ||
                    timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
                    /* The supervision_timeout parameter defines the link supervision timeout for the connection.
                       The supervision_timeout in milliseconds shall be large than (1 + latency) * max_interval * 2,
                       where max_interval is given in milliseconds. (See [Vol 6] Part B, Section 4.5.2).
                       supervision_timeout (mult of 10ms); conn_interval (mult of 1.25ms)
                       (max_interval * 1.25 * 2) replaced by ((max_interval * 5) >> 1).
                    */
                    ((timeout * 10) < ((1 + latency) *((max_interval * 5) >> 1))) ||
                    max_interval < min_interval) {
                l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);

                L2CAP_TRACE_ERROR("slave connection parameters update failed, the parameters are out of range");

            } else {

                l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
                p_lcb->waiting_update_conn_min_interval = min_interval;
                p_lcb->waiting_update_conn_max_interval = max_interval;
                p_lcb->waiting_update_conn_latency = latency;
                p_lcb->waiting_update_conn_timeout = timeout;
                p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;

                if (l2cble_start_conn_update(p_lcb) == TRUE) {
                    UINT32 time = CalConnectParamTimeout(p_lcb);
                    btu_start_timer(&p_lcb->upda_con_timer, BTU_TTYPE_L2CAP_UPDA_CONN_PARAMS, time);
                }
            }
        } else {
            l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
        }
        break;

    case L2CAP_CMD_BLE_UPDATE_RSP: {
        UINT16 result = 0;
        STREAM_TO_UINT16(result, p); //result = 0 connection param accepted, result = 1 connection param rejected.
        UINT8 status = (result == 0) ? HCI_SUCCESS : HCI_ERR_PARAM_OUT_OF_RANGE;
        if (status != HCI_SUCCESS) {
            btu_stop_timer(&p_lcb->upda_con_timer);
            p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
            p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PARAM_FULL;
            l2c_send_update_conn_params_cb(p_lcb, status);
        }
        break;
    }
    default:
        L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
        l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
        return;
    }
}

/*******************************************************************************
**
** Function         l2cble_init_direct_conn
**
** Description      This function is to initate a direct connection
**
** Returns          TRUE connection initiated, FALSE otherwise.
**
*******************************************************************************/
BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
{
#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE) && (!CONTROLLER_RPA_LIST_ENABLE))
    //check for security device information in the cache
    bool dev_rec_exist = true;
    tBTM_SEC_DEV_REC *find_dev_rec = btm_find_dev (p_lcb->remote_bd_addr);
    if(find_dev_rec == NULL) {
        dev_rec_exist = false;
    }

#endif // ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE) && (!CONTROLLER_RPA_LIST_ENABLE))
    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
    UINT16 scan_int;
    UINT16 scan_win;
    BD_ADDR peer_addr;
    UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
    UINT8 own_addr_type = BLE_ADDR_PUBLIC;

    /* There can be only one BLE connection request outstanding at a time */
    if (p_dev_rec == NULL) {
        L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
        return (FALSE);
    }

    scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;

    peer_addr_type = p_lcb->ble_addr_type;
    memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);

#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
    own_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
#if (!CONTROLLER_RPA_LIST_ENABLE)
    if(dev_rec_exist) {
        // if the current address information is valid, get the real address information
        if(p_dev_rec->ble.current_addr_valid) {
            peer_addr_type = p_dev_rec->ble.current_addr_type;
            memcpy(peer_addr, p_dev_rec->ble.current_addr, 6);
        } else {
            /* find security device information but not find the real address information
             * This state may be directly open without scanning. In this case, you must
             * use the current adv address of the device to open*/
        }
    } else {
        //not find security device information, We think this is a new device, connect directly
    }

    /* It will cause that scanner doesn't send scan request to advertiser
    * which has sent IRK to us and we have stored the IRK in controller.
    * It is a hardware limitation. The preliminary solution is not to
    * send key to the controller, but to resolve the random address in host.
    * so we need send the real address information to controller. */

#endif // (!CONTROLLER_RPA_LIST_ENABLE)

#if (CONTROLLER_RPA_LIST_ENABLE)

    if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
        if (btm_cb.ble_ctr_cb.privacy_mode >=  BTM_PRIVACY_1_2) {
            own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
        }

        //btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
        btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
    } else {
        btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
    }

#endif // CONTROLLER_RPA_LIST_ENABLE
#endif // (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE)

    if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
        l2cu_release_lcb (p_lcb);
        L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
        return FALSE;
    }
    uint32_t link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
    if(GATTC_CONNECT_RETRY_COUNT) {
        if(!p_lcb->retry_create_con) {
            p_lcb->start_time_s = (esp_system_get_time()/1000);
        }
        uint32_t current_time = (esp_system_get_time()/1000);
        link_timeout = (L2CAP_BLE_LINK_CONNECT_TOUT*1000 - (current_time - p_lcb->start_time_s))/1000;

        if(link_timeout == 0 || link_timeout > L2CAP_BLE_LINK_CONNECT_TOUT) {
            link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
        }
    }

    if (!p_lcb->is_aux) {
        if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                            scan_win, /* UINT16 scan_win      */
                                            FALSE,                   /* UINT8 white_list     */
                                            peer_addr_type,          /* UINT8 addr_type_peer */
                                            peer_addr,               /* BD_ADDR bda_peer     */
                                            own_addr_type,         /* UINT8 addr_type_own  */
                                            (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                    p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* UINT16 conn_int_min  */
                                            (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                    p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* UINT16 conn_int_max  */
                                            (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                    p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
                                            (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
                                                    p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
                                            BLE_CE_LEN_MIN,                       /* UINT16 min_len       */
                                            BLE_CE_LEN_MIN)) {                    /* UINT16 max_len       */
            l2cu_release_lcb (p_lcb);
            L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
            return (FALSE);
        } else {
            p_lcb->link_state = LST_CONNECTING;
            l2cb.is_ble_connecting = TRUE;
            memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
            btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
            btm_ble_set_conn_st (BLE_DIR_CONN);

            return (TRUE);
        }
    } else {
#if (BLE_50_FEATURE_SUPPORT == TRUE)

        /*
        * 0x00 Public Device Address
        * 0x01 Random Device Address
        * 0x02 Public Identity Address (corresponds to Resolved Private Address)
        * 0x03 Random (static) Identity Address (corresponds to Resolved Private Address)
        * 0xFF No address provided (anonymous advertisement)
        */

        if ((peer_addr_type & BLE_ADDR_RANDOM) == BLE_ADDR_RANDOM) {
            peer_addr_type = BLE_ADDR_RANDOM;
        } else {
            peer_addr_type = BLE_ADDR_PUBLIC;
        }

        tHCI_CreatExtConn aux_conn = {0};
        aux_conn.filter_policy = FALSE;
        aux_conn.own_addr_type = own_addr_type;
        aux_conn.peer_addr_type = peer_addr_type;
        memcpy(aux_conn.peer_addr, peer_addr, sizeof(BD_ADDR));
        if (p_dev_rec->ext_conn_params.phy_mask == BLE_PHY_NO_PREF) {
            L2CAP_TRACE_WARNING("No extend connection parameters set, use default parameters");
            aux_conn.init_phy_mask = BLE_PHY_PREF_MASK;
            memcpy(&aux_conn.params[0], &ext_conn_params, sizeof(tHCI_ExtConnParams));
            memcpy(&aux_conn.params[1], &ext_conn_params, sizeof(tHCI_ExtConnParams));
            memcpy(&aux_conn.params[2], &ext_conn_params, sizeof(tHCI_ExtConnParams));
        } else {
            aux_conn.init_phy_mask = p_dev_rec->ext_conn_params.phy_mask;
            memcpy(&aux_conn.params[0], &p_dev_rec->ext_conn_params.phy_1m_conn_params, sizeof(tHCI_ExtConnParams));
            memcpy(&aux_conn.params[1], &p_dev_rec->ext_conn_params.phy_2m_conn_params, sizeof(tHCI_ExtConnParams));
            memcpy(&aux_conn.params[2], &p_dev_rec->ext_conn_params.phy_coded_conn_params, sizeof(tHCI_ExtConnParams));
        }
        p_lcb->link_state = LST_CONNECTING;
        l2cb.is_ble_connecting = TRUE;
        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
        btm_ble_set_conn_st (BLE_DIR_CONN);
        if(!btsnd_hcic_ble_create_ext_conn(&aux_conn)) {
            l2cu_release_lcb (p_lcb);
            L2CAP_TRACE_ERROR("initate Aux connection failed, no resources");
        }
#else
    L2CAP_TRACE_ERROR("BLE 5.0 not support!\n");
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
        return (TRUE);
    }
}

/*******************************************************************************
**
** Function         l2cble_create_conn
**
** Description      This function initiates an acl connection via HCI
**
** Returns          TRUE if successful, FALSE if connection not started.
**
*******************************************************************************/
BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
{
    tBTM_BLE_CONN_ST     conn_st = btm_ble_get_conn_st();
    BOOLEAN         rt = FALSE;

    /* There can be only one BLE connection request outstanding at a time */
    if (conn_st == BLE_CONN_IDLE) {
        rt = l2cble_init_direct_conn(p_lcb);
    } else {
        L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);

        btm_ble_enqueue_direct_conn_req(p_lcb);

        if (conn_st == BLE_BG_CONN) {
            btm_ble_suspend_bg_conn();
        }

        rt = TRUE;
    }
    return rt;
}

/*******************************************************************************
**
** Function         l2c_link_processs_ble_num_bufs
**
** Description      This function is called when a "controller buffer size"
**                  event is first received from the controller. It updates
**                  the L2CAP values.
**
** Returns          void
**
*******************************************************************************/
void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
{
    if (num_lm_ble_bufs == 0) {
        num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
        l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
    }
    L2CAP_TRACE_DEBUG("num_lm_ble_bufs = %d",num_lm_ble_bufs);
    l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
}

/*******************************************************************************
**
** Function         l2c_ble_link_adjust_allocation
**
** Description      This function is called when a link is created or removed
**                  to calculate the amount of packets each link may send to
**                  the HCI without an ack coming back.
**
**                  Currently, this is a simple allocation, dividing the
**                  number of Controller Packets by the number of links. In
**                  the future, QOS configuration should be examined.
**
** Returns          void
**
*******************************************************************************/
void l2c_ble_link_adjust_allocation (void)
{
    UINT16      qq, qq_remainder;
    tL2C_LCB    *p_lcb;
    UINT16      hi_quota, low_quota;
    UINT16      num_lowpri_links = 0;
    UINT16      num_hipri_links  = 0;
    UINT16      controller_xmit_quota = l2cb.num_lm_ble_bufs;
    UINT16      high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
    list_node_t *p_node = NULL;

    /* If no links active, reset buffer quotas and controller buffers */
    if (l2cb.num_ble_links_active == 0) {
        l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
        l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
        return;
    }

    /* First, count the links */
    for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
        p_lcb = list_node(p_node);
        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
                num_hipri_links++;
            } else {
                num_lowpri_links++;
            }
        }
    }

    /* now adjust high priority link quota */
    low_quota = num_lowpri_links ? 1 : 0;
    while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota ) {
        high_pri_link_quota--;
    }

    /* Work out the xmit quota and buffer quota high and low priorities */
    hi_quota  = num_hipri_links * high_pri_link_quota;
    low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;

    /* Work out and save the HCI xmit quota for each low priority link */

    /* If each low priority link cannot have at least one buffer */
    if (num_lowpri_links > low_quota) {
        l2cb.ble_round_robin_quota = low_quota;
        qq = qq_remainder = 0;
    }
    /* If each low priority link can have at least one buffer */
    else if (num_lowpri_links > 0) {
        l2cb.ble_round_robin_quota = 0;
        l2cb.ble_round_robin_unacked = 0;
        qq = low_quota / num_lowpri_links;
        qq_remainder = low_quota % num_lowpri_links;
    }
    /* If no low priority link */
    else {
        l2cb.ble_round_robin_quota = 0;
        l2cb.ble_round_robin_unacked = 0;
        qq = qq_remainder = 0;
    }
    L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
                       num_hipri_links, num_lowpri_links, low_quota,
                       l2cb.ble_round_robin_quota, qq);

    /* Now, assign the quotas to each link */
    p_node = NULL;
    for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
        p_lcb = list_node(p_node);
        if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE) {
            if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH) {
                p_lcb->link_xmit_quota   = high_pri_link_quota;
            } else {
                /* Safety check in case we switched to round-robin with something outstanding */
                /* if sent_not_acked is added into round_robin_unacked then don't add it again */
                /* l2cap keeps updating sent_not_acked for exiting from round robin */
                if (( p_lcb->link_xmit_quota > 0 ) && ( qq == 0 )) {
                    l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
                }

                p_lcb->link_xmit_quota   = qq;
                if (qq_remainder > 0) {
                    p_lcb->link_xmit_quota++;
                    qq_remainder--;
                }
            }

            L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation   Priority: %d  XmitQuota: %d",
                              p_lcb->acl_priority, p_lcb->link_xmit_quota);

            L2CAP_TRACE_EVENT("        SentNotAcked: %d  RRUnacked: %d",
                              p_lcb->sent_not_acked, l2cb.round_robin_unacked);

            /* There is a special case where we have readjusted the link quotas and  */
            /* this link may have sent anything but some other link sent packets so  */
            /* so we may need a timer to kick off this link's transmissions.         */
            if ( (p_lcb->link_state == LST_CONNECTED)
                    && (!list_is_empty(p_lcb->link_xmit_data_q))
                    && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) ) {
                btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_LINK_FLOW_CONTROL_TOUT);
            }
        }
    }
}

#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
/*******************************************************************************
**
** Function         l2cble_process_rc_param_request_evt
**
** Description      process LE Remote Connection Parameter Request Event.
**
** Returns          void
**
*******************************************************************************/
void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
        UINT16 latency, UINT16 timeout)
{
    tL2C_LCB    *p_lcb = l2cu_find_lcb_by_handle (handle);

    if (p_lcb != NULL) {

        /* if update is enabled, always accept connection parameter update */
        if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
            p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
            btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
        }else {
            /* always accept connection parameters request which is sent by itself */
            if (int_max == BTM_BLE_CONN_INT_MIN) {
                p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
                btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
            }else {
                L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
                p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
                btsnd_hcic_ble_rc_param_req_neg_reply (handle, HCI_ERR_UNACCEPT_CONN_INTERVAL);
            }
        }

    } else {
        L2CAP_TRACE_WARNING("No link to update connection parameter")
    }
}
#endif

/*******************************************************************************
**
** Function         l2cble_update_data_length
**
** Description      This function update link tx data length if applicable
**
** Returns          void
**
*******************************************************************************/
void l2cble_update_data_length(tL2C_LCB *p_lcb)
{
    UINT16 tx_mtu = 0;
    UINT16 i = 0;

    L2CAP_TRACE_DEBUG("%s", __FUNCTION__);

    /* See if we have a link control block for the connection */
    if (p_lcb == NULL) {
        return;
    }

    for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++) {
        if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID) {
            if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
                    (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD))) {
                tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
            }
        }
    }

    if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) {
        tx_mtu = BTM_BLE_DATA_SIZE_MAX;
    }

    /* update TX data length if changed */
    if (p_lcb->tx_data_len != tx_mtu) {
        BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
    }

}

/*******************************************************************************
**
** Function         l2cble_process_data_length_change_evt
**
** Description      This function process the data length change event
**
** Returns          void
**
*******************************************************************************/
void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
{
    tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
    tACL_CONN *p_acl = btm_handle_to_acl(handle);
    tBTM_LE_SET_PKT_DATA_LENGTH_PARAMS data_length_params;

    L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
    if (p_lcb == NULL) {
        return;
    }

    if (tx_data_len > 0) {
        p_lcb->tx_data_len = tx_data_len;
    }

    data_length_params.rx_len = rx_data_len;
    data_length_params.tx_len = tx_data_len;

    if(p_acl) {
        p_acl->data_length_params = data_length_params;
        if (p_acl->p_set_pkt_data_cback) {
            (*p_acl->p_set_pkt_data_cback)(BTM_SUCCESS, &data_length_params);
        }

        p_acl->data_len_updating = false;
        if(p_acl->data_len_waiting) {
            p_acl->data_len_waiting = false;
            p_acl->p_set_pkt_data_cback = p_acl->p_set_data_len_cback_waiting;
            p_acl->p_set_data_len_cback_waiting = NULL;
            // if value is same, triger callback directly
            if(p_acl->tx_len_waiting == p_acl->data_length_params.tx_len) {
                if(p_acl->p_set_pkt_data_cback) {
                    (*p_acl->p_set_pkt_data_cback)(BTM_SUCCESS, &p_acl->data_length_params);
                }
                return;
            }
            p_acl->data_len_updating = true;
            /* always set the TxTime to be max, as controller does not care for now */
            btsnd_hcic_ble_set_data_length(handle, p_acl->tx_len_waiting,
                                            BTM_BLE_DATA_TX_TIME_MAX);
        }
    }
}

/*******************************************************************************
**
** Function         l2cble_set_fixed_channel_tx_data_length
**
** Description      This function update max fixed channel tx data length if applicable
**
** Returns          void
**
*******************************************************************************/
void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
{
    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
    UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;

    L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);

    if (!controller_get_interface()->supports_ble_packet_extension()) {
        L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
        return;
    }

    /* See if we have a link control block for the connection */
    if (p_lcb == NULL) {
        return;
    }

    if (p_lcb->p_fixed_ccbs[cid] != NULL) {
        if (tx_mtu > BTM_BLE_DATA_SIZE_MAX) {
            tx_mtu = BTM_BLE_DATA_SIZE_MAX;
        }

        p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
    }

    l2cble_update_data_length(p_lcb);
}

/*******************************************************************************
**
** Function         l2c_send_update_conn_params_cb
**
** Description      This function send the update connection parameter callback to the uplayer.
**
** Returns          void
**
*******************************************************************************/
void l2c_send_update_conn_params_cb(tL2C_LCB *p_lcb, UINT8 status)
{
    if(conn_param_update_cb.update_conn_param_cb != NULL){
        tBTM_LE_UPDATE_CONN_PRAMS update_param;
        //if myself update the connection parameters
        if (p_lcb->updating_param_flag){
            update_param.max_conn_int = p_lcb->updating_conn_max_interval;
            update_param.min_conn_int = p_lcb->updating_conn_min_interval;
            p_lcb->updating_param_flag = false;
        }else{
            // remote device update the connection parameters
            update_param.max_conn_int = update_param.min_conn_int = 0;
        }
        // current connection parameters
        update_param.conn_int = p_lcb->current_used_conn_interval;
        update_param.slave_latency = p_lcb->current_used_conn_latency;
        update_param.supervision_tout = p_lcb->current_used_conn_timeout;

        (conn_param_update_cb.update_conn_param_cb)(status, p_lcb->remote_bd_addr, &update_param);
    }
}

/*******************************************************************************
**
** Function         CalConnectParamTimeout
**
** Description      This function is called to calculate the connection parameter timeout.
**
** Returns          timeout
**
*******************************************************************************/
UINT32 CalConnectParamTimeout(tL2C_LCB *p_lcb)
{
    UINT32 timeout = 6;
    if (p_lcb != NULL){
        //1.25 * conn_int *(1+ latency) *32
        timeout = (40 * ( 1 + p_lcb->current_used_conn_latency) * p_lcb->current_used_conn_interval + 1000) / 1000;
        if (timeout < 1){
            timeout = 1;
        }else if (timeout > 120){
            timeout = 120;
        }
    }
    return timeout;
}

/*******************************************************************************
**
** Function         l2cble_credit_based_conn_req
**
** Description      This function sends LE Credit Based Connection Request for
**                  LE connection oriented channels.
**
** Returns          void
**
*******************************************************************************/
void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb)
{
    if (!p_ccb) {
        return;
    }

    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
    {
        L2CAP_TRACE_WARNING ("LE link doesn't exist");
        return;
    }

    l2cu_send_peer_ble_credit_based_conn_req (p_ccb);
    return;
}

/*******************************************************************************
**
** Function         l2cble_credit_based_conn_res
**
** Description      This function sends LE Credit Based Connection Response for
**                  LE connection oriented channels.
**
** Returns          void
**
*******************************************************************************/
void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
{
    if (!p_ccb) {
        return;
    }

    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
    {
        L2CAP_TRACE_WARNING ("LE link doesn't exist");
        return;
    }

    l2cu_send_peer_ble_credit_based_conn_res (p_ccb, result);
    return;
}

/*******************************************************************************
**
** Function         l2cble_send_flow_control_credit
**
** Description      This function sends flow control credits for
**                  LE connection oriented channels.
**
** Returns          void
**
*******************************************************************************/
void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
{
    if (!p_ccb) {
        return;
    }

    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
    {
        L2CAP_TRACE_WARNING ("LE link doesn't exist");
        return;
    }

    l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
    return;

}

/*******************************************************************************
**
** Function         l2cble_send_peer_disc_req
**
** Description      This function sends disconnect request
**                  to the peer LE device
**
** Returns          void
**
*******************************************************************************/
void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb)
{
    L2CAP_TRACE_DEBUG ("%s",__func__);
    if (!p_ccb) {
        return;
    }

    if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
    {
        L2CAP_TRACE_WARNING ("LE link doesn't exist");
        return;
    }

    l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
    return;
}

#if (SMP_INCLUDED == TRUE)
/*******************************************************************************
**
** Function         l2cble_sec_comp
**
** Description      This function is called when security procedure for an LE COC
**                  link is done
**
** Returns          void
**
*******************************************************************************/
void  l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
{
    tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
    tL2CAP_SEC_DATA *p_buf = NULL;
    UINT8 sec_flag;
    UINT8 sec_act;

    if (!p_lcb)
    {
        L2CAP_TRACE_WARNING ("%s security complete for unknown device", __func__);
        return;
    }

    sec_act = p_lcb->sec_act;
    p_lcb->sec_act = 0;

    if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
    {
        p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q, FIXED_QUEUE_MAX_TIMEOUT);
        if (!p_buf)
        {
            L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP",
                    __func__);
            return;
        }

        if (status != BTM_SUCCESS)
        {
            (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
        }
        else
        {
            if (sec_act == BTM_SEC_ENCRYPT_MITM)
            {
                BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
                if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) {
                    (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
                }
                else
                {
                    L2CAP_TRACE_DEBUG ("%s MITM Protection Not present", __func__);
                    (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
                            BTM_FAILED_ON_SECURITY);
                }
            }
            else
            {
                L2CAP_TRACE_DEBUG ("%s MITM Protection not required sec_act = %d",
                        __func__, p_lcb->sec_act);

                (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
            }
        }
    }
    else
    {
        L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP", __func__);
        return;
    }
    osi_free(p_buf);

    while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
    {
        p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q, FIXED_QUEUE_MAX_TIMEOUT);

        if (status != BTM_SUCCESS) {
            (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
        } else {
            l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
                    p_buf->p_callback, p_buf->p_ref_data);
        }

       osi_free(p_buf);
    }
}

/*******************************************************************************
**
** Function         l2ble_sec_access_req
**
** Description      This function is called by LE COC link to meet the
**                  security requirement for the link
**
** Returns          TRUE - security procedures are started
**                  FALSE - failure
**
*******************************************************************************/
BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data)
{
    L2CAP_TRACE_DEBUG ("%s", __func__);
    BOOLEAN status;
    tL2C_LCB *p_lcb = NULL;

    if (!p_callback)
    {
        L2CAP_TRACE_ERROR("%s No callback function", __func__);
        return FALSE;
    }

    p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);

    if (!p_lcb)
    {
        L2CAP_TRACE_ERROR ("%s Security check for unknown device", __func__);
        p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
        return FALSE;
    }

    tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) osi_malloc((UINT16)sizeof(tL2CAP_SEC_DATA));
    if (!p_buf)
    {
        p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
        return FALSE;
    }

    p_buf->psm = psm;
    p_buf->is_originator = is_originator;
    p_buf->p_callback = p_callback;
    p_buf->p_ref_data = p_ref_data;
    fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf, FIXED_QUEUE_MAX_TIMEOUT);
    status = btm_ble_start_sec_check(bd_addr, psm, is_originator, &l2cble_sec_comp, p_ref_data);

    return status;
}
#endif /* #if (SMP_INCLUDED == TRUE) */
#endif /* (BLE_INCLUDED == TRUE) */
/*******************************************************************************
**
** Function         L2CA_GetDisconnectReason
**
** Description      This function returns the disconnect reason code.
**
** Returns          disconnect reason
**
*******************************************************************************/
UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
{
    tL2C_LCB            *p_lcb;
    UINT16              reason = 0;

    if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL) {
        reason = p_lcb->disc_reason;
    }

    L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ", reason);

    return reason;
}

redpajama_set_name: RedPajamaGithub


text:
namespace courgette {

namespace {

// Helper class to load and execute a Rel32Finder test case.
class Rel32FinderTestCase {
 public:
  Rel32FinderTestCase(const std::string& test_data)
      : text_start_rva_(0),
        text_end_rva_(0),
        relocs_start_rva_(0),
        relocs_end_rva_(0),
        image_end_rva_(0) {
    LoadTestFromString(test_data);
  }

  void RunTestBasic(std::string name) {
    ASSERT_FALSE(text_data_.empty());
    finder_->Find(&text_data_[0], &text_data_[0] + text_data_.size(),
                  text_start_rva_, text_end_rva_, abs32_locations_);
    std::vector<RVA> rel32_locations;
    finder_->SwapRel32Locations(&rel32_locations);
    EXPECT_EQ(expected_rel32_locations_, rel32_locations)
        << "From test case " << name << " (addresses are in hex)";
  }

  void CreateFinder(const std::string& processor_type) {
    if (processor_type == "x64") {
      finder_ = std::unique_ptr<Rel32Finder>(new Rel32FinderX64(
          relocs_start_rva_, relocs_end_rva_, image_end_rva_));
    } else if (processor_type == "x86") {
      finder_ = std::unique_ptr<Rel32Finder>(
          new Rel32FinderX86(relocs_start_rva_, relocs_end_rva_));
    } else {
      NOTREACHED();
    }
  }

 private:
  std::unique_ptr<Rel32Finder> finder_;
  RVA text_start_rva_;
  RVA text_end_rva_;
  RVA relocs_start_rva_;
  RVA relocs_end_rva_;
  RVA image_end_rva_;
  std::vector<uint8_t> text_data_;
  std::vector<RVA> abs32_locations_;
  std::vector<RVA> expected_rel32_locations_;

  // Scans |iss| for the next non-empty line, after removing "#"-style comments
  // and stripping trailing spaces. On success, returns true and writes the
  // result to |line_out|. Otherwise returns false.
  bool ReadNonEmptyLine(std::istringstream& iss, std::string* line_out) {
    std::string line;
    while (std::getline(iss, line)) {
      // Trim comments and trailing spaces.
      size_t end_pos = std::min(line.find("#"), line.length());
      while (end_pos > 0 && line[end_pos - 1] == ' ')
        --end_pos;
      line.resize(end_pos);
      if (!line.empty())
        break;
    }
    if (line.empty())
      return false;
    line_out->swap(line);
    return true;
  }

  // Scans |iss| for the next non-empty line, and reads (hex) uint32_t into |v|.
  // Returns true iff successful.
  bool ReadHexUInt32(std::istringstream& iss, uint32_t* v) {
    std::string line;
    if (!ReadNonEmptyLine(iss, &line))
      return false;
    return sscanf(line.c_str(), "%X", v) == 1;
  }

  // Initializes the test case by parsing the multi-line string |test_data|
  // to extract Rel32Finder parameters, and read expected values.
  void LoadTestFromString(const std::string& test_data) {
    // The first lines (ignoring empty ones) specify RVA bounds.
    std::istringstream iss(test_data);
    std::string processor_type;
    ASSERT_TRUE(ReadNonEmptyLine(iss, &processor_type));
    ASSERT_TRUE(ReadHexUInt32(iss, &text_start_rva_));
    ASSERT_TRUE(ReadHexUInt32(iss, &text_end_rva_));
    ASSERT_TRUE(ReadHexUInt32(iss, &relocs_start_rva_));
    ASSERT_TRUE(ReadHexUInt32(iss, &relocs_end_rva_));
    ASSERT_TRUE(ReadHexUInt32(iss, &image_end_rva_));

    std::string line;
    // The Program section specifies instruction bytes. We require lines to be
    // formatted in "DUMPBIN /DISASM" style, i.e.,
    // "00401003: E8 00 00 00 00     call        00401008"
    //            ^  ^  ^  ^  ^  ^
    // We extract up to 6 bytes per line. The remaining are ignored.
    const int kBytesBegin = 12;
    const int kBytesEnd = 17;
    ReadNonEmptyLine(iss, &line);
    ASSERT_EQ("Program:", line);
    while (ReadNonEmptyLine(iss, &line) && line != "Abs32:") {
      std::string toks = line.substr(kBytesBegin, kBytesEnd);
      uint32_t vals[6];
      int num_read = sscanf(toks.c_str(), "%X %X %X %X %X %X", &vals[0],
                            &vals[1], &vals[2], &vals[3], &vals[4], &vals[5]);
      for (int i = 0; i < num_read; ++i)
        text_data_.push_back(static_cast<uint8_t>(vals[i] & 0xFF));
    }
    ASSERT_FALSE(text_data_.empty());

    // The Abs32 section specifies hex RVAs, one per line.
    ASSERT_EQ("Abs32:", line);
    while (ReadNonEmptyLine(iss, &line) && line != "Expected:") {
      RVA abs32_location;
      ASSERT_EQ(1, sscanf(line.c_str(), "%X", &abs32_location));
      abs32_locations_.push_back(abs32_location);
    }

    // The Expected section specifies hex Rel32 RVAs, one per line.
    ASSERT_EQ("Expected:", line);
    while (ReadNonEmptyLine(iss, &line)) {
      RVA rel32_location;
      ASSERT_EQ(1, sscanf(line.c_str(), "%X", &rel32_location));
      expected_rel32_locations_.push_back(rel32_location);
    }
    CreateFinder(processor_type);
  }
};

class Rel32FinderTest : public BaseTest {
 public:
  void RunTest(const char* test_case_file) {
    Rel32FinderTestCase test_case(FileContents(test_case_file));
    test_case.RunTestBasic(test_case_file);
  }
};

TEST_F(Rel32FinderTest, TestBasic) {
  RunTest("rel32_x86_01.txt");
  RunTest("rel32_x86_02.txt");
  RunTest("rel32_x86_03.txt");
  RunTest("rel32_x86_04.txt");

  RunTest("rel32_x64_01.txt");
  RunTest("rel32_x64_02.txt");
  RunTest("rel32_x64_03.txt");
}

}  // namespace

}  // namespace courgette


Metropolitan Property Management is a full-service property management firm specializing in maintaining its portfolio of properties and resident relationships.
Metropolitan Property Management is a Philadelphia based management company that seeks to offer a higher quality of life for all of its residents. We strive to exceed expectations in customer support offering longer hours of operation, dedicated and attentive property managers, emergency availability 24/7, and a commitment to our residents of an overall positive experience. Metropolitan operates with decades of experience proactively maintaining and updating all of its properties, expeditiously making necessary repairs and resolving resident issues promptly. Our mission is to make you feel at home without the inconvenience of maintaining, repairing or improving your home.


text:
Relatively Scottish
Family History Research for Scots and those of Scottish Heritage
House Histories in the South of Scotland
Scottish Borders Family History
Borders Estate Rentals
Prices for Genealogical Research
Home→Uncategorized→The joy of researching the Border reiver families
← Bondagers in Berwickshire and Roxburghshire
Top Ten Kelso Surnames of 1780 →
The joy of researching the Border reiver families
Posted on October 31, 2015 by adminaa
What are the chances of being able to research ordinary Scottish ancestors from the 16th century ? Normally, the answer has to be next to none. If you weren't nobility or titled then almost certainly no records will survive to even hint at your existence. Its too early for almost all surviving church records , except perhaps for the minister himself. Almost no headstones survive from that era. And what about property transactions, however unlikely that may be for an average ancestor ? Well the register of sasines was only started properly in 1617. A DNA test might demonstrate genetic succession but it wouldn't tell you anything about 16th century lives.
A 1590 map of strong Scottish towers on Liddesdale drawn by an English 'spy'.
But what if your actions presented a real risk to national and international security ? What if your area was considered to be beyond the law ? Then , not so different from modern times, the state was interested and your actions would be spied upon, noted and reported to the highest authorities in the land. And thankfully, most of this intelligence has survived to the present day. As a result, there exists a marvellous legacy of information about the actions of many families who lived close to the Anglo-Scottish border and supplemented their meagre incomes with cross-border crimes of theft, blackmail, ransom and murder on a regular basis throughout the 16th century.
The Calendar of Border Papers is a compilation of intelligence gathered on the English side of the Border between 1560 and 1603 which includes complaints made by English residents about crimes committed against them mainly by Scottish reivers, letters between various English officials and indeed the Queen herself on occasion, and reports from spies and other Border officials about key individual troublemakers. On the Scottish side, the Register of the Privy Council of Scotland deals with pressing matters from the southern frontier and names many border troublemakers too.
These sources and others have allowed us in modern times to examine the importance of kinship in defining how the Border reivers operated and how the various families, closely allied to very particular territory on the Border , interacted with one another. Genealogy is all about family relationships and nothing defined the Border more than the fierce family loyalties of the time. The use of To-Names in official descriptions helps us to imagine the character,appearance and indeed humour of some of our ancestors whether it's Willie 'Redcloak' Bell, Ill Will Armstrong or Archie 'Fire the Braes' Elliot. The ringleaders played a long strategic game with the authorities. The calculated way in which many of them married girls from across the Border succeeded in undermining the authorities of each country by creating important cross-Border family alliances.
So the study of the genealogy of the Border reiving families allows us a unique insight into 16th century life however untypical it may have been. Like Sir Walter Scott before us (who was directly descended from a notorious reiver) , we may choose to romanticise this undoubtedly brutal lifestyle , but if that helps to bring our history alive and make it feel relevant for us today then is that such a bad thing ? I contend that the story of the reiving families of both Scotland and England that we can construct from contemporary sources is an absolutely fascinating one and one that I'm delighted to be involved with. We may not always be able to identify specific individual ancestors in this era but we can build up a considerable picture of their kinsfolk and where and how they lived. For me genealogy is as much about understanding contemporary lifestyle of the greater family groups than it is about a single name in a family tree.
The joy of researching the Border reiver families — 13 Comments
Jeff graham on May 17, 2018 at 4:47 am said:
Thanks for an interesting read. I was wondering if you can help me. Have you ever heard of the places called Greystoke and Penrith I've traced my line of Grahams to those places in England. One of our relatives from that region ended up a convict and transported to western Australia he then became bush ranger known as William the fiddler Graham.
adminaa on May 17, 2018 at 9:07 pm said:
Penrith is a town about 25 miles south of the parish of Kirkandrews in England, the main area where the border Grahams lived up to 1603. Greystoke is a small village about 4 miles from Penrith.
After 1603, the English authorities tried twice to forcibly transport all the Grahams that they could find firstly to Holland and then, when that failed, to Roscommon in Ireland. Ultimately it failed and many made their way back to Cumberland.
So over 200 years later your William hadn't really moved far until of course his transportation to WA which was clearly more effective than the previous attempts !
Jeff Graham on November 19, 2018 at 1:11 pm said:
Thanks for the info, yep my Grahams are bad to the bone its in the blood. Even as a young fellow my best friends had riever surnames such Armstrong, Elliot, and Bell not knowing about our family histories on the other side of the planet. Many convicts and early settlers took aboriginal wives my family included sadly devastating the ancient original culture and the lawful marriages that were central to a very cohesive and relatively peaceful society.
Jeff Graham.
Mark Elliott on July 25, 2018 at 9:26 pm said:
Didn't think much of being related to a Clementis Hob, until a met an Armstrong who felt he was related to a Gilknockie, and that made me feel better about it.
http://gorrenberry.com/clementis-hobs-stobs/
http://www.elwald.com/wp-content/uploads/2013/05/Clementis-Hob1.pdf
John Elwald rector of Kirkandrews c1420;
http://www.elwald.com/wp-content/uploads/2013/05/John-Elwald.pdf
http://gorrenberry.com/john-elwald-1418-rector-st-andrews-conn-mcconnell-mccall-dna-kirkinner-carnesmole/
Alan Elliott on March 14, 2019 at 9:55 pm said:
I've got my Elliott ancestry back to 1765 (well a relative of my father has!): one John Elliott born that year who married one Dorothy Dawson, born 1768. I have not yet tried to go further back. I also have the reiver surnames Grahams, Turners and Charltons (the later on my Mother's side) in my ancestry.
Kyle Elliot on April 24, 2019 at 12:19 am said:
Alan, This is my Elliot family via an Autosomal, DNA match to a Hugh Elliott. Have you DNA tested?
Robert Forster on May 8, 2019 at 7:27 pm said:
Interesting. Is the Calendar if Border papers available for research. I'm related to the Forster's of Stonegarthside and I'm curious to find if the Ro Forster mentioned on the map was the first Forster there and whether he was related to the Forsters of Bamburgh.
adminaa on May 8, 2019 at 10:32 pm said:
Robert, there are two volumes for the Calendar of Border Papers. Volume 1 covers the years 1560-1594 and Volume 2 covers 1595-1603. You can find pdf copies of it on the internet (it's well out of copyright !). For example I can find volume 1 here – https://archive.org/details/cu31924091786057/page/n6 and volume 2 here – https://archive.org/details/borderpaperscale02grea/page/n6. They're indexed so you can find the specific names you're looking for easily. I think they're fascinating.
john redden on September 19, 2019 at 6:51 pm said:
My Surname Redden is often said to originate from Reddenburn near the borders of Scotland and England.I even found a farm named redden from there currently!!!,,,Is that a family name that can be traced to the Borders?
adminaa on September 19, 2019 at 10:49 pm said:
Yes John you can consider yourself as a Borderer now ! The bible for Scottish surnames is 'The Surnames of Scotland' compiled by George F.Black. He says it comes from Redden near Sprouston which itself is near the town of Kelso. This is now a farm with a number of cottages on it. Black says that the very first recorded bearer of the name was Henry de Reueden who witnessed a charter around 1170.
Redden is one mile from the English border (and I'm writing this no more than 7 miles from Redden now).
Angie Yelland on October 3, 2019 at 9:39 am said:
My ancestors are Thompsons, Milburns and Charlton.I have found information about Milburn and Charlton but I am stuck on the Thompsons.They are all from Northumberland so I am assuming they must be defended from Reivers
adminaa on October 8, 2019 at 8:42 pm said:
I'm not especially knowledgeable about Northumbrian Reivers but Thompson is definitely acknowledged as a reiver name in the Redesdale area. See https://englandsnortheast.co.uk/border-reivers/
Leave a Reply to Alan Elliott Cancel reply
Reiver Families of Liddesdale and Canonbie in 1630
Canonbie Militia List – 1802
Local Militia Lists
Migration and the Borders
Old maps for family history
Nicole Mullen on Old maps for family history
adminaa on Bondagers in Berwickshire and Roxburghshire
Jim sim on Bondagers in Berwickshire and Roxburghshire
Harold (Hal) Elliott (in Utah) on Reiver Families of Liddesdale and Canonbie in 1630
© 2020 - Relatively Scottish Proudly powered by WordPress Weaver II by WP Weaver

redpajama_set_name: RedPajamaCommonCrawl


Watch out for income when purchasing Centerset Bathroom Faucet By Oakbrook Collection. More often than not furnishings are wear transaction. If you require a certain piece, it will save you a ton of money by with patience awaiting the purchase price to be reduced. You could ask your favorite Centerset Bathroom Faucet By Oakbrook Collection store as soon as the piece will probably be marked at a lower price. If you need a new sofa, try out getting one particular with many completely covered cushions. These soft cushions stay longer and may be switched frequently. If at all possible, you should buy a sofa with easily removed covers so that you can effortlessly wash them. Detachable covers can also be replaced effortlessly in the event you are unable to clean a blemish Get Centerset Bathroom Faucet By Oakbrook Collection in the future during. Following this year, it is popular for merchants to obtain these items away their display room flooring. This can bring about some terrific product sales and savings.
Bar tables are not only specific furniture meant to be utilized in bars as the name suggests. If you are looking to give your kitchen area, diner of home a business-like look, then you need to buy the best club tables. The dinning tables are earning a constantly-increasing existence in individuals houses as they look for that distinctive company-like existence at home. Nevertheless, with a large number of bar furniture to select, from, obtaining the best deal could be a daunting task for most owners. For those seeking to transform the dining area into a lively modern bar, we have you covered with some of the best club tables on the market presently. This club desk is a breakfast established well suited for homes with little eating areas. It's a pretty compact table that will not take an excessive amount of space within the dining room. It functions caster wheels that allow for easy motion inside the house especially when cleaning. You also get some bar stools and decrease leaf providing you with good value for your money. Made of the natural Beachwood, this table is a superb purchase and arrives as a whole and square form.
Much like its namesake, the camelback sofa has a hump or maybe two that highlights the main outline of the sofa style. This can be a traditional design that was made popular in the 1700s by Chippendale and families who wanted aristocratic, formal Brentwood Widespread Bathroom Faucet often opted for this design. These days, this couch style lends a more official air to the space, particularly when padded inside a formal fabric. A far more informal textile choice would make it suitable for a family room that doesnt need a lot of formality. Either way, the camelback sofa has some elements that characterize the style. The legs are usually exposed, the sofa has no back cushions also it normally has square or folded arms.
If you are searching for some serious relaxation, this loveseats solid pillow back again and folded arms will deliverbut at a higher price tag. Every chair cushioning contains 30 person pocketed circles for spring and support, and resilience chair froth for an additional coating of plushness and durability. In addition, the froth soft cushions are topped with extremely soft, blended down feathers. For your extra comfort and ease, there are 3 standard jobs: sitting, a slight lie down with an elevated foot rest, and a complete lie down with an elevated foot rest. It does not harm this reclining loveseat appears lux, possibly. Its all-leather-based upholstery and ornamental nail mind trim provide a classic appear that can work with lots of house decorations designs, from traditional to country to crafts and arts. Plus, leather holds up well against everyday use, children and pet locks and fingernails. Just be sure you situation the leather every 6 to twelve months.
Even though this reclining loveseat has a heftier price tag, its traditional style, choices for customization and automatic lying program make it well worth the dough. Its hand made wooden body is padded with lower blend cushions for a softer feel than you would receive from high-density foam soft cushions, and the furniture is available in a whopping 72 color and fabric combos. The supply of a lot of choices makes it additional simple to pair this lying loveseat with various designs, supplies, accents and dcor designs. Plus, for those who have kids or animals (or each!), you can select a more durable, stain-proof material. One customer shared that the Sunbrella fabric material has held up nicely against her children and pets. This reclining loveseat may have a classic, old-college look, but its built-in tech is anything but. Not only does it come with an automated reclining program (that will give you a full lie down, with your foot rest totally similar towards the seat), but it features a USB port for implementing or just getting your iPad, iPhone, Amazon kindle or laptop computer.
If you are searching for some severe relaxation, this loveseats solid cushion back and rolled hands will deliverbut at a higher price tag. Each seat cushion contains 30 person pocketed coils for springtime and support, and high strength seat foam for an extra coating of plushness and sturdiness. Plus, the froth soft cushions are capped with super gentle, combined lower down. For the extra comfort and ease, you will find three standard jobs: seated, a small recline with an elevated footrest, along with a complete lie down with an elevated foot rest. It doesnt hurt that this lying loveseat looks lux, possibly. Its all-leather-based upholstery and decorative nail mind trim provide a classic appear that may work with lots of home decorations designs, from traditional to nation to crafts and arts. Plus, leather-based stands up nicely towards daily use, kids and pet locks and nails. Just remember to situation the leather each and every 6 to 12 months.
Puffy, overstuffed loveseat cushions arent your thing? This reclining loveseat from GDF has crisper, solution outlines than your traditional reclining loveseat, which makes it an elegant accessory for a mid-hundred years modern, contemporary, modern or contemporary style of home. And, at just 46.46 inches in width, its easy to match a smaller room, like flats, dens or office spaces. Available in a number of color and fabric choices, including grilling with charcoal material, navy blue fabric and slate micro-fiber, its easy to find the right complement for your house dcor, and also the sturdiness your loved ones requirements for everyday use. Gone are the days of good-searching, but uncomfortable Naples Widespread Bathroom Faucet with Drain Assembly you no longer need to sacrifice comfort and ease for style. This reclining loveseat functions an oversized, gentle, plush-stuffed seat cushioning with enough space for two or sufficient space for one to disseminate and unwind.
Whilst the back of this couch hints at the Chesterfield, with its rows of tufting, a tux couch has solution, more angular outlines. It is stated to possess been the bellwether of more contemporary styles in the 20's. Although some say this sofa style took its title from Tuxedo Recreation area in New York, it's also said to be named after the traditional extravagant men's match. You are able to determine a tux sofa by its hands that are the same height as the back again. The tufting on the rear of the couch and its rectangular silhouette will also be classic qualities. Cushions add comfort to this high-equipped design. Also, as the couch above from Upcountry is padded in leather, this well-liked style is often completed in textiles of all kinds, such as the very trendy purple velvet.
This luxurious group of urban-chic couches is created to supply an embellished site. Actually, even your modest areas may have you required to have an perfect film night. Lay him down to obtain a totally changed mattress. This auparavant-garde sleeper futon mattress is accessible in different shades. This incorporates some vibrant tones unmanageable for example Lemon, Mild Azure, and lightweight Crimson. Place them in your innovative research or loft to assess the exuberance. It is also available in lowering shades for example dark, darkish and darkish. These nuances, once more, print a respectable part of the higher course. With the breaking element of your back, you can relaxation to your favorite position. This sofa looks wealthy with tufted material texture furniture. The good thing is that it's personalized with hypoallergenic filling up. A conclusive result provides a comfy relaxation.
The term here is the comfort and complicated look. This established has a tufted back rest and toe nail head highlight that gives it the subtle look. Its grey color contributes to its impressive appear. It can match up to 8 inches bed mattress. That on your own lets you know how comfy the established can be. Particularly, it doesn't incorporate a mattress. So you may want to purchase one. The trundle features a castor to allow quick access. You may even draw the trundle that people take a seat on. Just to mention, it should take assembling, but again its super easy to put together.
Weighing below $300 (in addition delivery) and 56 inches in width, our pocket book- and room-pleasant pick is ideal for very first flats, playrooms, dens or other small areas. Because its upholstered with additional strong glued leather-based, this reclining loveseat is more resistant against stains, rips and holes. Clients explain this lying loveseat as comfortable, stylish and an excellent worth. 1 reviewer authored that it was probably the most comfortable furniture pieces she is ever endured, while another stated he could not have requested more for his money. Fair caution, though: some reviewers said the furniture on their loveseats took very easily. Thankfully, the maker has a warranty for parts. Because this loveseat has this type of simple design, it can make a good base for additional customized dcor products. Add some ornamental toss cushions or covers to up its comfortable element, and add a few jumps of colour and pattern.
Carolina Mild Grey Fabric Sofa Couch is well known for its stunning comfort and impressive style. It features a modular design that enables for several arrangement options to suit your needs.The established functions soft material and pushes soft cushions to bring about the desired comfort and ease. More to the point, its of the good dimension to support you together with the family of friends. Depending on the available space and your desired form, you are able to combine the I seats to produce an impressive form. Its highly recommended for those with small areas and needs a sofa.
Copyright © Centerset Bathroom Faucet By Oakbrook Collection in Bathroom Sink Faucets All right reserved.