text: /*
   * 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 extended payload size */
  #define PDU_AC_EXT_PAYLOAD_SIZE_MAX 255
  
  /* Advertisement channel maximum payload size */
  #if defined(CONFIG_BT_CTLR_ADV_EXT)
  #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)
  #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)
  #else
  #define PDU_AC_PAYLOAD_SIZE_MAX     PDU_AC_LEG_PAYLOAD_SIZE_MAX
  #endif
  
  /* 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 maximum legacy advertising/scan data size */
  #define PDU_AC_DATA_SIZE_MAX   31
  
  /* 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 */
  #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 */
  #define PDU_DC_PAYLOAD_SIZE_MAX 251
  
  #if defined(CONFIG_BT_CTLR_DF)
  #define PDU_DC_PAYLOAD_TIME_MAX 2128
  #else
  #define PDU_DC_PAYLOAD_TIME_MAX 2120
  #endif
  
  #define PDU_DC_PAYLOAD_TIME_MAX_CODED 17040
  
  /* 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
  /* Standard allows 2 us timing uncertainty inside the event */
  #define EVENT_IFS_MAX_US        (EVENT_IFS_US + EVENT_CLOCK_JITTER_US)
  /* Controller will layout extended adv with minimum separation */
  #define EVENT_MAFS_US           300
  /* 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_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
  
  /* 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
  
  /*
   * 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)
  
  #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))
  
  struct pdu_adv_adv_ind {
  	uint8_t addr[BDADDR_SIZE];
  	uint8_t data[PDU_AC_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_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];
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  		uint8_t  hop:5;
  		uint8_t  sca:3;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  		uint8_t  sca:3;
  		uint8_t  hop:5;
  #else
  #error "Unsupported endianness"
  #endif
  
  	} __packed;
  } __packed;
  
  struct pdu_adv_ext_hdr {
  #if __BYTE_ORDER__ == __ORDER_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;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	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;
  #else
  #error "Unsupported endianness"
  #endif
  	uint8_t data[0];
  } __packed;
  
  struct pdu_adv_com_ext_adv {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t ext_hdr_len:6;
  	uint8_t adv_mode:2;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t adv_mode:2;
  	uint8_t ext_hdr_len:6;
  #else
  #error "Unsupported endianness"
  #endif
  	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 {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint16_t did:12;
  	uint16_t sid:4;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint16_t sid:4;
  	uint16_t did:12;
  #else
  #error "Unsupported endianness"
  #endif
  } __packed;
  
  struct pdu_adv_aux_ptr {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t  chan_idx:6;
  	uint8_t  ca:1;
  	uint8_t  offs_units:1;
  	uint16_t offs:13;
  	uint16_t phy:3;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t  offs_units:1;
  	uint8_t  ca:1;
  	uint8_t  chan_idx:6;
  	uint16_t phy:3;
  	uint16_t offs:13;
  #else
  #error "Unsupported endianness"
  #endif
  } __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_cte_info {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t  time:5;
  	uint8_t  rfu:1;
  	uint8_t  type:2;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t  type:2;
  	uint8_t  rfu:1;
  	uint8_t  time:5;
  #else
  #error "Unsupported endianness"
  #endif
  } __packed;
  
  struct pdu_adv_sync_info {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint16_t offs:13;
  	uint16_t offs_units:1;
  	uint16_t offs_adjust:1;
  	uint16_t rfu:1;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint16_t rfu:1;
  	uint16_t offs_adjust:1;
  	uint16_t offs_units:1;
  	uint16_t offs:13;
  #else
  #error "Unsupported endianness"
  #endif
  	uint16_t interval;
  	uint8_t  sca_chm[PDU_CHANNEL_MAP_SIZE];
  	uint32_t aa;
  	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 {
  #if __BYTE_ORDER__ == __ORDER_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;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t rx_addr:1;
  	uint8_t tx_addr:1;
  	uint8_t chan_sel:1;
  	uint8_t rfu:1;
  	uint8_t type:4;
  #else
  #error "Unsupported endianness"
  #endif
  
  	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_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;
  
  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;
  
  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 {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t min_cte_len_req : 5;
  	uint8_t rfu : 1;
  	uint8_t cte_type_req : 2;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t cte_type_req : 2;
  	uint8_t rfu : 1;
  	uint8_t min_cte_len_req : 5;
  #else
  #error "Unsupported endianness"
  #endif
  } __packed;
  
  struct pdu_data_llctrl_cte_rsp {
  	/* no members */
  } __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];
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t  c_bn:4;
  	uint8_t  p_bn:4;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t  p_bn:4;
  	uint8_t  c_bn:4;
  #else
  #error "Unsupported endianness"
  #endif
  	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 {
  	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_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;
  	} __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 {
  	uint8_t lcur;
  	uint8_t lmin;
  	uint8_t lmax;
  	uint8_t cur;
  	uint8_t min;
  	uint8_t max;
  	uint8_t radio;
  	uint8_t lll;
  	uint8_t ull_high;
  	uint8_t ull_low;
  } __packed;
  #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
  
  struct pdu_data {
  #if __BYTE_ORDER__ == __ORDER_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
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  #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;
  #else
  #error "Unsupported endianness"
  #endif
  
  	uint8_t len;
  
  #if !defined(CONFIG_SOC_OPENISA_RV32M1_RISCV32)
  #if !defined(CONFIG_BT_CTLR_DATA_LENGTH_CLEAR)
  	union {
  		uint8_t resv; /* TODO: remove nRF specific code */
  		struct pdu_cte_info cte_info; /* BT 5.1 Core spec. CTEInfo storage */
  	};
  #endif /* !CONFIG_BT_CTLR_DATA_LENGTH_CLEAR */
  #endif /* !CONFIG_SOC_OPENISA_RV32M1_RISCV32 */
  
  	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 {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t ll_id:2;
  	uint8_t hdr_other:6;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t hdr_other:6;
  	uint8_t ll_id:2;
  #else
  #error "Unsupported endianness"
  #endif /* __BYTE_ORDER__ */
  	uint8_t length;
  	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 {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t sc:1;
  	uint8_t cmplt:1;
  	uint8_t rfu:6;
  
  	uint8_t length;
  	/* Note, timeoffset only available in first segment of sdu */
  	uint32_t timeoffset:24;
  	uint32_t payload:8;
  
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t rfu:6;
  	uint8_t cmplt:1;
  	uint8_t sc:1;
  
  	uint8_t length;
  	/* Note, timeoffset only available in first segment of sdu */
  	uint32_t payload:8;
  	uint32_t timeoffset:24;
  #else
  #error "Unsupported endianness"
  #endif /* __BYTE_ORDER__ */
  } __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 {
  #if __BYTE_ORDER__ == __ORDER_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;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	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;
  #else
  #error "Unsupported endianness"
  #endif /* __BYTE_ORDER__ */
  	uint8_t length;
  	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 {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint8_t ll_id:2;
  	uint8_t cssn:3;
  	uint8_t cstf:1;
  	uint8_t rfu:2;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint8_t rfu:2;
  	uint8_t cstf:1;
  	uint8_t cssn:3;
  	uint8_t ll_id:2;
  #else
  #error "Unsupported endianness"
  #endif /* __BYTE_ORDER__ */
  	uint8_t len;
  	union {
  		uint8_t payload[0];
  		struct pdu_big_ctrl ctrl;
  	} __packed;
  } __packed;
  
  struct pdu_big_info {
  #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  	uint32_t offs:14;
  	uint32_t offs_units:1;
  	uint32_t iso_interval:12;
  	uint32_t num_bis:5;
  
  	uint32_t nse:5;
  	uint32_t bn:3;
  	uint32_t sub_interval:20;
  	uint32_t pto:4;
  
  	uint32_t spacing:20;
  	uint32_t irc:4;
  	uint32_t max_pdu:8;
  
  	uint8_t  rfu;
  
  	uint32_t seed_access_addr;
  
  	uint32_t sdu_interval:20;
  	uint32_t max_sdu:12;
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  	uint32_t num_bis:5;
  	uint32_t iso_interval:12;
  	uint32_t offs_units:1;
  	uint32_t offs:14;
  
  	uint32_t pto:4;
  	uint32_t sub_interval:20;
  	uint32_t bn:3;
  	uint32_t nse:5;
  
  	uint32_t max_pdu:8;
  	uint32_t irc:4;
  	uint32_t spacing:20;
  
  	uint8_t  rfu;
  
  	uint32_t seed_access_addr;
  
  	uint32_t max_sdu:12;
  	uint32_t sdu_interval:20;
  #else
  #error "Unsupported endianness"
  #endif /* __BYTE_ORDER__ */
  
  	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
  
  struct pdu_dtm {
  #if __BYTE_ORDER__ == __ORDER_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
  #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  #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;
  #else
  #error "Unsupported endianness"
  #endif
  	uint8_t length;
  #if defined(CONFIG_BT_CTLR_DF_CTE_TX)
  	union {
  		uint8_t resv; /* TODO: remove nRF specific code */
  		struct pdu_cte_info cte_info; /* BT 5.1 Core spec. CTEInfo storage */
  	};
  #endif
  	uint8_t payload[0];
  } __packed;
  
  /* Direct Test Mode maximum payload size */
  #define PDU_DTM_PAYLOAD_SIZE_MAX 255
  