Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4119c211 authored by Chaojing Sun's avatar Chaojing Sun Committed by Andre Eisenbach
Browse files

LE: Serialize multiple connection parameter update requests

Bluetooth controllers do not allow multiple connection parameter
updates where there is one outstanding. This requires serializing
all connection parameter update requests and send the latest
request when the pending one is finished.

Bug: 17979666
Change-Id: Ic49bd89a4ded28014d74b40e67f2a3ea490b9ef7
parent 726eca89
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ extern void hidd_pm_proc_mode_change( UINT8 hci_status, UINT8 mode, UINT16 inter
static void btu_ble_ll_conn_complete_evt (UINT8 *p, UINT16 evt_len);
static void btu_ble_process_adv_pkt (UINT8 *p);
static void btu_ble_read_remote_feat_evt (UINT8 *p);
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p);
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len);
static void btu_ble_proc_ltk_req (UINT8 *p);
static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p);
#if (BLE_LLT_INCLUDED == TRUE)
@@ -413,7 +413,7 @@ void btu_hcif_process_event (UINT8 controller_id, BT_HDR *p_msg)
                    btu_ble_ll_conn_complete_evt(p, hci_evt_len);
                    break;
                case HCI_BLE_LL_CONN_PARAM_UPD_EVT:
                    btu_ble_ll_conn_param_upd_evt(p);
                    btu_ble_ll_conn_param_upd_evt(p, hci_evt_len);
                    break;
                case HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT:
                    btu_ble_read_remote_feat_evt(p);
@@ -2276,9 +2276,17 @@ static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
    btm_ble_conn_complete(p, evt_len);
}

static void btu_ble_ll_conn_param_upd_evt (UINT8 *p)
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
{
    /* This is empty until an upper layer cares about returning event */
    /* LE connection update has completed successfully as a master. */
    /* We can enable the update request if the result is a success. */
    /* extract the HCI handle first */
    UINT8   status;
    UINT16  handle;

    STREAM_TO_UINT8  (status, p);
    STREAM_TO_UINT16 (handle, p);
    l2cble_process_conn_update_evt(handle, status);
}

static void btu_ble_read_remote_feat_evt (UINT8 *p)
+0 −4
Original line number Diff line number Diff line
@@ -420,10 +420,6 @@ BTU_API UINT32 btu_task (UINT32 param)
                    case BTU_TTYPE_L2CAP_HOLD:
                    case BTU_TTYPE_L2CAP_INFO:
                    case BTU_TTYPE_L2CAP_FCR_ACK:
#if (BLE_INCLUDED == TRUE)
                    case BTU_TTYPE_L2CAP_END_CONN_UPD:
#endif

                        l2c_process_timeout (p_tle);
                        break;

+3 −5
Original line number Diff line number Diff line
@@ -153,13 +153,11 @@ typedef void (*tBTU_EVENT_CALLBACK)(BT_HDR *p_hdr);
#define BTU_TTYPE_ATT_WAIT_FOR_APP_RSP              104
#define BTU_TTYPE_ATT_WAIT_FOR_IND_ACK              105

#define BTU_TTYPE_L2CAP_END_CONN_UPD                106
#define BTU_TTYPE_BLE_GAP_FAST_ADV                  106
#define BTU_TTYPE_BLE_OBSERVE                       107

#define BTU_TTYPE_BLE_GAP_FAST_ADV                  107
#define BTU_TTYPE_BLE_OBSERVE                       108


#define BTU_TTYPE_UCD_TO                            109
#define BTU_TTYPE_UCD_TO                            108



+112 −95
Original line number Diff line number Diff line
@@ -32,8 +32,7 @@
#include "hcimsgs.h"

#if (BLE_INCLUDED == TRUE)
#define L2CA_GET_UPD_ST(x)          ((x) & UPD_ST_MASK)
#define L2CA_SET_UPD_ST(x, y)      x = (((x) & ~UPD_ST_MASK) | (y))
static void l2cble_start_conn_update (tL2C_LCB *p_lcb);

#include "vendor_ble.h"
/*******************************************************************************
@@ -126,9 +125,13 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in
        if ((HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
         HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)))
        {
            /* TODO: CE length selection ?? */
            btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
            latency, timeout, 0, 0);
            p_lcb->min_interval = min_int;
            p_lcb->max_interval = max_int;
            p_lcb->latency = latency;
            p_lcb->timeout = timeout;
            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;

            l2cble_start_conn_update(p_lcb);
        }
        else
        /* if either side does not support Connection Parameters Request
@@ -137,8 +140,15 @@ BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_in
#endif
        {
            if (p_lcb->link_role == HCI_ROLE_MASTER)
                btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
                latency, timeout, 0, 0);
        {
            p_lcb->min_interval = min_int;
            p_lcb->max_interval = max_int;
            p_lcb->latency = latency;
            p_lcb->timeout = timeout;
            p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;

            l2cble_start_conn_update(p_lcb);
        }
            else
                l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
        }
@@ -186,43 +196,13 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
    }

    if (enable)
    {
        if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) == UPD_DISABLED)
        {
            p_lcb->conn_param_enb.param = (TIMER_PARAM_TYPE)p_lcb;
            btu_start_timer (&p_lcb->conn_param_enb, BTU_TTYPE_L2CAP_END_CONN_UPD,
                                                    L2CAP_BLE_ENB_CONN_PARAM_TOUT);
            L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENB_TOUT);
        }
    }
    else if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) != UPD_DISABLED)
    {
        btu_stop_timer(&p_lcb->conn_param_enb);

        if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
        {

            /*
            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 & UPD_REQUEST) != 0)
            {
                /* revert back to default */
                btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
                                                   BTM_BLE_CONN_INT_MIN_DEF,
                                                   BTM_BLE_CONN_INT_MAX_DEF,
                                                   BTM_BLE_CONN_SLAVE_LATENCY_DEF,
                                                   BTM_BLE_CONN_TIMEOUT_DEF,
                                                   0, 0);
            }
        }
        L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_DISABLED);
        p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
    else
        p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;

    }
    l2cble_start_conn_update(p_lcb);

    return (TRUE);

}


