Bluetooth: controller: Support big-endian archs in split controller.

Use reverse order for bitfields on big-endian architectures. Treat
all PDU data as little-endian and add conversions as needed. Treat
access address as 4-byte value instead of u32_t to avoid flipping
endianness.

Signed-off-by: Wolfgang Puffitsch <wopu@oticon.com>
This commit is contained in:
Wolfgang Puffitsch 2019-02-07 10:08:31 +01:00 committed by Carles Cufí
parent ebc4e83a20
commit d7fac9bf8c
7 changed files with 300 additions and 156 deletions

View file

@ -1806,13 +1806,13 @@ static void vs_read_version_info(struct net_buf *buf, struct net_buf **evt)
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
rp->hw_platform = BT_HCI_VS_HW_PLAT;
rp->hw_variant = BT_HCI_VS_HW_VAR;
rp->hw_platform = sys_cpu_to_le16(BT_HCI_VS_HW_PLAT);
rp->hw_variant = sys_cpu_to_le16(BT_HCI_VS_HW_VAR);
rp->fw_variant = 0;
rp->fw_version = (KERNEL_VERSION_MAJOR & 0xff);
rp->fw_revision = KERNEL_VERSION_MINOR;
rp->fw_build = (KERNEL_PATCHLEVEL & 0xffff);
rp->fw_revision = sys_cpu_to_le16(KERNEL_VERSION_MINOR);
rp->fw_build = sys_cpu_to_le32(KERNEL_PATCHLEVEL & 0xffff);
}
static void vs_read_supported_commands(struct net_buf *buf,
@ -3142,8 +3142,8 @@ static void remote_version_info(struct pdu_data *pdu_data, u16_t handle,
ep->status = 0x00;
ep->handle = sys_cpu_to_le16(handle);
ep->version = ver_ind->version_number;
ep->manufacturer = sys_cpu_to_le16(ver_ind->company_id);
ep->subversion = sys_cpu_to_le16(ver_ind->sub_version_number);
ep->manufacturer = ver_ind->company_id;
ep->subversion = ver_ind->sub_version_number;
}
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)

View file

