Separate Tx/Rx frame spacing. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
1282 lines
36 KiB
C
1282 lines
36 KiB
C
/*
|
|
* Copyright (c) 2016 Nordic Semiconductor ASA
|
|
* Copyright (c) 2016 Vinayak Kariappa Chettimada
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/*
|
|
* PDU fields sizes
|
|
*/
|
|
|
|
#define PDU_PREAMBLE_SIZE(phy) (phy&0x3)
|
|
#define PDU_ACCESS_ADDR_SIZE 4
|
|
#define PDU_HEADER_SIZE 2
|
|
#define PDU_MIC_SIZE 4
|
|
#define PDU_CRC_SIZE 3
|
|
#define PDU_OVERHEAD_SIZE(phy) (PDU_PREAMBLE_SIZE(phy) + \
|
|
PDU_ACCESS_ADDR_SIZE + \
|
|
PDU_HEADER_SIZE + \
|
|
PDU_CRC_SIZE)
|
|
|
|
#define BDADDR_SIZE 6
|
|
#define ADVA_SIZE BDADDR_SIZE
|
|
#define SCANA_SIZE BDADDR_SIZE
|
|
#define INITA_SIZE BDADDR_SIZE
|
|
#define TARGETA_SIZE BDADDR_SIZE
|
|
#define LLDATA_SIZE 22
|
|
|
|
/* Constant offsets in extended header (TargetA is present in PDUs with AdvA) */
|
|
#define ADVA_OFFSET 0
|
|
#define TGTA_OFFSET (ADVA_OFFSET + BDADDR_SIZE)
|
|
|
|
#define BYTES2US(bytes, phy) (((bytes)<<3)/BIT((phy&0x3)>>1))
|
|
|
|
/* Advertisement channel minimum payload size */
|
|
#define PDU_AC_PAYLOAD_SIZE_MIN 1
|
|
/* Advertisement channel maximum legacy payload size */
|
|
#define PDU_AC_LEG_PAYLOAD_SIZE_MAX 37
|
|
/* Advertisement channel maximum legacy advertising/scan data size */
|
|
#define PDU_AC_LEG_DATA_SIZE_MAX 31
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
/* Advertisement channel maximum extended payload size */
|
|
#define PDU_AC_EXT_PAYLOAD_SIZE_MAX 255
|
|
|
|
/* Extended Scan and Periodic Sync Rx PDU time reservation */
|
|
#if defined(CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN)
|
|
#define PDU_AC_EXT_PAYLOAD_RX_SIZE 0U
|
|
#else /* !CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */
|
|
#define PDU_AC_EXT_PAYLOAD_RX_SIZE PDU_AC_EXT_PAYLOAD_SIZE_MAX
|
|
#endif /* !CONFIG_BT_CTLR_SCAN_AUX_SYNC_RESERVE_MIN */
|
|
|
|
#define PDU_AC_EXT_HEADER_SIZE_MIN offsetof(struct pdu_adv_com_ext_adv, \
|
|
ext_hdr_adv_data)
|
|
#define PDU_AC_EXT_HEADER_SIZE_MAX 63
|
|
/* TODO: PDU_AC_EXT_PAYLOAD_OVERHEAD can be reduced based on supported
|
|
* features, like omitting support for periodic advertising will reduce
|
|
* 18 octets in the Common Extended Advertising Payload Format.
|
|
*/
|
|
#define PDU_AC_EXT_PAYLOAD_OVERHEAD (PDU_AC_EXT_HEADER_SIZE_MIN + \
|
|
PDU_AC_EXT_HEADER_SIZE_MAX)
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_BROADCASTER)
|
|
#define PDU_AC_PAYLOAD_SIZE_MAX MAX(MIN((PDU_AC_EXT_PAYLOAD_OVERHEAD + \
|
|
CONFIG_BT_CTLR_ADV_DATA_LEN_MAX), \
|
|
PDU_AC_EXT_PAYLOAD_SIZE_MAX), \
|
|
PDU_AC_LEG_PAYLOAD_SIZE_MAX)
|
|
#define PDU_AC_EXT_AD_DATA_LEN_MAX (PDU_AC_PAYLOAD_SIZE_MAX - \
|
|
PDU_AC_EXT_PAYLOAD_OVERHEAD)
|
|
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_BROADCASTER */
|
|
#define PDU_AC_PAYLOAD_SIZE_MAX PDU_AC_LEG_PAYLOAD_SIZE_MAX
|
|
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_BROADCASTER */
|
|
|
|
/* Link Layer header size of Adv PDU. Assumes pdu_adv is packed */
|
|
#define PDU_AC_LL_HEADER_SIZE (offsetof(struct pdu_adv, payload))
|
|
|
|
/* Link Layer Advertisement channel maximum PDU buffer size */
|
|
#define PDU_AC_LL_SIZE_MAX (PDU_AC_LL_HEADER_SIZE + PDU_AC_PAYLOAD_SIZE_MAX)
|
|
|
|
/* Advertisement channel Access Address */
|
|
#define PDU_AC_ACCESS_ADDR 0x8e89bed6
|
|
|
|
/* Advertisement channel CRC init value */
|
|
#define PDU_AC_CRC_IV 0x555555
|
|
|
|
/* CRC polynomial */
|
|
#define PDU_CRC_POLYNOMIAL ((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16))
|
|
|
|
/* Data channel minimum payload size and time in us */
|
|
#define PDU_DC_PAYLOAD_SIZE_MIN 27
|
|
#define PDU_DC_PAYLOAD_TIME_MIN 328
|
|
#define PDU_DC_PAYLOAD_TIME_MIN_CODED 2704
|
|
|
|
/* Data channel maximum payload size and time in us */
|
|
#define PDU_DC_PAYLOAD_SIZE_MAX 251
|
|
#define PDU_DC_PAYLOAD_TIME_MAX_CODED 17040
|
|
|
|
#if defined(CONFIG_BT_CTLR_DF)
|
|
#define PDU_DC_PAYLOAD_TIME_MAX 2128
|
|
#else /* !CONFIG_BT_CTLR_DF */
|
|
#define PDU_DC_PAYLOAD_TIME_MAX 2120
|
|
#endif /* !CONFIG_BT_CTLR_DF */
|
|
|
|
/* Data channel control PDU maximum payload size */
|
|
#if defined(CONFIG_BT_CONN)
|
|
#if defined(CONFIG_BT_CTLR_CONN_ISO)
|
|
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PERIPHERAL)
|
|
/* Isochronous Central and Peripheral */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_req)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_req)
|
|
#elif defined(CONFIG_BT_CENTRAL)
|
|
/* Isochronous Central */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_req)
|
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_param_req)
|
|
#elif defined(CONFIG_BT_CTLR_LE_ENC)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_rsp)
|
|
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_rsp)
|
|
#endif /* !CONFIG_BT_CTLR_LE_ENC */
|
|
#elif defined(CONFIG_BT_PERIPHERAL)
|
|
/* Isochronous Peripheral */
|
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_param_req)
|
|
#elif defined(CONFIG_BT_CTLR_LE_ENC)
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_rsp)
|
|
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_rsp)
|
|
#endif /* !CONFIG_BT_CTLR_LE_ENC */
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(cis_req)
|
|
#endif /* !CONFIG_BT_PERIPHERAL */
|
|
|
|
#elif defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
|
/* Central and Peripheral with Connection Parameter Request */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_param_req)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_param_req)
|
|
|
|
#elif defined(CONFIG_BT_CTLR_LE_ENC)
|
|
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PERIPHERAL)
|
|
/* Central and Peripheral with encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_req)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_req)
|
|
#elif defined(CONFIG_BT_CENTRAL)
|
|
/* Central with encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_req)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_rsp)
|
|
#elif defined(CONFIG_BT_PERIPHERAL)
|
|
/* Peripheral with encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_rsp)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(enc_req)
|
|
#endif /* !CONFIG_BT_PERIPHERAL */
|
|
|
|
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
|
#if defined(CONFIG_BT_CENTRAL) && defined(CONFIG_BT_PERIPHERAL)
|
|
/* Central and Peripheral without encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_update_ind)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_update_ind)
|
|
#elif defined(CONFIG_BT_CENTRAL)
|
|
/* Central without encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_update_ind)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(feature_rsp)
|
|
#elif defined(CONFIG_BT_PERIPHERAL)
|
|
/* Peripheral without encryption */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX PDU_DATA_LLCTRL_LEN(feature_rsp)
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX PDU_DATA_LLCTRL_LEN(conn_update_ind)
|
|
#endif /* !CONFIG_BT_PERIPHERAL */
|
|
#endif /* !CONFIG_BT_CTLR_LE_ENC */
|
|
|
|
#else /* !CONFIG_BT_CONN */
|
|
#define PDU_DC_CTRL_TX_SIZE_MAX 0U
|
|
#define PDU_DC_CTRL_RX_SIZE_MAX 0U
|
|
#endif /* !CONFIG_BT_CONN */
|
|
|
|
/* Link Layer header size of Data PDU. Assumes pdu_data is packed */
|
|
#define PDU_DC_LL_HEADER_SIZE (offsetof(struct pdu_data, lldata))
|
|
|
|
/* Link Layer Max size of an empty PDU. TODO: Remove; only used in Nordic LLL */
|
|
#define PDU_EM_LL_SIZE_MAX (PDU_DC_LL_HEADER_SIZE)
|
|
|
|
/* Link Layer header size of BIS PDU. Assumes pdu_bis is packed */
|
|
#define PDU_BIS_LL_HEADER_SIZE (offsetof(struct pdu_bis, payload))
|
|
|
|
/* Event Active Clock Jitter */
|
|
#define EVENT_CLOCK_JITTER_US 2
|
|
/* Event interframe timings */
|
|
#define EVENT_IFS_US 150
|
|
/* Event interframe timings, default */
|
|
#define EVENT_IFS_DEFAULT_US EVENT_IFS_US
|
|
/* Standard allows 2 us timing uncertainty inside the event */
|
|
#define EVENT_IFS_MAX_US (EVENT_IFS_US + EVENT_CLOCK_JITTER_US)
|
|
/* Specification defined Minimum AUX Frame Space (MAFS) */
|
|
#define EVENT_MAFS_US 300
|
|
/* Controller dependent MAFS minimum used to populate aux_offset */
|
|
#define EVENT_MAFS_MIN_US MAX(EVENT_MAFS_US, PDU_ADV_AUX_OFFSET_MIN_US)
|
|
/* Standard allows 2 us timing uncertainty inside the event */
|
|
#define EVENT_MAFS_MAX_US (EVENT_MAFS_US + EVENT_CLOCK_JITTER_US)
|
|
/* Controller defined back to back transmit MAFS for extended advertising */
|
|
#define EVENT_B2B_MAFS_US (CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK_AFS)
|
|
/* Controller defined back to back transmit MAFS for periodic advertising */
|
|
#define EVENT_SYNC_B2B_MAFS_US (CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK_AFS)
|
|
/* Minimum Subevent Space timings */
|
|
#define EVENT_MSS_US 150
|
|
/* Standard allows 2 us timing uncertainty inside the event */
|
|
#define EVENT_MSS_MAX_US (EVENT_MSS_US + EVENT_CLOCK_JITTER_US)
|
|
|
|
/* Instant maximum value and maximum latency (or delta) past the instant */
|
|
#define EVENT_INSTANT_MAX 0xffff
|
|
#define EVENT_INSTANT_LATENCY_MAX 0x7fff
|
|
|
|
/* Channel Map Unused channels count minimum */
|
|
#define CHM_USED_COUNT_MIN 2U
|
|
|
|
/* Channel Map hop count minimum and maximum */
|
|
#define CHM_HOP_COUNT_MIN 5U
|
|
#define CHM_HOP_COUNT_MAX 16U
|
|
|
|
/* Offset Units field encoding */
|
|
#define OFFS_UNIT_BITS 13
|
|
#define OFFS_UNIT_30_US 30
|
|
#define OFFS_UNIT_300_US 300
|
|
#define OFFS_UNIT_VALUE_30_US 0
|
|
#define OFFS_UNIT_VALUE_300_US 1
|
|
/* Value specified in BT Spec. Vol 6, Part B, section 2.3.4.6 */
|
|
#define OFFS_ADJUST_US 2457600UL
|
|
|
|
/* Macros for getting offset/phy from pdu_adv_aux_ptr */
|
|
#define PDU_ADV_AUX_PTR_OFFSET_GET(aux_ptr) ((aux_ptr)->offs_phy_packed[0] | \
|
|
(((aux_ptr)->offs_phy_packed[1] & 0x1F) << 8))
|
|
#define PDU_ADV_AUX_PTR_PHY_GET(aux_ptr) (((aux_ptr)->offs_phy_packed[1] >> 5) & 0x07)
|
|
|
|
/* Macros for getting/setting offset/offset_units/offset_adjust from pdu_adv_sync_info */
|
|
#define PDU_ADV_SYNC_INFO_OFFSET_GET(si) ((si)->offs_packed[0] | \
|
|
(((si)->offs_packed[1] & 0x1F) << 8))
|
|
#define PDU_ADV_SYNC_INFO_OFFS_UNITS_GET(si) (((si)->offs_packed[1] >> 5) & 0x01)
|
|
#define PDU_ADV_SYNC_INFO_OFFS_ADJUST_GET(si) (((si)->offs_packed[1] >> 6) & 0x01)
|
|
#define PDU_ADV_SYNC_INFO_OFFS_SET(si, offs, offs_units, offs_adjust) \
|
|
do { \
|
|
(si)->offs_packed[0] = (offs) & 0xFF; \
|
|
(si)->offs_packed[1] = (((offs) >> 8) & 0x1F) + \
|
|
(((offs_units) << 5) & 0x20) + \
|
|
(((offs_adjust) << 6) & 0x40); \
|
|
} while (0)
|
|
|
|
/* Advertiser's Sleep Clock Accuracy Value */
|
|
#define SCA_500_PPM 500 /* 51 ppm to 500 ppm */
|
|
#define SCA_50_PPM 50 /* 0 ppm to 50 ppm */
|
|
#define SCA_VALUE_500_PPM 0 /* 51 ppm to 500 ppm */
|
|
#define SCA_VALUE_50_PPM 1 /* 0 ppm to 50 ppm */
|
|
|
|
/* Sleep Clock Accuracy, calculate drift in microseconds */
|
|
#define SCA_DRIFT_50_PPM_US(t) (((t) * 50UL) / 1000000UL)
|
|
#define SCA_DRIFT_500_PPM_US(t) (((t) * 500UL) / 1000000UL)
|
|
|
|
/* transmitWindowDelay times (us) */
|
|
#define WIN_DELAY_LEGACY 1250
|
|
#define WIN_DELAY_UNCODED 2500
|
|
#define WIN_DELAY_CODED 3750
|
|
|
|
/* Channel Map Size */
|
|
#define PDU_CHANNEL_MAP_SIZE 5
|
|
|
|
/* Advertising Data */
|
|
#define PDU_ADV_DATA_HEADER_SIZE 2U
|
|
#define PDU_ADV_DATA_HEADER_LEN_SIZE 1U
|
|
#define PDU_ADV_DATA_HEADER_TYPE_SIZE 1U
|
|
#define PDU_ADV_DATA_HEADER_LEN_OFFSET 0U
|
|
#define PDU_ADV_DATA_HEADER_TYPE_OFFSET 1U
|
|
#define PDU_ADV_DATA_HEADER_DATA_OFFSET 2U
|
|
|
|
/* Advertising Data Types in ACAD */
|
|
#define PDU_ADV_DATA_TYPE_CHANNEL_MAP_UPDATE_IND 0x28
|
|
|
|
/*
|
|
* Macros to return correct Data Channel PDU time
|
|
* Note: formula is valid for 1M, 2M and Coded S8
|
|
* see BT spec Version 5.1 Vol 6. Part B, chapters 2.1 and 2.2
|
|
* for packet formats and thus lengths
|
|
*/
|
|
|
|
#define PHY_LEGACY 0
|
|
#define PHY_1M BIT(0)
|
|
#define PHY_2M BIT(1)
|
|
#define PHY_CODED BIT(2)
|
|
#define PHY_FLAGS_S2 0
|
|
#define PHY_FLAGS_S8 BIT(0)
|
|
|
|
/* Macros for getting/setting did/sid from pdu_adv_adi */
|
|
#define PDU_ADV_ADI_DID_GET(adi) ((adi)->did_sid_packed[0] | \
|
|
(((adi)->did_sid_packed[1] & 0x0F) << 8))
|
|
#define PDU_ADV_ADI_SID_GET(adi) (((adi)->did_sid_packed[1] >> 4) & 0x0F)
|
|
#define PDU_ADV_ADI_SID_SET(adi, sid) (adi)->did_sid_packed[1] = (((sid) << 4) + \
|
|
((adi)->did_sid_packed[1] & 0x0F))
|
|
#define PDU_ADV_ADI_DID_SID_SET(adi, did, sid) \
|
|
do { \
|
|
(adi)->did_sid_packed[0] = (did) & 0xFF; \
|
|
(adi)->did_sid_packed[1] = (((did) >> 8) & 0x0F) + ((sid) << 4); \
|
|
} while (0)
|
|
|
|
#if defined(CONFIG_BT_CTLR_PHY_CODED)
|
|
#define CODED_PHY_PREAMBLE_TIME_US 80
|
|
#define CODED_PHY_ACCESS_ADDRESS_TIME_US 256
|
|
#define CODED_PHY_CI_TIME_US 16
|
|
#define CODED_PHY_TERM1_TIME_US 24
|
|
#define CODED_PHY_CRC_SIZE 24
|
|
#define CODED_PHY_TERM2_SIZE 3
|
|
|
|
#define FEC_BLOCK1_US ((CODED_PHY_ACCESS_ADDRESS_TIME_US) + \
|
|
(CODED_PHY_CI_TIME_US) + \
|
|
(CODED_PHY_TERM1_TIME_US))
|
|
|
|
/* cs = 0, S2 coding scheme, use PHY_FLAGS_S2
|
|
* cs = 1, S8 coding scheme, use PHY_FLAGS_S8
|
|
*
|
|
* Not using the term CI, Coding Indicator, where in the Spec its defined value
|
|
* of 0 is S8 encoding, 1 is S2 encoding.
|
|
*/
|
|
#define FEC_BLOCK2_US(octets, mic, cs) (((((PDU_HEADER_SIZE) + \
|
|
(octets) + \
|
|
(mic)) << 3) + \
|
|
(CODED_PHY_CRC_SIZE) + \
|
|
(CODED_PHY_TERM2_SIZE)) << \
|
|
(1 + (((cs) & 0x01) << 1)))
|
|
|
|
#define PDU_US(octets, mic, phy, cs) (((phy) & PHY_CODED) ? \
|
|
((CODED_PHY_PREAMBLE_TIME_US) + \
|
|
(FEC_BLOCK1_US) + \
|
|
FEC_BLOCK2_US((octets), (mic), \
|
|
(cs))) : \
|
|
(((PDU_PREAMBLE_SIZE(phy) + \
|
|
(PDU_ACCESS_ADDR_SIZE) + \
|
|
(PDU_HEADER_SIZE) + \
|
|
(octets) + \
|
|
(mic) + \
|
|
(PDU_CRC_SIZE)) << 3) / \
|
|
BIT(((phy) & 0x03) >> 1)))
|
|
|
|
#define PDU_MAX_US(octets, mic, phy) PDU_US((octets), (mic), (phy), \
|
|
PHY_FLAGS_S8)
|
|
|
|
#else /* !CONFIG_BT_CTLR_PHY_CODED */
|
|
#define PDU_US(octets, mic, phy, cs) (((PDU_PREAMBLE_SIZE(phy) + \
|
|
(PDU_ACCESS_ADDR_SIZE) + \
|
|
(PDU_HEADER_SIZE) + \
|
|
(octets) + \
|
|
(mic) + \
|
|
(PDU_CRC_SIZE)) << 3) / \
|
|
BIT(((phy) & 0x03) >> 1))
|
|
|
|
#define PDU_MAX_US(octets, mic, phy) PDU_US((octets), (mic), (phy), 0)
|
|
#endif /* !CONFIG_BT_CTLR_PHY_CODED */
|
|
|
|
#define PDU_DC_MAX_US(octets, phy) PDU_MAX_US((octets), (PDU_MIC_SIZE), (phy))
|
|
|
|
#define PDU_DC_US(octets, mic, phy, cs) PDU_US((octets), (mic), (phy), (cs))
|
|
|
|
#define PDU_AC_MAX_US(octets, phy) PDU_MAX_US((octets), 0, (phy))
|
|
|
|
#define PDU_AC_US(octets, phy, cs) PDU_US((octets), 0, (phy), (cs))
|
|
|
|
#define PDU_BIS_MAX_US(octets, enc, phy) PDU_MAX_US((octets), \
|
|
((enc) ? \
|
|
(PDU_MIC_SIZE) : 0), \
|
|
(phy))
|
|
|
|
#define PDU_BIS_US(octets, enc, phy, s8) PDU_US((octets), \
|
|
((enc) ? (PDU_MIC_SIZE) : 0), \
|
|
(phy), (s8))
|
|
|
|
#define PDU_CIS_MAX_US(octets, enc, phy) PDU_MAX_US((octets), \
|
|
((enc) ? \
|
|
(PDU_MIC_SIZE) : 0), \
|
|
(phy))
|
|
#define PDU_CIS_OFFSET_MIN_US 500U
|
|
|
|
struct pdu_adv_adv_ind {
|
|
uint8_t addr[BDADDR_SIZE];
|
|
uint8_t data[PDU_AC_LEG_DATA_SIZE_MAX];
|
|
} __packed;
|
|
|
|
struct pdu_adv_direct_ind {
|
|
uint8_t adv_addr[BDADDR_SIZE];
|
|
uint8_t tgt_addr[BDADDR_SIZE];
|
|
} __packed;
|
|
|
|
struct pdu_adv_scan_rsp {
|
|
uint8_t addr[BDADDR_SIZE];
|
|
uint8_t data[PDU_AC_LEG_DATA_SIZE_MAX];
|
|
} __packed;
|
|
|
|
struct pdu_adv_scan_req {
|
|
uint8_t scan_addr[BDADDR_SIZE];
|
|
uint8_t adv_addr[BDADDR_SIZE];
|
|
} __packed;
|
|
|
|
struct pdu_adv_connect_ind {
|
|
uint8_t init_addr[BDADDR_SIZE];
|
|
uint8_t adv_addr[BDADDR_SIZE];
|
|
struct {
|
|
uint8_t access_addr[4];
|
|
uint8_t crc_init[3];
|
|
uint8_t win_size;
|
|
uint16_t win_offset;
|
|
uint16_t interval;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint8_t chan_map[PDU_CHANNEL_MAP_SIZE];
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t hop:5;
|
|
uint8_t sca:3;
|
|
#else
|
|
uint8_t sca:3;
|
|
uint8_t hop:5;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
} __packed;
|
|
} __packed;
|
|
|
|
struct pdu_adv_ext_hdr {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t adv_addr:1;
|
|
uint8_t tgt_addr:1;
|
|
uint8_t cte_info:1;
|
|
uint8_t adi:1;
|
|
uint8_t aux_ptr:1;
|
|
uint8_t sync_info:1;
|
|
uint8_t tx_pwr:1;
|
|
uint8_t rfu:1;
|
|
#else
|
|
uint8_t rfu:1;
|
|
uint8_t tx_pwr:1;
|
|
uint8_t sync_info:1;
|
|
uint8_t aux_ptr:1;
|
|
uint8_t adi:1;
|
|
uint8_t cte_info:1;
|
|
uint8_t tgt_addr:1;
|
|
uint8_t adv_addr:1;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
uint8_t data[0];
|
|
} __packed;
|
|
|
|
struct pdu_adv_com_ext_adv {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t ext_hdr_len:6;
|
|
uint8_t adv_mode:2;
|
|
#else
|
|
uint8_t adv_mode:2;
|
|
uint8_t ext_hdr_len:6;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
union {
|
|
struct pdu_adv_ext_hdr ext_hdr;
|
|
uint8_t ext_hdr_adv_data[0];
|
|
};
|
|
} __packed;
|
|
|
|
enum pdu_adv_mode {
|
|
EXT_ADV_MODE_NON_CONN_NON_SCAN = 0x00,
|
|
EXT_ADV_MODE_CONN_NON_SCAN = 0x01,
|
|
EXT_ADV_MODE_NON_CONN_SCAN = 0x02,
|
|
};
|
|
|
|
#define PDU_ADV_SID_COUNT 16
|
|
|
|
struct pdu_adv_adi {
|
|
/* did:12
|
|
* sid:4
|
|
* NOTE: This layout as bitfields is not portable for BE using
|
|
* endianness conversion macros.
|
|
*/
|
|
uint8_t did_sid_packed[2];
|
|
} __packed;
|
|
|
|
struct pdu_adv_aux_ptr {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t chan_idx:6;
|
|
uint8_t ca:1;
|
|
uint8_t offs_units:1;
|
|
#else
|
|
uint8_t offs_units:1;
|
|
uint8_t ca:1;
|
|
uint8_t chan_idx:6;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
/* offs:13
|
|
* phy:3
|
|
* NOTE: This layout as bitfields is not portable for BE using
|
|
* endianness conversion macros.
|
|
*/
|
|
uint8_t offs_phy_packed[2];
|
|
} __packed;
|
|
|
|
enum pdu_adv_aux_ptr_ca {
|
|
EXT_ADV_AUX_PTR_CA_500_PPM = 0x00,
|
|
EXT_ADV_AUX_PTR_CA_50_PPM = 0x01,
|
|
};
|
|
|
|
enum pdu_adv_offs_units {
|
|
EXT_ADV_AUX_PTR_OFFS_UNITS_30 = 0x00,
|
|
EXT_ADV_AUX_PTR_OFFS_UNITS_300 = 0x01,
|
|
};
|
|
|
|
enum pdu_adv_aux_phy {
|
|
EXT_ADV_AUX_PHY_LE_1M = 0x00,
|
|
EXT_ADV_AUX_PHY_LE_2M = 0x01,
|
|
EXT_ADV_AUX_PHY_LE_CODED = 0x02,
|
|
};
|
|
|
|
struct pdu_adv_sync_info {
|
|
/* offs:13
|
|
* offs_units:1
|
|
* offs_adjust:1
|
|
* rfu:1
|
|
* NOTE: This layout as bitfields is not portable for BE using
|
|
* endianness conversion macros.
|
|
*/
|
|
uint8_t offs_packed[2];
|
|
uint16_t interval;
|
|
uint8_t sca_chm[PDU_CHANNEL_MAP_SIZE];
|
|
uint8_t aa[4];
|
|
uint8_t crc_init[3];
|
|
uint16_t evt_cntr;
|
|
} __packed;
|
|
|
|
#define PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET 4
|
|
#define PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS 5
|
|
#define PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK \
|
|
(0x07 << (PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS))
|
|
|
|
struct pdu_adv_sync_chm_upd_ind {
|
|
uint8_t chm[PDU_CHANNEL_MAP_SIZE];
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
enum pdu_adv_type {
|
|
PDU_ADV_TYPE_ADV_IND = 0x00,
|
|
PDU_ADV_TYPE_DIRECT_IND = 0x01,
|
|
PDU_ADV_TYPE_NONCONN_IND = 0x02,
|
|
PDU_ADV_TYPE_SCAN_REQ = 0x03,
|
|
PDU_ADV_TYPE_AUX_SCAN_REQ = PDU_ADV_TYPE_SCAN_REQ,
|
|
PDU_ADV_TYPE_SCAN_RSP = 0x04,
|
|
PDU_ADV_TYPE_ADV_IND_SCAN_RSP = 0x05,
|
|
PDU_ADV_TYPE_CONNECT_IND = 0x05,
|
|
PDU_ADV_TYPE_AUX_CONNECT_REQ = PDU_ADV_TYPE_CONNECT_IND,
|
|
PDU_ADV_TYPE_SCAN_IND = 0x06,
|
|
PDU_ADV_TYPE_EXT_IND = 0x07,
|
|
PDU_ADV_TYPE_AUX_ADV_IND = PDU_ADV_TYPE_EXT_IND,
|
|
PDU_ADV_TYPE_AUX_SCAN_RSP = PDU_ADV_TYPE_EXT_IND,
|
|
PDU_ADV_TYPE_AUX_SYNC_IND = PDU_ADV_TYPE_EXT_IND,
|
|
PDU_ADV_TYPE_AUX_CHAIN_IND = PDU_ADV_TYPE_EXT_IND,
|
|
PDU_ADV_TYPE_AUX_CONNECT_RSP = 0x08,
|
|
} __packed;
|
|
|
|
struct pdu_adv {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t type:4;
|
|
uint8_t rfu:1;
|
|
uint8_t chan_sel:1;
|
|
uint8_t tx_addr:1;
|
|
uint8_t rx_addr:1;
|
|
#else
|
|
uint8_t rx_addr:1;
|
|
uint8_t tx_addr:1;
|
|
uint8_t chan_sel:1;
|
|
uint8_t rfu:1;
|
|
uint8_t type:4;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
union {
|
|
uint8_t payload[0];
|
|
struct pdu_adv_adv_ind adv_ind;
|
|
struct pdu_adv_direct_ind direct_ind;
|
|
struct pdu_adv_scan_req scan_req;
|
|
struct pdu_adv_scan_rsp scan_rsp;
|
|
struct pdu_adv_connect_ind connect_ind;
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
struct pdu_adv_com_ext_adv adv_ext_ind;
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
|
} __packed;
|
|
} __packed;
|
|
|
|
enum pdu_data_llid {
|
|
PDU_DATA_LLID_RESV = 0x00,
|
|
PDU_DATA_LLID_DATA_CONTINUE = 0x01,
|
|
PDU_DATA_LLID_DATA_START = 0x02,
|
|
PDU_DATA_LLID_CTRL = 0x03,
|
|
};
|
|
|
|
enum pdu_data_llctrl_type {
|
|
PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_IND = 0x00,
|
|
PDU_DATA_LLCTRL_TYPE_CHAN_MAP_IND = 0x01,
|
|
PDU_DATA_LLCTRL_TYPE_TERMINATE_IND = 0x02,
|
|
PDU_DATA_LLCTRL_TYPE_ENC_REQ = 0x03,
|
|
PDU_DATA_LLCTRL_TYPE_ENC_RSP = 0x04,
|
|
PDU_DATA_LLCTRL_TYPE_START_ENC_REQ = 0x05,
|
|
PDU_DATA_LLCTRL_TYPE_START_ENC_RSP = 0x06,
|
|
PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP = 0x07,
|
|
PDU_DATA_LLCTRL_TYPE_FEATURE_REQ = 0x08,
|
|
PDU_DATA_LLCTRL_TYPE_FEATURE_RSP = 0x09,
|
|
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ = 0x0A,
|
|
PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP = 0x0B,
|
|
PDU_DATA_LLCTRL_TYPE_VERSION_IND = 0x0C,
|
|
PDU_DATA_LLCTRL_TYPE_REJECT_IND = 0x0D,
|
|
PDU_DATA_LLCTRL_TYPE_PER_INIT_FEAT_XCHG = 0x0E,
|
|
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_REQ = 0x0F,
|
|
PDU_DATA_LLCTRL_TYPE_CONN_PARAM_RSP = 0x10,
|
|
PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND = 0x11,
|
|
PDU_DATA_LLCTRL_TYPE_PING_REQ = 0x12,
|
|
PDU_DATA_LLCTRL_TYPE_PING_RSP = 0x13,
|
|
PDU_DATA_LLCTRL_TYPE_LENGTH_REQ = 0x14,
|
|
PDU_DATA_LLCTRL_TYPE_LENGTH_RSP = 0x15,
|
|
PDU_DATA_LLCTRL_TYPE_PHY_REQ = 0x16,
|
|
PDU_DATA_LLCTRL_TYPE_PHY_RSP = 0x17,
|
|
PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND = 0x18,
|
|
PDU_DATA_LLCTRL_TYPE_MIN_USED_CHAN_IND = 0x19,
|
|
PDU_DATA_LLCTRL_TYPE_CTE_REQ = 0x1A,
|
|
PDU_DATA_LLCTRL_TYPE_CTE_RSP = 0x1B,
|
|
PDU_DATA_LLCTRL_TYPE_PERIODIC_SYNC_IND = 0x1C,
|
|
PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_REQ = 0x1D,
|
|
PDU_DATA_LLCTRL_TYPE_CLOCK_ACCURACY_RSP = 0x1E,
|
|
PDU_DATA_LLCTRL_TYPE_CIS_REQ = 0x1F,
|
|
PDU_DATA_LLCTRL_TYPE_CIS_RSP = 0x20,
|
|
PDU_DATA_LLCTRL_TYPE_CIS_IND = 0x21,
|
|
PDU_DATA_LLCTRL_TYPE_CIS_TERMINATE_IND = 0x22,
|
|
PDU_DATA_LLCTRL_TYPE_UNUSED = 0xFF
|
|
};
|
|
|
|
struct pdu_data_llctrl_conn_update_ind {
|
|
uint8_t win_size;
|
|
uint16_t win_offset;
|
|
uint16_t interval;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_chan_map_ind {
|
|
uint8_t chm[PDU_CHANNEL_MAP_SIZE];
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_terminate_ind {
|
|
uint8_t error_code;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_enc_req {
|
|
uint8_t rand[8];
|
|
uint8_t ediv[2];
|
|
uint8_t skdm[8];
|
|
uint8_t ivm[4];
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_enc_rsp {
|
|
uint8_t skds[8];
|
|
uint8_t ivs[4];
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_start_enc_req {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_start_enc_rsp {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_unknown_rsp {
|
|
uint8_t type;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_feature_req {
|
|
uint8_t features[8];
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_feature_rsp {
|
|
uint8_t features[8];
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_pause_enc_req {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_pause_enc_rsp {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_version_ind {
|
|
uint8_t version_number;
|
|
uint16_t company_id;
|
|
uint16_t sub_version_number;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_reject_ind {
|
|
uint8_t error_code;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_per_init_feat_xchg {
|
|
uint8_t features[8];
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_conn_param_req {
|
|
uint16_t interval_min;
|
|
uint16_t interval_max;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint8_t preferred_periodicity;
|
|
uint16_t reference_conn_event_count;
|
|
uint16_t offset0;
|
|
uint16_t offset1;
|
|
uint16_t offset2;
|
|
uint16_t offset3;
|
|
uint16_t offset4;
|
|
uint16_t offset5;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_conn_param_rsp {
|
|
uint16_t interval_min;
|
|
uint16_t interval_max;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint8_t preferred_periodicity;
|
|
uint16_t reference_conn_event_count;
|
|
uint16_t offset0;
|
|
uint16_t offset1;
|
|
uint16_t offset2;
|
|
uint16_t offset3;
|
|
uint16_t offset4;
|
|
uint16_t offset5;
|
|
} __packed;
|
|
|
|
/*
|
|
* According to Spec Core v5.3, section 2.4.2.17
|
|
* LL_CONNECTION_PARAM_RSP and LL_CONNECTION_PARAM_REQ are identical
|
|
* This is utilized in pdu encode/decode, and for this is needed a common struct
|
|
*/
|
|
struct pdu_data_llctrl_conn_param_req_rsp_common {
|
|
uint16_t interval_min;
|
|
uint16_t interval_max;
|
|
uint16_t latency;
|
|
uint16_t timeout;
|
|
uint8_t preferred_periodicity;
|
|
uint16_t reference_conn_event_count;
|
|
uint16_t offset0;
|
|
uint16_t offset1;
|
|
uint16_t offset2;
|
|
uint16_t offset3;
|
|
uint16_t offset4;
|
|
uint16_t offset5;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_reject_ext_ind {
|
|
uint8_t reject_opcode;
|
|
uint8_t error_code;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_ping_req {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_ping_rsp {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_length_req {
|
|
uint16_t max_rx_octets;
|
|
uint16_t max_rx_time;
|
|
uint16_t max_tx_octets;
|
|
uint16_t max_tx_time;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_length_rsp {
|
|
uint16_t max_rx_octets;
|
|
uint16_t max_rx_time;
|
|
uint16_t max_tx_octets;
|
|
uint16_t max_tx_time;
|
|
} __packed;
|
|
|
|
/*
|
|
* According to Spec Core v5.3, section 2.4.2.21
|
|
* LL_LENGTH_REQ and LL_LENGTH_RSP are identical
|
|
* This is utilized in pdu encode/decode, and for this is needed a common struct
|
|
*/
|
|
struct pdu_data_llctrl_length_req_rsp_common {
|
|
uint16_t max_rx_octets;
|
|
uint16_t max_rx_time;
|
|
uint16_t max_tx_octets;
|
|
uint16_t max_tx_time;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_phy_req {
|
|
uint8_t tx_phys;
|
|
uint8_t rx_phys;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_phy_rsp {
|
|
uint8_t tx_phys;
|
|
uint8_t rx_phys;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_phy_upd_ind {
|
|
uint8_t c_to_p_phy;
|
|
uint8_t p_to_c_phy;
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_min_used_chans_ind {
|
|
uint8_t phys;
|
|
uint8_t min_used_chans;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cte_req {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t min_cte_len_req : 5;
|
|
uint8_t rfu : 1;
|
|
uint8_t cte_type_req : 2;
|
|
#else
|
|
uint8_t cte_type_req : 2;
|
|
uint8_t rfu : 1;
|
|
uint8_t min_cte_len_req : 5;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cte_rsp {
|
|
/* no members */
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_clock_accuracy_req {
|
|
uint8_t sca;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_clock_accuracy_rsp {
|
|
uint8_t sca;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cis_req {
|
|
uint8_t cig_id;
|
|
uint8_t cis_id;
|
|
uint8_t c_phy;
|
|
uint8_t p_phy;
|
|
/* c_max_sdu:12
|
|
* rfu:3
|
|
* framed:1
|
|
* NOTE: This layout as bitfields is not portable for BE using
|
|
* endianness conversion macros.
|
|
*/
|
|
uint8_t c_max_sdu_packed[2];
|
|
/* p_max_sdu:12
|
|
* rfu:4
|
|
* NOTE: This layout as bitfields is not portable for BE using
|
|
* endianness conversion macros.
|
|
*/
|
|
uint8_t p_max_sdu[2];
|
|
uint8_t c_sdu_interval[3];
|
|
uint8_t p_sdu_interval[3];
|
|
uint16_t c_max_pdu;
|
|
uint16_t p_max_pdu;
|
|
uint8_t nse;
|
|
uint8_t sub_interval[3];
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t c_bn:4;
|
|
uint8_t p_bn:4;
|
|
#else
|
|
uint8_t p_bn:4;
|
|
uint8_t c_bn:4;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
uint8_t c_ft;
|
|
uint8_t p_ft;
|
|
uint16_t iso_interval;
|
|
uint8_t cis_offset_min[3];
|
|
uint8_t cis_offset_max[3];
|
|
uint16_t conn_event_count;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cis_rsp {
|
|
uint8_t cis_offset_min[3];
|
|
uint8_t cis_offset_max[3];
|
|
uint16_t conn_event_count;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cis_ind {
|
|
uint8_t aa[4];
|
|
uint8_t cis_offset[3];
|
|
uint8_t cig_sync_delay[3];
|
|
uint8_t cis_sync_delay[3];
|
|
uint16_t conn_event_count;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_cis_terminate_ind {
|
|
uint8_t cig_id;
|
|
uint8_t cis_id;
|
|
uint8_t error_code;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl_periodic_sync_ind {
|
|
uint16_t id;
|
|
struct pdu_adv_sync_info sync_info;
|
|
uint16_t conn_event_count;
|
|
uint16_t last_pa_event_counter;
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t sid:4;
|
|
uint8_t addr_type:1;
|
|
uint8_t sca:3;
|
|
#else
|
|
uint8_t sca:3;
|
|
uint8_t addr_type:1;
|
|
uint8_t sid:4;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
uint8_t phy;
|
|
uint8_t adv_addr[6];
|
|
uint16_t sync_conn_event_count;
|
|
} __packed;
|
|
|
|
struct pdu_data_llctrl {
|
|
uint8_t opcode;
|
|
union {
|
|
struct pdu_data_llctrl_conn_update_ind conn_update_ind;
|
|
struct pdu_data_llctrl_chan_map_ind chan_map_ind;
|
|
struct pdu_data_llctrl_terminate_ind terminate_ind;
|
|
struct pdu_data_llctrl_enc_req enc_req;
|
|
struct pdu_data_llctrl_enc_rsp enc_rsp;
|
|
struct pdu_data_llctrl_start_enc_req start_enc_req;
|
|
struct pdu_data_llctrl_start_enc_rsp start_enc_rsp;
|
|
struct pdu_data_llctrl_unknown_rsp unknown_rsp;
|
|
struct pdu_data_llctrl_feature_req feature_req;
|
|
struct pdu_data_llctrl_feature_rsp feature_rsp;
|
|
struct pdu_data_llctrl_pause_enc_req pause_enc_req;
|
|
struct pdu_data_llctrl_pause_enc_rsp pause_enc_rsp;
|
|
struct pdu_data_llctrl_version_ind version_ind;
|
|
struct pdu_data_llctrl_reject_ind reject_ind;
|
|
struct pdu_data_llctrl_per_init_feat_xchg per_init_feat_xchg;
|
|
struct pdu_data_llctrl_conn_param_req conn_param_req;
|
|
struct pdu_data_llctrl_conn_param_rsp conn_param_rsp;
|
|
struct pdu_data_llctrl_reject_ext_ind reject_ext_ind;
|
|
struct pdu_data_llctrl_ping_req ping_req;
|
|
struct pdu_data_llctrl_ping_rsp ping_rsp;
|
|
struct pdu_data_llctrl_length_req length_req;
|
|
struct pdu_data_llctrl_length_rsp length_rsp;
|
|
struct pdu_data_llctrl_phy_req phy_req;
|
|
struct pdu_data_llctrl_phy_rsp phy_rsp;
|
|
struct pdu_data_llctrl_phy_upd_ind phy_upd_ind;
|
|
struct pdu_data_llctrl_min_used_chans_ind min_used_chans_ind;
|
|
struct pdu_data_llctrl_cte_req cte_req;
|
|
struct pdu_data_llctrl_cte_rsp cte_rsp;
|
|
struct pdu_data_llctrl_clock_accuracy_req clock_accuracy_req;
|
|
struct pdu_data_llctrl_clock_accuracy_rsp clock_accuracy_rsp;
|
|
struct pdu_data_llctrl_cis_req cis_req;
|
|
struct pdu_data_llctrl_cis_rsp cis_rsp;
|
|
struct pdu_data_llctrl_cis_ind cis_ind;
|
|
struct pdu_data_llctrl_cis_terminate_ind cis_terminate_ind;
|
|
struct pdu_data_llctrl_periodic_sync_ind periodic_sync_ind;
|
|
} __packed;
|
|
} __packed;
|
|
|
|
#define PDU_DATA_LLCTRL_LEN(type) (offsetof(struct pdu_data_llctrl, type) + \
|
|
sizeof(struct pdu_data_llctrl_ ## type))
|
|
|
|
#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
|
|
struct profile {
|
|
uint16_t lcur;
|
|
uint16_t lmin;
|
|
uint16_t lmax;
|
|
uint16_t cur;
|
|
uint16_t min;
|
|
uint16_t max;
|
|
uint16_t radio;
|
|
uint16_t lll;
|
|
uint16_t ull_high;
|
|
uint16_t ull_low;
|
|
uint8_t radio_ticks;
|
|
uint8_t lll_ticks;
|
|
uint8_t ull_high_ticks;
|
|
uint8_t ull_low_ticks;
|
|
} __packed;
|
|
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
|
|
|
|
struct pdu_data {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t ll_id:2;
|
|
uint8_t nesn:1;
|
|
uint8_t sn:1;
|
|
uint8_t md:1;
|
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
|
|
uint8_t cp:1;
|
|
uint8_t rfu:2;
|
|
#else
|
|
uint8_t rfu:3;
|
|
#endif
|
|
#else
|
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_TX) || defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
|
|
uint8_t rfu:2;
|
|
uint8_t cp:1;
|
|
#else
|
|
uint8_t rfu:3;
|
|
#endif
|
|
uint8_t md:1;
|
|
uint8_t sn:1;
|
|
uint8_t nesn:1;
|
|
uint8_t ll_id:2;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
struct pdu_data_vnd_octet3 octet3;
|
|
|
|
union {
|
|
struct pdu_data_llctrl llctrl;
|
|
uint8_t lldata[0];
|
|
|
|
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
|
|
uint8_t rssi;
|
|
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
|
|
|
|
#if defined(CONFIG_BT_CTLR_PROFILE_ISR)
|
|
struct profile profile;
|
|
#endif /* CONFIG_BT_CTLR_PROFILE_ISR */
|
|
} __packed;
|
|
} __packed;
|
|
|
|
/* Generic ISO pdu, could be CIS or BIS
|
|
* To be used when referring to component without knowing CIS or BIS type
|
|
*/
|
|
struct pdu_iso {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t ll_id:2;
|
|
uint8_t hdr_other:6;
|
|
#else
|
|
uint8_t hdr_other:6;
|
|
uint8_t ll_id:2;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
struct pdu_iso_vnd_octet3 octet3;
|
|
|
|
uint8_t payload[0];
|
|
} __packed;
|
|
|
|
/* ISO SDU segmentation header */
|
|
#define PDU_ISO_SEG_HDR_SIZE 2
|
|
#define PDU_ISO_SEG_TIMEOFFSET_SIZE 3
|
|
|
|
struct pdu_iso_sdu_sh {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t sc:1;
|
|
uint8_t cmplt:1;
|
|
uint8_t rfu:6;
|
|
|
|
uint8_t len;
|
|
/* Note, timeoffset only available in first segment of sdu */
|
|
uint32_t timeoffset:24;
|
|
uint32_t payload:8;
|
|
#else
|
|
uint8_t rfu:6;
|
|
uint8_t cmplt:1;
|
|
uint8_t sc:1;
|
|
|
|
uint8_t len;
|
|
|
|
/* Note, timeoffset only available in first segment of sdu */
|
|
uint32_t timeoffset:24;
|
|
uint32_t payload:8;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
} __packed;
|
|
|
|
enum pdu_cis_llid {
|
|
/** Unframed complete or end fragment */
|
|
PDU_CIS_LLID_COMPLETE_END = 0x00,
|
|
/** Unframed start or continuation fragment */
|
|
PDU_CIS_LLID_START_CONTINUE = 0x01,
|
|
/** Framed; one or more segments of a SDU */
|
|
PDU_CIS_LLID_FRAMED = 0x02
|
|
};
|
|
|
|
struct pdu_cis {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t ll_id:2;
|
|
uint8_t nesn:1;
|
|
uint8_t sn:1;
|
|
uint8_t cie:1;
|
|
uint8_t rfu0:1;
|
|
uint8_t npi:1;
|
|
uint8_t rfu1:1;
|
|
#else
|
|
uint8_t rfu1:1;
|
|
uint8_t npi:1;
|
|
uint8_t rfu0:1;
|
|
uint8_t cie:1;
|
|
uint8_t sn:1;
|
|
uint8_t nesn:1;
|
|
uint8_t ll_id:2;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
struct pdu_cis_vnd_octet3 octet3;
|
|
|
|
uint8_t payload[0];
|
|
} __packed;
|
|
|
|
enum pdu_big_ctrl_type {
|
|
PDU_BIG_CTRL_TYPE_CHAN_MAP_IND = 0x00,
|
|
PDU_BIG_CTRL_TYPE_TERM_IND = 0x01,
|
|
};
|
|
|
|
struct pdu_big_ctrl_chan_map_ind {
|
|
uint8_t chm[PDU_CHANNEL_MAP_SIZE];
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
struct pdu_big_ctrl_term_ind {
|
|
uint8_t reason;
|
|
uint16_t instant;
|
|
} __packed;
|
|
|
|
|
|
struct pdu_big_ctrl {
|
|
uint8_t opcode;
|
|
union {
|
|
uint8_t ctrl_data[0];
|
|
struct pdu_big_ctrl_chan_map_ind chan_map_ind;
|
|
struct pdu_big_ctrl_term_ind term_ind;
|
|
} __packed;
|
|
} __packed;
|
|
|
|
enum pdu_bis_llid {
|
|
/** Unframed complete or end fragment */
|
|
PDU_BIS_LLID_COMPLETE_END = 0x00,
|
|
/** Unframed start or continuation fragment */
|
|
PDU_BIS_LLID_START_CONTINUE = 0x01,
|
|
/** Framed; one or more segments of a SDU */
|
|
PDU_BIS_LLID_FRAMED = 0x02,
|
|
/** BIG Control PDU */
|
|
PDU_BIS_LLID_CTRL = 0x03,
|
|
};
|
|
|
|
struct pdu_bis {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t ll_id:2;
|
|
uint8_t cssn:3;
|
|
uint8_t cstf:1;
|
|
uint8_t rfu:2;
|
|
#else
|
|
uint8_t rfu:2;
|
|
uint8_t cstf:1;
|
|
uint8_t cssn:3;
|
|
uint8_t ll_id:2;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
struct pdu_bis_vnd_octet3 octet3;
|
|
|
|
union {
|
|
uint8_t payload[0];
|
|
struct pdu_big_ctrl ctrl;
|
|
} __packed;
|
|
} __packed;
|
|
|
|
struct pdu_big_info {
|
|
/* offs:14 [0].0 - [1].5
|
|
* offs_units:1 [1].6
|
|
* iso_interval:12 [1].7 - [3].2
|
|
* num_bis:5 [3].3 - [3].7
|
|
*/
|
|
uint8_t bi_packed_0_3[4];
|
|
|
|
/* nse:5 [0].0 - [0].4
|
|
* bn:3 [0].5 - [0].7
|
|
* sub_interval:20 [1].0 - [3].3
|
|
* pto:4 [3].4 - [3].7
|
|
*/
|
|
uint8_t bi_packed_4_7[4];
|
|
|
|
/* spacing:20 [0].0 - [2].3
|
|
* irc:4 [2].4 - [2].7
|
|
*/
|
|
uint8_t bi_packed_8_11[3];
|
|
|
|
uint8_t max_pdu;
|
|
|
|
uint8_t rfu;
|
|
|
|
uint32_t seed_access_addr;
|
|
|
|
/* sdu_interval:20 [0].0 - [2].3
|
|
* max_sdu:12; [2].4 - [3].7
|
|
*/
|
|
uint8_t sdu_packed[4];
|
|
|
|
uint16_t base_crc_init;
|
|
|
|
uint8_t chm_phy[PDU_CHANNEL_MAP_SIZE]; /* 37 bit chm; 3 bit phy */
|
|
uint8_t payload_count_framing[5]; /* 39 bit count; 1 bit framing */
|
|
|
|
uint8_t giv[8]; /* encryption required */
|
|
uint8_t gskd[16]; /* encryption required */
|
|
} __packed;
|
|
#define PDU_BIG_INFO_CLEARTEXT_SIZE offsetof(struct pdu_big_info, giv)
|
|
#define PDU_BIG_INFO_ENCRYPTED_SIZE sizeof(struct pdu_big_info)
|
|
#define PDU_BIG_BN_MAX 0x07
|
|
#define PDU_BIG_PAYLOAD_COUNT_MAX 28
|
|
|
|
#define PDU_BIG_INFO_OFFS_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_0_3[0], 0, 14)
|
|
#define PDU_BIG_INFO_OFFS_UNITS_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_0_3[1], 6, 1)
|
|
#define PDU_BIG_INFO_ISO_INTERVAL_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_0_3[1], 7, 12)
|
|
#define PDU_BIG_INFO_NUM_BIS_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_0_3[3], 3, 5)
|
|
#define PDU_BIG_INFO_NSE_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_4_7[0], 0, 5)
|
|
#define PDU_BIG_INFO_BN_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_4_7[0], 5, 3)
|
|
#define PDU_BIG_INFO_SUB_INTERVAL_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_4_7[1], 0, 20)
|
|
#define PDU_BIG_INFO_PTO_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_4_7[3], 4, 4)
|
|
#define PDU_BIG_INFO_SPACING_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_8_11[0], 0, 20)
|
|
#define PDU_BIG_INFO_IRC_GET(bi) \
|
|
util_get_bits(&(bi)->bi_packed_8_11[2], 4, 4)
|
|
#define PDU_BIG_INFO_SDU_INTERVAL_GET(bi) \
|
|
util_get_bits(&(bi)->sdu_packed[0], 0, 20)
|
|
#define PDU_BIG_INFO_MAX_SDU_GET(bi) \
|
|
util_get_bits(&(bi)->sdu_packed[2], 4, 12)
|
|
|
|
#define PDU_BIG_INFO_OFFS_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_0_3[0], 0, 14, val)
|
|
#define PDU_BIG_INFO_OFFS_UNITS_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_0_3[1], 6, 1, val)
|
|
#define PDU_BIG_INFO_ISO_INTERVAL_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_0_3[1], 7, 12, val)
|
|
#define PDU_BIG_INFO_NUM_BIS_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_0_3[3], 3, 5, val)
|
|
#define PDU_BIG_INFO_NSE_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_4_7[0], 0, 5, val)
|
|
#define PDU_BIG_INFO_BN_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_4_7[0], 5, 3, val)
|
|
#define PDU_BIG_INFO_SUB_INTERVAL_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_4_7[1], 0, 20, val)
|
|
#define PDU_BIG_INFO_PTO_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_4_7[3], 4, 4, val)
|
|
#define PDU_BIG_INFO_SPACING_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_8_11[0], 0, 20, val)
|
|
#define PDU_BIG_INFO_IRC_SET(bi, val) \
|
|
util_set_bits(&(bi)->bi_packed_8_11[2], 4, 4, val)
|
|
#define PDU_BIG_INFO_SDU_INTERVAL_SET(bi, val) \
|
|
util_set_bits(&(bi)->sdu_packed[0], 0, 20, val)
|
|
#define PDU_BIG_INFO_MAX_SDU_SET(bi, val) \
|
|
util_set_bits(&(bi)->sdu_packed[2], 4, 12, val)
|
|
|
|
struct pdu_dtm {
|
|
#ifdef CONFIG_LITTLE_ENDIAN
|
|
uint8_t type:4;
|
|
uint8_t rfu0:1;
|
|
#if defined(CONFIG_BT_CTLR_DF_CTE_TX)
|
|
uint8_t cp:1;
|
|
uint8_t rfu1:2;
|
|
#else
|
|
uint8_t rfu1:3;
|
|
#endif
|
|
#else
|
|
#if defined(CONFIG_BT_CTLR_DF_CTE_TX)
|
|
uint8_t rfu1:2;
|
|
uint8_t cp:1;
|
|
#else
|
|
uint8_t rfu1:3;
|
|
#endif
|
|
uint8_t rfu0:1;
|
|
uint8_t type:4;
|
|
#endif /* CONFIG_LITTLE_ENDIAN */
|
|
|
|
uint8_t len;
|
|
|
|
struct pdu_data_vnd_octet3 octet3;
|
|
|
|
uint8_t payload[0];
|
|
} __packed;
|
|
|
|
/* Direct Test Mode maximum payload size */
|
|
#define PDU_DTM_PAYLOAD_SIZE_MAX 255
|