diff --git a/include/bluetooth/hci.h b/include/bluetooth/hci.h index 449f06a8338..75b377b29d0 100644 --- a/include/bluetooth/hci.h +++ b/include/bluetooth/hci.h @@ -141,9 +141,23 @@ struct bt_hci_cmd_hdr { #define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0) /* LE features */ -#define BT_FEAT_LE_ENCR(feat) BT_FEAT_TEST(feat, 0, 0, 0) -#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_FEAT_TEST(feat, 0, 0, 1) -#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat) BT_FEAT_TEST(feat, 0, 0, 3) +#define BT_LE_FEAT_BIT_ENC 0 +#define BT_LE_FEAT_BIT_CONN_PARAM_REQ 1 +#define BT_LE_FEAT_BIT_EXT_REJ_IND 2 +#define BT_LE_FEAT_BIT_SLAVE_FEAT_REQ 3 +#define BT_LE_FEAT_BIT_PING 4 +#define BT_LE_FEAT_BIT_DLE 5 +#define BT_LE_FEAT_BIT_PRIVACY 6 +#define BT_LE_FEAT_BIT_EXT_SCAN 7 + +#define BT_FEAT_LE_ENCR(feat) BT_FEAT_TEST(feat, 0, 0, \ + BT_LE_FEAT_BIT_ENC) +#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_FEAT_TEST(feat, 0, 0, \ + BT_LE_FEAT_BIT_CONN_PARAM_REQ) +#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat) BT_FEAT_TEST(feat, 0, 0, \ + BT_LE_FEAT_BIT_SLAVE_FEAT_REQ) +#define BT_FEAT_LE_DLE(feat) BT_FEAT_TEST(feat, 0, 0, \ + BT_LE_FEAT_BIT_DLE) /* LE States */ #define BT_LE_STATES_SLAVE_CONN_ADV(states) (states & 0x0000004000000000) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index ec9ba87c78b..50b985752d7 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -679,6 +679,39 @@ static void le_set_data_len(struct net_buf *buf, struct net_buf *evt) rp->handle = cmd->handle; } +static void le_read_default_data_len(struct net_buf *buf, struct net_buf *evt) +{ + struct bt_hci_rp_le_read_default_data_len *rp; + + rp = cmd_complete(evt, sizeof(*rp)); + + radio_length_default_get(&rp->max_tx_octets, &rp->max_tx_time); + rp->status = 0x00; +} + +static void le_write_default_data_len(struct net_buf *buf, struct net_buf *evt) +{ + struct bt_hci_cp_le_write_default_data_len *cmd = (void *)buf->data; + struct bt_hci_evt_cc_status *ccst; + uint32_t status; + + status = radio_length_default_set(cmd->max_tx_octets, cmd->max_tx_time); + + ccst = cmd_complete(evt, sizeof(*ccst)); + ccst->status = (!status) ? 0x00 : BT_HCI_ERR_INVALID_LL_PARAMS; +} + +static void le_read_max_data_len(struct net_buf *buf, struct net_buf *evt) +{ + struct bt_hci_rp_le_read_max_data_len *rp; + + rp = cmd_complete(evt, sizeof(*rp)); + + radio_length_max_get(&rp->max_tx_octets, &rp->max_tx_time, + &rp->max_rx_octets, &rp->max_rx_time); + rp->status = 0x00; +} + static int controller_cmd_handle(uint8_t ocf, struct net_buf *cmd, struct net_buf *evt) { @@ -799,6 +832,18 @@ static int controller_cmd_handle(uint8_t ocf, struct net_buf *cmd, le_set_data_len(cmd, evt); break; + case BT_OCF(BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN): + le_read_default_data_len(cmd, evt); + break; + + case BT_OCF(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN): + le_write_default_data_len(cmd, evt); + break; + + case BT_OCF(BT_HCI_OP_LE_READ_MAX_DATA_LEN): + le_read_max_data_len(cmd, evt); + break; + default: return -EINVAL; } diff --git a/subsys/bluetooth/controller/ll/ctrl.c b/subsys/bluetooth/controller/ll/ctrl.c index 687d0531a2d..e4258318f25 100644 --- a/subsys/bluetooth/controller/ll/ctrl.c +++ b/subsys/bluetooth/controller/ll/ctrl.c @@ -159,6 +159,10 @@ static struct { uint8_t data_channel_count; uint8_t sca; + /* DLE global settings */ + uint16_t default_tx_octets; + uint16_t default_tx_time; + /** @todo below members to be made role specific and quota managed for * Rx-es. */ @@ -475,6 +479,10 @@ static void common_init(void) _radio.data_channel_map[4] = 0x1F; _radio.data_channel_count = 37; + /* Initialize the DLE defaults */ + _radio.default_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; + _radio.default_tx_time = RADIO_LL_LENGTH_TIME_RX_MIN; + /* allocate the rx queue */ packet_rx_allocate(0xFF); } @@ -1249,11 +1257,11 @@ static inline void isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx, lr = (struct pdu_data_llctrl_length_req_rsp *) &pdu_data_rx->payload.llctrl.ctrldata.length_req; - /* use the minimal of our sugg_tx_octets and + /* use the minimal of our default_tx_octets and * peer max_rx_octets */ - if (lr->max_rx_octets > _radio.conn_curr->sug_tx_octets) { - eff_tx_octets = _radio.conn_curr->sug_tx_octets; + if (lr->max_rx_octets > _radio.conn_curr->default_tx_octets) { + eff_tx_octets = _radio.conn_curr->default_tx_octets; } else { eff_tx_octets = lr->max_rx_octets; } @@ -4907,8 +4915,8 @@ static inline void event_len_prep(struct connection *conn) /* wait for resp before completing the procedure */ conn->llcp_length.state = LLCP_LENGTH_STATE_ACK_WAIT; - /* set the suggested tx octets to requested value */ - conn->sug_tx_octets = conn->llcp_length.tx_octets; + /* set the default tx octets to requested value */ + conn->default_tx_octets = conn->llcp_length.tx_octets; /* place the length req packet as next in tx queue */ pdu_ctrl_tx = (struct pdu_data *) node_tx->pdu_data; @@ -4922,8 +4930,8 @@ static inline void event_len_prep(struct connection *conn) &pdu_ctrl_tx->payload.llctrl.ctrldata.length_req; lr->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX; lr->max_rx_time = ((RADIO_LL_LENGTH_OCTETS_RX_MAX + 14) << 3); - lr->max_tx_octets = conn->sug_tx_octets; - lr->max_tx_time = ((conn->sug_tx_octets + 14) << 3); + lr->max_tx_octets = conn->default_tx_octets; + lr->max_tx_time = ((conn->default_tx_octets + 14) << 3); ctrl_tx_enqueue(conn, node_tx); @@ -6656,7 +6664,7 @@ uint32_t radio_adv_enable(uint16_t interval, uint8_t chl_map, conn->event_counter = 0; conn->latency_prepare = 0; conn->latency_event = 0; - conn->sug_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; + conn->default_tx_octets = _radio.default_tx_octets; conn->max_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; conn->role.slave.role = 1; @@ -6977,7 +6985,7 @@ uint32_t radio_connect_enable(uint8_t adv_addr_type, uint8_t *adv_addr, conn->latency_prepare = 0; conn->latency_event = 0; conn->latency = _radio.observer.conn_latency; - conn->sug_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; + conn->default_tx_octets = _radio.default_tx_octets; conn->max_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN; conn->role.master.role = 0; @@ -7315,6 +7323,35 @@ uint32_t radio_length_req_send(uint16_t handle, uint16_t tx_octets) return 0; } +void radio_length_default_get(uint16_t *max_tx_octets, uint16_t *max_tx_time) +{ + *max_tx_octets = _radio.default_tx_octets; + *max_tx_time = _radio.default_tx_time; +} + +uint32_t radio_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time) +{ + if (max_tx_octets > RADIO_LL_LENGTH_OCTETS_RX_MAX || + max_tx_time > RADIO_LL_LENGTH_TIME_RX_MAX) { + + return 1; + } + + _radio.default_tx_octets = max_tx_octets; + _radio.default_tx_time = max_tx_time; + + return 0; +} + +void radio_length_max_get(uint16_t *max_tx_octets, uint16_t *max_tx_time, + uint16_t *max_rx_octets, uint16_t *max_rx_time) +{ + *max_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX; + *max_tx_time = RADIO_LL_LENGTH_TIME_RX_MAX; + *max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX; + *max_rx_time = RADIO_LL_LENGTH_TIME_RX_MAX; +} + static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last) { uint8_t _first; diff --git a/subsys/bluetooth/controller/ll/ctrl.h b/subsys/bluetooth/controller/ll/ctrl.h index cd2a6c1e996..8b57854d159 100644 --- a/subsys/bluetooth/controller/ll/ctrl.h +++ b/subsys/bluetooth/controller/ll/ctrl.h @@ -18,6 +18,8 @@ #ifndef _CTRL_H_ #define _CTRL_H_ +#include + /***************************************************************************** * Zephyr Kconfig defined ****************************************************************************/ @@ -81,11 +83,13 @@ #define RADIO_BLE_VERSION_NUMBER (0x08) #define RADIO_BLE_COMPANY_ID (0xFFFF) #define RADIO_BLE_SUB_VERSION_NUMBER (0xFFFF) -#define RADIO_BLE_FEATURES (0x1F) /* LE Ping, Slave Initiated - * Feature request, Extended - * Reject Indication, Conn Param - * Req Procedure, LE encryption. - */ + +#define RADIO_BLE_FEATURES (BT_LE_FEAT_BIT_ENC | \ + BT_LE_FEAT_BIT_CONN_PARAM_REQ | \ + BT_LE_FEAT_BIT_EXT_REJ_IND | \ + BT_LE_FEAT_BIT_SLAVE_FEAT_REQ | \ + BT_LE_FEAT_BIT_PING | \ + BT_LE_FEAT_BIT_DLE) /***************************************************************************** * Controller Reference Defines (compile time override-able) @@ -241,6 +245,10 @@ uint32_t radio_feature_req_send(uint16_t handle); uint32_t radio_version_ind_send(uint16_t handle); uint32_t radio_terminate_ind_send(uint16_t handle, uint8_t reason); uint32_t radio_length_req_send(uint16_t handle, uint16_t tx_octets); +void radio_length_default_get(uint16_t *max_tx_octets, uint16_t *max_tx_time); +uint32_t radio_length_default_set(uint16_t max_tx_octets, uint16_t max_tx_time); +void radio_length_max_get(uint16_t *max_tx_octets, uint16_t *max_tx_time, + uint16_t *max_rx_octets, uint16_t *max_rx_time); uint8_t radio_rx_get(struct radio_pdu_node_rx **radio_pdu_node_rx, uint16_t *handle); void radio_rx_dequeue(void); diff --git a/subsys/bluetooth/controller/ll/ctrl_internal.h b/subsys/bluetooth/controller/ll/ctrl_internal.h index 21e8959c76e..fa55e5d5b0d 100644 --- a/subsys/bluetooth/controller/ll/ctrl_internal.h +++ b/subsys/bluetooth/controller/ll/ctrl_internal.h @@ -55,7 +55,7 @@ struct connection { uint16_t latency; uint16_t latency_prepare; uint16_t latency_event; - uint16_t sug_tx_octets; + uint16_t default_tx_octets; uint16_t max_tx_octets; uint16_t max_rx_octets; uint16_t supervision_reload;