@ -8,6 +8,7 @@
#include <stddef.h>
#include <zephyr/types.h>
#include <misc/byteorder.h>
#include <toolchain.h>
#include <bluetooth/hci.h>
@ -116,7 +117,7 @@ static int init_reset(void)
static int prepare_cb(struct lll_prepare_param *prepare_param)
{
struct lll_adv *lll = prepare_param->param;
u32_t aa = 0x8e89bed6;
u32_t aa = sys_cpu_to_le32(0x8e89bed6);
u32_t ticks_at_event;
struct evt_hdr *evt;
u32_t remainder_us;

View file

@ -7,6 +7,7 @@
#include <zephyr/types.h>
#include <toolchain.h>
#include <bluetooth/hci.h>
#include <misc/byteorder.h>
#include "hal/ccm.h"
#include "hal/radio.h"
@ -117,7 +118,7 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
{
struct lll_scan *lll = prepare_param->param;
struct node_rx_pdu *node_rx;
u32_t aa = 0x8e89bed6;
u32_t aa = sys_cpu_to_le32(0x8e89bed6);
u32_t ticks_at_event;
struct evt_hdr *evt;
u32_t remainder_us;
@ -702,7 +703,7 @@ static inline u32_t isr_rx_pdu(struct lll_scan *lll, u8_t devmatch_ok,
if (!IS_ENABLED(CONFIG_BT_CTLR_SCHED_ADVANCED) ||
lll->conn_win_offset_us == 0) {
conn_space_us = conn_offset_us;
pdu_tx->connect_ind.win_offset = 0;
pdu_tx->connect_ind.win_offset = sys_cpu_to_le16(0);
} else {
conn_space_us = lll->conn_win_offset_us;
while ((conn_space_us & ((u32_t)1 << 31)) ||
@ -710,13 +711,17 @@ static inline u32_t isr_rx_pdu(struct lll_scan *lll, u8_t devmatch_ok,
conn_space_us += conn_interval_us;
}
pdu_tx->connect_ind.win_offset =
(conn_space_us - conn_offset_us) / 1250;
sys_cpu_to_le16((conn_space_us -
conn_offset_us) / 1250);
pdu_tx->connect_ind.win_size++;
}
pdu_tx->connect_ind.interval = lll_conn->interval;
pdu_tx->connect_ind.latency = lll_conn->latency;
pdu_tx->connect_ind.timeout = lll->conn_timeout;
pdu_tx->connect_ind.interval =
sys_cpu_to_le16(lll_conn->interval);
pdu_tx->connect_ind.latency =
sys_cpu_to_le16(lll_conn->latency);
pdu_tx->connect_ind.timeout =
sys_cpu_to_le16(lll->conn_timeout);
memcpy(&pdu_tx->connect_ind.chan_map[0],
&lll_conn->data_chan_map[0],
sizeof(pdu_tx->connect_ind.chan_map));

View file

@ -82,15 +82,30 @@ struct pdu_adv_connect_ind {
u16_t latency;
u16_t timeout;
u8_t chan_map[5];
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t hop:5;
u8_t sca:3;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t sca:3;
u8_t hop:5;
#else
#error "Unsupported endianness"
#endif
} __packed;
} __packed;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct pdu_adv_com_ext_adv {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t ext_hdr_len:6;
u8_t adv_mode:2;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t adv_mode:2;
u8_t ext_hdr_len:6;
#else
#error "Unsupported endianness"
#endif
u8_t ext_hdr_adi_adv_data[254];
} __packed;
@ -101,6 +116,7 @@ enum ext_adv_mode {
};
struct ext_adv_hdr {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t adv_addr:1;
u8_t tgt_addr:1;
u8_t rfu0:1;
@ -109,19 +125,48 @@ struct ext_adv_hdr {
u8_t sync_info:1;
u8_t tx_pwr:1;
u8_t rfu1:1;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t rfu1:1;
u8_t tx_pwr:1;
u8_t sync_info:1;
u8_t aux_ptr:1;
u8_t adi:1;
u8_t rfu0:1;
u8_t tgt_addr:1;
u8_t adv_addr:1;
#else
#error "Unsupported endianness"
#endif
} __packed;
struct ext_adv_adi {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u16_t did:12;
u16_t sid:4;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u16_t sid:4;
u16_t did:12;
#else
#error "Unsupported endianness"
#endif
} __packed;
struct ext_adv_aux_ptr {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t chan_idx:6;
u8_t ca:1;
u8_t offs_units:1;
u16_t offs:13;
u16_t phy:3;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t offs_units:1;
u8_t ca:1;
u8_t chan_idx:6;
u16_t phy:3;
u16_t offs:13;
#else
#error "Unsupported endianness"
#endif
} __packed;
enum ext_adv_aux_ptr_ca {
@ -141,9 +186,17 @@ enum ext_adv_aux_phy {
};
struct ext_adv_sync_info {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u16_t sync_pkt_offs:13;
u16_t offs_units:1;
u16_t rfu:2;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u16_t rfu:2;
u16_t offs_units:1;
u16_t sync_pkt_offs:13;
#else
#error "Unsupported endianness"
#endif
u16_t interval;
u8_t sca_chm[5];
u32_t aa;
@ -171,13 +224,23 @@ enum pdu_adv_type {
} __packed;
struct pdu_adv {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t type:4;
u8_t rfu:1;
u8_t chan_sel:1;
u8_t tx_addr:1;
u8_t rx_addr:1;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t rx_addr:1;
u8_t tx_addr:1;
u8_t chan_sel:1;
u8_t rfu:1;
u8_t type:4;
#else
#error "Unsupported endianness"
#endif
u8_t len:8;
u8_t len;
union {
u8_t payload[0];
@ -423,13 +486,23 @@ struct profile {
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
struct pdu_data {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
u8_t ll_id:2;
u8_t nesn:1;
u8_t sn:1;
u8_t md:1;
u8_t rfu:3;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
u8_t rfu:3;
u8_t md:1;
u8_t sn:1;
u8_t nesn:1;
u8_t ll_id:2;
#else
#error "Unsupported endianness"
#endif
u8_t len:8;
u8_t len;
#if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
u8_t resv:8; /* TODO: remove nRF specific code */

View file

@ -9,6 +9,7 @@
#include <device.h>
#include <entropy.h>
#include <bluetooth/bluetooth.h>
#include <misc/byteorder.h>
#include "hal/ecb.h"
#include "hal/ccm.h"
@ -1433,15 +1434,15 @@ static inline void event_conn_upd_init(struct ll_conn *conn,
pdu_ctrl_tx->llctrl.conn_update_ind.win_size =
conn->llcp.conn_upd.win_size;
pdu_ctrl_tx->llctrl.conn_update_ind.win_offset =
conn->llcp.conn_upd.win_offset_us / 1250;
sys_cpu_to_le16(conn->llcp.conn_upd.win_offset_us / 1250);
pdu_ctrl_tx->llctrl.conn_update_ind.interval =
conn->llcp.conn_upd.interval;
sys_cpu_to_le16(conn->llcp.conn_upd.interval);
pdu_ctrl_tx->llctrl.conn_update_ind.latency =
conn->llcp.conn_upd.latency;
sys_cpu_to_le16(conn->llcp.conn_upd.latency);
pdu_ctrl_tx->llctrl.conn_update_ind.timeout =
conn->llcp.conn_upd.timeout;
sys_cpu_to_le16(conn->llcp.conn_upd.timeout);
pdu_ctrl_tx->llctrl.conn_update_ind.instant =
conn->llcp.conn_upd.instant;
sys_cpu_to_le16(conn->llcp.conn_upd.instant);
#if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
{
@ -1797,7 +1798,7 @@ static inline void event_ch_map_prep(struct ll_conn *conn,
&conn->llcp.chan_map.chm[0],
sizeof(pdu_ctrl_tx->llctrl.chan_map_ind.chm));
pdu_ctrl_tx->llctrl.chan_map_ind.instant =
conn->llcp.chan_map.instant;
sys_cpu_to_le16(conn->llcp.chan_map.instant);
ctrl_tx_enqueue(conn, tx);
}
@ -2040,6 +2041,8 @@ static inline void event_vex_prep(struct ll_conn *conn)
tx = mem_acquire(&mem_conn_tx_ctrl.free);
if (tx) {
struct pdu_data *pdu = (void *)tx->pdu;
u16_t cid;
u16_t svn;
/* procedure request acked */
conn->llcp_ack = conn->llcp_req;
@ -2056,10 +2059,10 @@ static inline void event_vex_prep(struct ll_conn *conn)
PDU_DATA_LLCTRL_TYPE_VERSION_IND;
pdu->llctrl.version_ind.version_number =
LL_VERSION_NUMBER;
pdu->llctrl.version_ind.company_id =
CONFIG_BT_CTLR_COMPANY_ID;
pdu->llctrl.version_ind.sub_version_number =
CONFIG_BT_CTLR_SUBVERSION_NUMBER;
cid = sys_cpu_to_le16(CONFIG_BT_CTLR_COMPANY_ID);
svn = sys_cpu_to_le16(CONFIG_BT_CTLR_SUBVERSION_NUMBER);
pdu->llctrl.version_ind.company_id = cid;
pdu->llctrl.version_ind.sub_version_number = svn;
ctrl_tx_enqueue(conn, tx);
@ -2093,9 +2096,9 @@ static inline void event_vex_prep(struct ll_conn *conn)
pdu->llctrl.version_ind.version_number =
conn->llcp_version.version_number;
pdu->llctrl.version_ind.company_id =
conn->llcp_version.company_id;
sys_cpu_to_le16(conn->llcp_version.company_id);
pdu->llctrl.version_ind.sub_version_number =
conn->llcp_version.sub_version_number;
sys_cpu_to_le16(conn->llcp_version.sub_version_number);
/* enqueue version ind structure into rx queue */
ll_rx_put(rx->hdr.link, rx);
@ -2130,18 +2133,18 @@ static inline void event_conn_param_req(struct ll_conn *conn,
sizeof(struct pdu_data_llctrl_conn_param_req);
pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
p = (void *)&pdu_ctrl_tx->llctrl.conn_param_req;
p->interval_min = conn->llcp_conn_param.interval_min;
p->interval_max = conn->llcp_conn_param.interval_max;
p->latency = conn->llcp_conn_param.latency;
p->timeout = conn->llcp_conn_param.timeout;
p->interval_min = sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
p->interval_max = sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
p->latency = sys_cpu_to_le16(conn->llcp_conn_param.latency);
p->timeout = sys_cpu_to_le16(conn->llcp_conn_param.timeout);
p->preferred_periodicity = 0;
p->reference_conn_event_count = event_counter;
p->offset0 = 0x0000;
p->offset1 = 0xffff;
p->offset2 = 0xffff;
p->offset3 = 0xffff;
p->offset4 = 0xffff;
p->offset5 = 0xffff;
p->reference_conn_event_count = sys_cpu_to_le16(event_counter);
p->offset0 = sys_cpu_to_le16(0x0000);
p->offset1 = sys_cpu_to_le16(0xffff);
p->offset2 = sys_cpu_to_le16(0xffff);
p->offset3 = sys_cpu_to_le16(0xffff);
p->offset4 = sys_cpu_to_le16(0xffff);
p->offset5 = sys_cpu_to_le16(0xffff);
ctrl_tx_enqueue(conn, tx);
@ -2271,20 +2274,24 @@ static inline void event_conn_param_rsp(struct ll_conn *conn)
sizeof(struct pdu_data_llctrl_conn_param_rsp);
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP;
rsp = (void *)&pdu->llctrl.conn_param_rsp;
rsp->interval_min = conn->llcp_conn_param.interval_min;
rsp->interval_max = conn->llcp_conn_param.interval_max;
rsp->latency = conn->llcp_conn_param.latency;
rsp->timeout = conn->llcp_conn_param.timeout;
rsp->interval_min =
sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
rsp->interval_max =
sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
rsp->latency =
sys_cpu_to_le16(conn->llcp_conn_param.latency);
rsp->timeout =
sys_cpu_to_le16(conn->llcp_conn_param.timeout);
rsp->preferred_periodicity =
conn->llcp_conn_param.preferred_periodicity;
rsp->reference_conn_event_count =
conn->llcp_conn_param.reference_conn_event_count;
rsp->offset0 = conn->llcp_conn_param.offset0;
rsp->offset1 = conn->llcp_conn_param.offset1;
rsp->offset2 = conn->llcp_conn_param.offset2;
rsp->offset3 = conn->llcp_conn_param.offset3;
rsp->offset4 = conn->llcp_conn_param.offset4;
rsp->offset5 = conn->llcp_conn_param.offset5;
sys_cpu_to_le16(conn->llcp_conn_param.reference_conn_event_count);
rsp->offset0 = sys_cpu_to_le16(conn->llcp_conn_param.offset0);
rsp->offset1 = sys_cpu_to_le16(conn->llcp_conn_param.offset1);
rsp->offset2 = sys_cpu_to_le16(conn->llcp_conn_param.offset2);
rsp->offset3 = sys_cpu_to_le16(conn->llcp_conn_param.offset3);
rsp->offset4 = sys_cpu_to_le16(conn->llcp_conn_param.offset4);
rsp->offset5 = sys_cpu_to_le16(conn->llcp_conn_param.offset5);
ctrl_tx_enqueue(conn, tx);
@ -2328,10 +2335,10 @@ static inline void event_conn_param_app_req(struct ll_conn *conn)
sizeof(struct pdu_data_llctrl_conn_param_req);
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ;
p = (void *) &pdu->llctrl.conn_param_req;
p->interval_min = conn->llcp_conn_param.interval_min;
p->interval_max = conn->llcp_conn_param.interval_max;
p->latency = conn->llcp_conn_param.latency;
p->timeout = conn->llcp_conn_param.timeout;
p->interval_min = sys_cpu_to_le16(conn->llcp_conn_param.interval_min);
p->interval_max = sys_cpu_to_le16(conn->llcp_conn_param.interval_max);
p->latency = sys_cpu_to_le16(conn->llcp_conn_param.latency);
p->timeout = sys_cpu_to_le16(conn->llcp_conn_param.timeout);
/* enqueue connection parameter request into rx queue */
ll_rx_put(rx->hdr.link, rx);
@ -2812,7 +2819,7 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
ind = &pdu_ctrl_tx->llctrl.phy_upd_ind;
ind->m_to_s_phy = conn->llcp.phy_upd_ind.tx;
ind->s_to_m_phy = conn->llcp.phy_upd_ind.rx;
ind->instant = conn->llcp.phy_upd_ind.instant;
ind->instant = sys_cpu_to_le16(conn->llcp.phy_upd_ind.instant);
ctrl_tx_enqueue(conn, tx);
} else if (((event_counter - conn->llcp.phy_upd_ind.instant) & 0xFFFF)
@ -2866,8 +2873,10 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
static u8_t conn_upd_recv(struct ll_conn *conn, memq_link_t *link,
struct node_rx_pdu **rx, struct pdu_data *pdu)
{
if (((pdu->llctrl.conn_update_ind.instant - conn->lll.event_counter) &
0xFFFF) > 0x7FFF) {
u16_t instant;
instant = sys_le16_to_cpu(pdu->llctrl.conn_update_ind.instant);
if (((instant - conn->lll.event_counter) & 0xFFFF) > 0x7FFF) {
/* Mark for buffer for release */
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
@ -2893,11 +2902,14 @@ static u8_t conn_upd_recv(struct ll_conn *conn, memq_link_t *link,
conn->llcp.conn_upd.win_size = pdu->llctrl.conn_update_ind.win_size;
conn->llcp.conn_upd.win_offset_us =
pdu->llctrl.conn_update_ind.win_offset * 1250;
conn->llcp.conn_upd.interval = pdu->llctrl.conn_update_ind.interval;
conn->llcp.conn_upd.latency = pdu->llctrl.conn_update_ind.latency;
conn->llcp.conn_upd.timeout = pdu->llctrl.conn_update_ind.timeout;
conn->llcp.conn_upd.instant = pdu->llctrl.conn_update_ind.instant;
sys_le16_to_cpu(pdu->llctrl.conn_update_ind.win_offset) * 1250;
conn->llcp.conn_upd.interval =
sys_le16_to_cpu(pdu->llctrl.conn_update_ind.interval);
conn->llcp.conn_upd.latency =
sys_le16_to_cpu(pdu->llctrl.conn_update_ind.latency);
conn->llcp.conn_upd.timeout =
sys_le16_to_cpu(pdu->llctrl.conn_update_ind.timeout);
conn->llcp.conn_upd.instant = instant;
conn->llcp.conn_upd.state = LLCP_CUI_STATE_INPROG;
conn->llcp.conn_upd.is_internal = 0;
@ -2924,9 +2936,10 @@ static u8_t chan_map_upd_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
struct pdu_data *pdu)
{
u8_t err = 0;
u16_t instant;
if (((pdu->llctrl.chan_map_ind.instant - conn->lll.event_counter) &
0xffff) > 0x7fff) {
instant = sys_le16_to_cpu(pdu->llctrl.chan_map_ind.instant);
if (((instant - conn->lll.event_counter) & 0xffff) > 0x7fff) {
err = BT_HCI_ERR_INSTANT_PASSED;
goto chan_map_upd_recv_exit;
@ -2942,7 +2955,7 @@ static u8_t chan_map_upd_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
memcpy(&conn->llcp.chan_map.chm[0], &pdu->llctrl.chan_map_ind.chm[0],
sizeof(conn->llcp.chan_map.chm));
conn->llcp.chan_map.instant = pdu->llctrl.chan_map_ind.instant;
conn->llcp.chan_map.instant = instant;
conn->llcp.chan_map.initiate = 0;
conn->llcp_type = LLCP_CHAN_MAP;
@ -3309,8 +3322,9 @@ static int version_ind_send(struct ll_conn *conn, struct node_rx_pdu *rx,
pdu_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_VERSION_IND;
v = &pdu_tx->llctrl.version_ind;
v->version_number = LL_VERSION_NUMBER;
v->company_id = CONFIG_BT_CTLR_COMPANY_ID;
v->sub_version_number = CONFIG_BT_CTLR_SUBVERSION_NUMBER;
v->company_id = sys_cpu_to_le16(CONFIG_BT_CTLR_COMPANY_ID);
v->sub_version_number =
sys_cpu_to_le16(CONFIG_BT_CTLR_SUBVERSION_NUMBER);
ctrl_tx_sec_enqueue(conn, tx);
@ -3330,8 +3344,9 @@ static int version_ind_send(struct ll_conn *conn, struct node_rx_pdu *rx,
v = &pdu_rx->llctrl.version_ind;
conn->llcp_version.version_number = v->version_number;
conn->llcp_version.company_id = v->company_id;
conn->llcp_version.sub_version_number = v->sub_version_number;
conn->llcp_version.company_id = sys_le16_to_cpu(v->company_id);
conn->llcp_version.sub_version_number =
sys_le16_to_cpu(v->sub_version_number);
conn->llcp_version.rx = 1;
return 0;
@ -3639,6 +3654,7 @@ static inline u8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link,
struct pdu_data *pdu_rx)
{
struct pdu_data_llctrl_phy_upd_ind *ind = &pdu_rx->llctrl.phy_upd_ind;
u16_t instant;
/* Both tx and rx PHY unchanged */
if (!((ind->m_to_s_phy | ind->s_to_m_phy) & 0x07)) {
@ -3677,7 +3693,8 @@ static inline u8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link,
}
/* instant passed */
if (((ind->instant - conn->lll.event_counter) & 0xffff) > 0x7fff) {
instant = sys_le16_to_cpu(ind->instant);
if (((instant - conn->lll.event_counter) & 0xffff) > 0x7fff) {
/* Mark for buffer for release */
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
@ -3703,7 +3720,7 @@ static inline u8_t phy_upd_ind_recv(struct ll_conn *conn, memq_link_t *link,
conn->llcp.phy_upd_ind.tx = ind->s_to_m_phy;
conn->llcp.phy_upd_ind.rx = ind->m_to_s_phy;
conn->llcp.phy_upd_ind.instant = ind->instant;
conn->llcp.phy_upd_ind.instant = instant;
conn->llcp.phy_upd_ind.initiate = 0;
LL_ASSERT(!conn->llcp_rx);
@ -4240,18 +4257,28 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
&pdu_rx->llctrl.conn_param_req;
struct lll_conn *lll = &conn->lll;
/* Extract parameters */
u16_t interval_min =
sys_le16_to_cpu(cpr->interval_min);
u16_t interval_max =
sys_le16_to_cpu(cpr->interval_max);
u16_t latency =
sys_le16_to_cpu(cpr->latency);
u16_t timeout =
sys_le16_to_cpu(cpr->timeout);
u16_t preferred_periodicity =
cpr->preferred_periodicity;
/* Invalid parameters */
if ((cpr->interval_min < 6) ||
(cpr->interval_max > 3200) ||
(cpr->interval_min > cpr->interval_max) ||
(cpr->latency > 499) ||
(cpr->timeout < 10) ||
(cpr->timeout > 3200) ||
((cpr->timeout * 4) <=
((cpr->latency + 1) *
cpr->interval_max)) ||
(cpr->preferred_periodicity >
cpr->interval_max)) {
if ((interval_min < 6) ||
(interval_max > 3200) ||
(interval_min > interval_max) ||
(latency > 499) ||
(timeout < 10) ||
(timeout > 3200) ||
((timeout * 4) <=
((latency + 1) * interval_max)) ||
(preferred_periodicity > interval_max)) {
nack = reject_ext_ind_send(conn, *rx,
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
BT_HCI_ERR_INVALID_LL_PARAM);
@ -4261,21 +4288,27 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
/* save parameters to be used to select offset
*/
conn->llcp_conn_param.interval_min =
cpr->interval_min;
interval_min;
conn->llcp_conn_param.interval_max =
cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
interval_max;
conn->llcp_conn_param.latency = latency;
conn->llcp_conn_param.timeout = timeout;
conn->llcp_conn_param.preferred_periodicity =
cpr->preferred_periodicity;
preferred_periodicity;
conn->llcp_conn_param.reference_conn_event_count =
cpr->reference_conn_event_count;
conn->llcp_conn_param.offset0 = cpr->offset0;
conn->llcp_conn_param.offset1 = cpr->offset1;
conn->llcp_conn_param.offset2 = cpr->offset2;
conn->llcp_conn_param.offset3 = cpr->offset3;
conn->llcp_conn_param.offset4 = cpr->offset4;
conn->llcp_conn_param.offset5 = cpr->offset5;
sys_le16_to_cpu(cpr->reference_conn_event_count);
conn->llcp_conn_param.offset0 =
sys_le16_to_cpu(cpr->offset0);
conn->llcp_conn_param.offset1 =
sys_le16_to_cpu(cpr->offset1);
conn->llcp_conn_param.offset2 =
sys_le16_to_cpu(cpr->offset2);
conn->llcp_conn_param.offset3 =
sys_le16_to_cpu(cpr->offset3);
conn->llcp_conn_param.offset4 =
sys_le16_to_cpu(cpr->offset4);
conn->llcp_conn_param.offset5 =
sys_le16_to_cpu(cpr->offset5);
/* enqueue the conn param req, if parameters
* changed, else respond.
@ -4333,15 +4366,23 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
&pdu_rx->llctrl.conn_param_req;
struct lll_conn *lll = &conn->lll;
/* Extract parameters */
u16_t interval_min = sys_le16_to_cpu(cpr->interval_min);
u16_t interval_max = sys_le16_to_cpu(cpr->interval_max);
u16_t latency = sys_le16_to_cpu(cpr->latency);
u16_t timeout = sys_le16_to_cpu(cpr->timeout);
u16_t preferred_periodicity =
cpr->preferred_periodicity;
/* Invalid parameters */
if ((cpr->interval_min < 6) ||
(cpr->interval_max > 3200) ||
(cpr->interval_min > cpr->interval_max) ||
(cpr->latency > 499) ||
(cpr->timeout < 10) || (cpr->timeout > 3200) ||
((cpr->timeout * 4) <= ((cpr->latency + 1) *
cpr->interval_max)) ||
(cpr->preferred_periodicity > cpr->interval_max)) {
if ((interval_min < 6) ||
(interval_max > 3200) ||
(interval_min > interval_max) ||
(latency > 499) ||
(timeout < 10) || (timeout > 3200) ||
((timeout * 4) <=
((latency + 1) * interval_max)) ||
(preferred_periodicity > interval_max)) {
nack = reject_ext_ind_send(conn, *rx,
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ,
BT_HCI_ERR_INVALID_LL_PARAM);
@ -4351,20 +4392,26 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
/* resp to be generated by app, for now save
* parameters
*/
conn->llcp_conn_param.interval_min = cpr->interval_min;
conn->llcp_conn_param.interval_max = cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
conn->llcp_conn_param.interval_min = interval_min;
conn->llcp_conn_param.interval_max = interval_max;
conn->llcp_conn_param.latency = latency;
conn->llcp_conn_param.timeout = timeout;
conn->llcp_conn_param.preferred_periodicity =
cpr->preferred_periodicity;
preferred_periodicity;
conn->llcp_conn_param.reference_conn_event_count =
cpr->reference_conn_event_count;
conn->llcp_conn_param.offset0 = cpr->offset0;
conn->llcp_conn_param.offset1 = cpr->offset1;
conn->llcp_conn_param.offset2 = cpr->offset2;
conn->llcp_conn_param.offset3 = cpr->offset3;
conn->llcp_conn_param.offset4 = cpr->offset4;
conn->llcp_conn_param.offset5 = cpr->offset5;
sys_le16_to_cpu(cpr->reference_conn_event_count);
conn->llcp_conn_param.offset0 =
sys_le16_to_cpu(cpr->offset0);
conn->llcp_conn_param.offset1 =
sys_le16_to_cpu(cpr->offset1);
conn->llcp_conn_param.offset2 =
sys_le16_to_cpu(cpr->offset2);
conn->llcp_conn_param.offset3 =
sys_le16_to_cpu(cpr->offset3);
conn->llcp_conn_param.offset4 =
sys_le16_to_cpu(cpr->offset4);
conn->llcp_conn_param.offset5 =
sys_le16_to_cpu(cpr->offset5);
/* enqueue the conn param req, if parameters changed,
* else respond
@ -4415,15 +4462,23 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
struct pdu_data_llctrl_conn_param_req *cpr = (void *)
&pdu_rx->llctrl.conn_param_req;
/* Extract parameters */
u16_t interval_min = sys_le16_to_cpu(cpr->interval_min);
u16_t interval_max = sys_le16_to_cpu(cpr->interval_max);
u16_t latency = sys_le16_to_cpu(cpr->latency);
u16_t timeout = sys_le16_to_cpu(cpr->timeout);
u16_t preferred_periodicity =
cpr->preferred_periodicity;
/* Invalid parameters */
if ((cpr->interval_min < 6) ||
(cpr->interval_max > 3200) ||
(cpr->interval_min > cpr->interval_max) ||
(cpr->latency > 499) ||
(cpr->timeout < 10) || (cpr->timeout > 3200) ||
((cpr->timeout * 4) <= ((cpr->latency + 1) *
cpr->interval_max)) ||
(cpr->preferred_periodicity > cpr->interval_max)) {
if ((interval_min < 6) ||
(interval_max > 3200) ||
(interval_min > interval_max) ||
(latency > 499) ||
(timeout < 10) || (timeout > 3200) ||
((timeout * 4) <=
((latency + 1) * interval_max)) ||
(preferred_periodicity > interval_max)) {
nack = reject_ext_ind_send(conn, *rx,
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP,
BT_HCI_ERR_INVALID_LL_PARAM);
@ -4435,20 +4490,26 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
/* save parameters to be used to select offset
*/
conn->llcp_conn_param.interval_min = cpr->interval_min;
conn->llcp_conn_param.interval_max = cpr->interval_max;
conn->llcp_conn_param.latency = cpr->latency;
conn->llcp_conn_param.timeout = cpr->timeout;
conn->llcp_conn_param.interval_min = interval_min;
conn->llcp_conn_param.interval_max = interval_max;
conn->llcp_conn_param.latency = latency;
conn->llcp_conn_param.timeout = timeout;
conn->llcp_conn_param.preferred_periodicity =
cpr->preferred_periodicity;
preferred_periodicity;
conn->llcp_conn_param.reference_conn_event_count =
cpr->reference_conn_event_count;
conn->llcp_conn_param.offset0 = cpr->offset0;
conn->llcp_conn_param.offset1 = cpr->offset1;
conn->llcp_conn_param.offset2 = cpr->offset2;
conn->llcp_conn_param.offset3 = cpr->offset3;
conn->llcp_conn_param.offset4 = cpr->offset4;
conn->llcp_conn_param.offset5 = cpr->offset5;
sys_le16_to_cpu(cpr->reference_conn_event_count);
conn->llcp_conn_param.offset0 =
sys_le16_to_cpu(cpr->offset0);
conn->llcp_conn_param.offset1 =
sys_le16_to_cpu(cpr->offset1);
conn->llcp_conn_param.offset2 =
sys_le16_to_cpu(cpr->offset2);
conn->llcp_conn_param.offset3 =
sys_le16_to_cpu(cpr->offset3);
conn->llcp_conn_param.offset4 =
sys_le16_to_cpu(cpr->offset4);
conn->llcp_conn_param.offset5 =
sys_le16_to_cpu(cpr->offset5);
/* Perform connection update */
conn->llcp_conn_param.state = LLCP_CPR_STATE_RSP;

View file

@ -6,6 +6,7 @@
#include <zephyr.h>
#include <bluetooth/hci.h>
#include <misc/byteorder.h>
#include "util/util.h"
#include "util/memq.h"
@ -42,7 +43,7 @@
static void ticker_op_stop_scan_cb(u32_t status, void *params);
static void ticker_op_cb(u32_t status, void *params);
static u32_t access_addr_get(void);
static void access_addr_get(u8_t access_addr[]);
u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
u8_t filter_policy, u8_t peer_addr_type,
@ -55,7 +56,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
struct lll_scan *lll;
struct ll_conn *conn;
memq_link_t *link;
u32_t access_addr;
u8_t access_addr[4];
u32_t err;
u8_t hop;
@ -96,7 +97,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
conn_lll = &conn->lll;
access_addr = access_addr_get();
access_addr_get(access_addr);
memcpy(conn_lll->access_addr, &access_addr,
sizeof(conn_lll->access_addr));
bt_rand(&conn_lll->crc_init[0], 3);
@ -746,7 +747,7 @@ static void ticker_op_cb(u32_t status, void *params)
* - It shall have no more than eleven transitions in the least significant 16
* bits.
*/
static u32_t access_addr_get(void)
static void access_addr_get(u8_t access_addr[])
{
#if defined(CONFIG_BT_CTLR_PHY_CODED)
u8_t transitions_lsb16;
@ -755,7 +756,7 @@ static u32_t access_addr_get(void)
u8_t consecutive_cnt;
u8_t consecutive_bit;
u32_t adv_aa_check;
u32_t access_addr;
u32_t aa;
u8_t transitions;
u8_t bit_idx;
u8_t retry;
@ -765,7 +766,8 @@ again:
LL_ASSERT(retry);
retry--;
bt_rand(&access_addr, sizeof(u32_t));
bt_rand(access_addr, 4);
aa = sys_get_le32(access_addr);
bit_idx = 31;
transitions = 0;
@ -774,7 +776,7 @@ again:
ones_count_lsb8 = 0;
transitions_lsb16 = 0;
#endif /* CONFIG_BT_CTLR_PHY_CODED */
consecutive_bit = (access_addr >> bit_idx) & 0x01;
consecutive_bit = (aa >> bit_idx) & 0x01;
while (bit_idx--) {
#if defined(CONFIG_BT_CTLR_PHY_CODED)
u8_t transitions_lsb16_prev = transitions_lsb16;
@ -783,7 +785,7 @@ again:
u8_t transitions_prev = transitions;
u8_t bit;
bit = (access_addr >> bit_idx) & 0x01;
bit = (aa >> bit_idx) & 0x01;
if (bit == consecutive_bit) {
consecutive_cnt++;
} else {
@ -822,7 +824,7 @@ again:
((bit_idx < 28) && (transitions < 2))))) {
if (consecutive_bit) {
consecutive_bit = 0;
access_addr &= ~BIT(bit_idx);
aa &= ~BIT(bit_idx);
#if defined(CONFIG_BT_CTLR_PHY_CODED)
if (bit_idx < 8) {
ones_count_lsb8--;
@ -830,7 +832,7 @@ again:
#endif /* CONFIG_BT_CTLR_PHY_CODED */
} else {
consecutive_bit = 1;
access_addr |= BIT(bit_idx);
aa |= BIT(bit_idx);
#if defined(CONFIG_BT_CTLR_PHY_CODED)
if (bit_idx < 8) {
ones_count_lsb8++;
@ -869,9 +871,9 @@ again:
#endif /* CONFIG_BT_CTLR_PHY_CODED */
0) {
if (consecutive_bit) {
access_addr &= ~(BIT(bit_idx + 1) - 1);
aa &= ~(BIT(bit_idx + 1) - 1);
} else {
access_addr |= (BIT(bit_idx + 1) - 1);
aa |= (BIT(bit_idx + 1) - 1);
}
break;
@ -882,17 +884,17 @@ again:
* It shall not be a sequence that differs from the advertising channel
* packets Access Address by only one bit.
*/
adv_aa_check = access_addr ^ 0x8e89bed6;
adv_aa_check = aa ^ 0x8e89bed6;
if (util_ones_count_get((u8_t *)&adv_aa_check,
sizeof(adv_aa_check)) <= 1) {
goto again;
}
/* It shall not have all four octets equal. */
if (!((access_addr & 0xFFFF) ^ (access_addr >> 16)) &&
!((access_addr & 0xFF) ^ (access_addr >> 24))) {
if (!((aa & 0xFFFF) ^ (aa >> 16)) &&
!((aa & 0xFF) ^ (aa >> 24))) {
goto again;
}
return access_addr;
sys_put_le32(aa, access_addr);
}

View file

@ -8,6 +8,7 @@
#include <stdbool.h>
#include <toolchain.h>
#include <zephyr/types.h>
#include <misc/byteorder.h>
#include <misc/util.h>
#include "hal/ticker.h"
@ -60,6 +61,7 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
u8_t peer_addr_type;
u16_t win_offset;
u16_t timeout;
u16_t interval;
u8_t chan_sel;
((struct lll_adv *)ftr->param)->conn = NULL;
@ -76,11 +78,12 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
lll->data_chan_count = util_ones_count_get(&lll->data_chan_map[0],
sizeof(lll->data_chan_map));
lll->data_chan_hop = pdu_adv->connect_ind.hop;
lll->interval = pdu_adv->connect_ind.interval;
lll->latency = pdu_adv->connect_ind.latency;
interval = sys_le16_to_cpu(pdu_adv->connect_ind.interval);
lll->interval = interval;
lll->latency = sys_le16_to_cpu(pdu_adv->connect_ind.latency);
win_offset = pdu_adv->connect_ind.win_offset;
conn_interval_us = pdu_adv->connect_ind.interval * 1250;
win_offset = sys_le16_to_cpu(pdu_adv->connect_ind.win_offset);
conn_interval_us = interval * 1250;
/* calculate the window widening */
lll->slave.sca = pdu_adv->connect_ind.sca;
@ -92,9 +95,9 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
lll->slave.window_size_event_us = pdu_adv->connect_ind.win_size * 1250;
/* procedure timeouts */
timeout = sys_le16_to_cpu(pdu_adv->connect_ind.timeout);
conn->supervision_reload =
RADIO_CONN_EVENTS((pdu_adv->connect_ind.timeout * 10 * 1000),
conn_interval_us);
RADIO_CONN_EVENTS((timeout * 10 * 1000), conn_interval_us);
conn->procedure_reload =
RADIO_CONN_EVENTS((40 * 1000 * 1000), conn_interval_us);
@ -120,7 +123,6 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx,
chan_sel = pdu_adv->chan_sel;
peer_addr_type = pdu_adv->tx_addr;
memcpy(peer_addr, pdu_adv->connect_ind.init_addr, BDADDR_SIZE);
timeout = pdu_adv->connect_ind.timeout;
cc = (void *)pdu_adv;
cc->status = 0;