@@ -478,6 +458,93 @@ void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE typ
        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:   none
**
*******************************************************************************/
static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
{
    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);

    if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;

    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)
        {
            btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle,
                (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)((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)((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)((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
                         p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
                0, 0);
            p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
            p_lcb->conn_update_mask |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NEW_CONN_PARAM);
        }
    }
    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)
        {
            btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
                p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
            p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
            p_lcb->conn_update_mask |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NOT_DEFAULT_PARAM);
        }
    }
}

/*******************************************************************************
**
** 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)
{
    tL2C_LCB *p_lcb;

    L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt");

    /* 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("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
        return;
    }

    p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;

    if (status != HCI_SUCCESS)
    {
        L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
    }

    l2cble_start_conn_update(p_lcb);

    L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
}
/*******************************************************************************
**
** Function         l2cble_process_sig_cmd
@@ -547,18 +614,9 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
                     p_lcb->max_interval = max_interval;
                     p_lcb->latency = latency;
                     p_lcb->timeout = timeout;
                     p_lcb->conn_update_mask |= UPD_REQUEST;

                     if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
                     {
                         btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_interval, max_interval,
                                                             latency, timeout, 0, 0);
                     }
                     else
                     {
                         L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
                     }
                     p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;

                     l2cble_start_conn_update(p_lcb);
                }
            }
            else
@@ -575,47 +633,7 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
            return;
    }
}
/*******************************************************************************
**
** Function         l2c_enable_conn_param_timeout
**
** Description      This function process the connection parameter enabling timeout
**
** Returns          None.
**
*******************************************************************************/
void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb)
{
    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);


    /* application allows to do update, if we were delaying one do it now, otherwise
    just mark lcb that updates are enabled */
    if (p_lcb->conn_update_mask & UPD_REQUEST)
    {
        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, p_lcb->min_interval, p_lcb->max_interval,
                                           p_lcb->latency, p_lcb->timeout, 0, 0);
    }
    else
    {
        /* if preferred number has been set, set to preferred conn parameter */
        if (p_dev_rec && p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF)
        {
            btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
                (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)((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)((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) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
                p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
                0, 0);
        }
    }
    L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENABLED);

}
/*******************************************************************************
**
** Function         l2cble_init_direct_conn
@@ -902,10 +920,9 @@ void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 i
        p_lcb->max_interval = int_max;
        p_lcb->latency = latency;
        p_lcb->timeout = timeout;
        p_lcb->conn_update_mask |= UPD_REQUEST;

        /* TODO: revisit: if update is enabled, always accept connection parameter update */
        if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
        /* if update is enabled, always accept connection parameter update */
        if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0)
        {
            btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
        }
+6 −8
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@
#define L2CAP_LINK_INFO_RESP_TOUT    2            /* 2  seconds */
#define L2CAP_BLE_LINK_CONNECT_TOUT  30           /* 30 seconds */
#define L2CAP_BLE_CONN_PARAM_UPD_TOUT   30           /* 30 seconds */
#define L2CAP_BLE_ENB_CONN_PARAM_TOUT   1           /* 1 seconds */

/* quick timer uses millisecond unit */
#define L2CAP_DEFAULT_RETRANS_TOUT   2000         /* 2000 milliseconds */
@@ -437,14 +436,13 @@ typedef struct t_l2c_linkcb
    tBT_TRANSPORT       transport;
#if (BLE_INCLUDED == TRUE)
    tBLE_ADDR_TYPE      ble_addr_type;
    TIMER_LIST_ENT      conn_param_enb;         /* Timer entry for enabling connection parameter update */

#define UPD_ENABLED     0  /* If peer requests update, we will change params */
#define UPD_DISABLED    1  /* application requested not to update */
#define UPD_ENB_TOUT    2  /* while updates are disabled, peer requested new parameters */
#define UPD_ST_MASK     0x0f
#define UPD_REQUEST     0x10  /* remote device set preferred conn param */
#define L2C_BLE_CONN_UPDATE_DISABLE 0x1  /* disable update connection parameters */
#define L2C_BLE_NEW_CONN_PARAM      0x2  /* new connection parameter to be set */
#define L2C_BLE_UPDATE_PENDING      0x4  /* waiting for connection update finished */
#define L2C_BLE_NOT_DEFAULT_PARAM   0x8  /* not using default connection parameters */
    UINT8               conn_update_mask;

    UINT16              min_interval; /* parameters as requested by peripheral */
    UINT16              max_interval;
    UINT16              latency;
@@ -771,9 +769,9 @@ extern void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
extern void l2cble_conn_comp (UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
                              UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout);
extern BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb);
extern void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb);
extern void l2cble_notify_le_connection (BD_ADDR bda);
extern void l2c_ble_link_adjust_allocation (void);
extern void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status);

#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
extern void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
Loading