Bluetooth: Controller: Implement missing DLE commands
Implement the 3 missing HCI commands required to support Data Length Extensions: - LE Read Suggested Default Data Length - LE Write Suggested Default Data Length - LE Read Maximum Data Length Note: Only octets are actually used at this time, not time. Jira: ZEP-1246 Change-Id: Id76d8fedb5ecaf0001c8429cf22f9a3e2c910a44 Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
e9b818e763
commit
c969e757bc
5 changed files with 122 additions and 18 deletions
|
@ -141,9 +141,23 @@ struct bt_hci_cmd_hdr {
|
||||||
#define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0)
|
#define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0)
|
||||||
|
|
||||||
/* LE features */
|
/* LE features */
|
||||||
#define BT_FEAT_LE_ENCR(feat) BT_FEAT_TEST(feat, 0, 0, 0)
|
#define BT_LE_FEAT_BIT_ENC 0
|
||||||
#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_FEAT_TEST(feat, 0, 0, 1)
|
#define BT_LE_FEAT_BIT_CONN_PARAM_REQ 1
|
||||||
#define BT_FEAT_LE_SLAVE_FEATURE_XCHG(feat) BT_FEAT_TEST(feat, 0, 0, 3)
|
#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 */
|
/* LE States */
|
||||||
#define BT_LE_STATES_SLAVE_CONN_ADV(states) (states & 0x0000004000000000)
|
#define BT_LE_STATES_SLAVE_CONN_ADV(states) (states & 0x0000004000000000)
|
||||||
|
|
|
@ -679,6 +679,39 @@ static void le_set_data_len(struct net_buf *buf, struct net_buf *evt)
|
||||||
rp->handle = cmd->handle;
|
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,
|
static int controller_cmd_handle(uint8_t ocf, struct net_buf *cmd,
|
||||||
struct net_buf *evt)
|
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);
|
le_set_data_len(cmd, evt);
|
||||||
break;
|
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:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,6 +159,10 @@ static struct {
|
||||||
uint8_t data_channel_count;
|
uint8_t data_channel_count;
|
||||||
uint8_t sca;
|
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
|
/** @todo below members to be made role specific and quota managed for
|
||||||
* Rx-es.
|
* Rx-es.
|
||||||
*/
|
*/
|
||||||
|
@ -475,6 +479,10 @@ static void common_init(void)
|
||||||
_radio.data_channel_map[4] = 0x1F;
|
_radio.data_channel_map[4] = 0x1F;
|
||||||
_radio.data_channel_count = 37;
|
_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 */
|
/* allocate the rx queue */
|
||||||
packet_rx_allocate(0xFF);
|
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 *)
|
lr = (struct pdu_data_llctrl_length_req_rsp *)
|
||||||
&pdu_data_rx->payload.llctrl.ctrldata.length_req;
|
&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
|
* peer max_rx_octets
|
||||||
*/
|
*/
|
||||||
if (lr->max_rx_octets > _radio.conn_curr->sug_tx_octets) {
|
if (lr->max_rx_octets > _radio.conn_curr->default_tx_octets) {
|
||||||
eff_tx_octets = _radio.conn_curr->sug_tx_octets;
|
eff_tx_octets = _radio.conn_curr->default_tx_octets;
|
||||||
} else {
|
} else {
|
||||||
eff_tx_octets = lr->max_rx_octets;
|
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 */
|
/* wait for resp before completing the procedure */
|
||||||
conn->llcp_length.state = LLCP_LENGTH_STATE_ACK_WAIT;
|
conn->llcp_length.state = LLCP_LENGTH_STATE_ACK_WAIT;
|
||||||
|
|
||||||
/* set the suggested tx octets to requested value */
|
/* set the default tx octets to requested value */
|
||||||
conn->sug_tx_octets = conn->llcp_length.tx_octets;
|
conn->default_tx_octets = conn->llcp_length.tx_octets;
|
||||||
|
|
||||||
/* place the length req packet as next in tx queue */
|
/* place the length req packet as next in tx queue */
|
||||||
pdu_ctrl_tx = (struct pdu_data *) node_tx->pdu_data;
|
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;
|
&pdu_ctrl_tx->payload.llctrl.ctrldata.length_req;
|
||||||
lr->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX;
|
lr->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX;
|
||||||
lr->max_rx_time = ((RADIO_LL_LENGTH_OCTETS_RX_MAX + 14) << 3);
|
lr->max_rx_time = ((RADIO_LL_LENGTH_OCTETS_RX_MAX + 14) << 3);
|
||||||
lr->max_tx_octets = conn->sug_tx_octets;
|
lr->max_tx_octets = conn->default_tx_octets;
|
||||||
lr->max_tx_time = ((conn->sug_tx_octets + 14) << 3);
|
lr->max_tx_time = ((conn->default_tx_octets + 14) << 3);
|
||||||
|
|
||||||
ctrl_tx_enqueue(conn, node_tx);
|
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->event_counter = 0;
|
||||||
conn->latency_prepare = 0;
|
conn->latency_prepare = 0;
|
||||||
conn->latency_event = 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_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
||||||
conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
||||||
conn->role.slave.role = 1;
|
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_prepare = 0;
|
||||||
conn->latency_event = 0;
|
conn->latency_event = 0;
|
||||||
conn->latency = _radio.observer.conn_latency;
|
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_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
||||||
conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
conn->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
|
||||||
conn->role.master.role = 0;
|
conn->role.master.role = 0;
|
||||||
|
@ -7315,6 +7323,35 @@ uint32_t radio_length_req_send(uint16_t handle, uint16_t tx_octets)
|
||||||
return 0;
|
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)
|
static uint8_t tx_cmplt_get(uint16_t *handle, uint8_t *first, uint8_t last)
|
||||||
{
|
{
|
||||||
uint8_t _first;
|
uint8_t _first;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#ifndef _CTRL_H_
|
#ifndef _CTRL_H_
|
||||||
#define _CTRL_H_
|
#define _CTRL_H_
|
||||||
|
|
||||||
|
#include <bluetooth/hci.h>
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Zephyr Kconfig defined
|
* Zephyr Kconfig defined
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
@ -81,11 +83,13 @@
|
||||||
#define RADIO_BLE_VERSION_NUMBER (0x08)
|
#define RADIO_BLE_VERSION_NUMBER (0x08)
|
||||||
#define RADIO_BLE_COMPANY_ID (0xFFFF)
|
#define RADIO_BLE_COMPANY_ID (0xFFFF)
|
||||||
#define RADIO_BLE_SUB_VERSION_NUMBER (0xFFFF)
|
#define RADIO_BLE_SUB_VERSION_NUMBER (0xFFFF)
|
||||||
#define RADIO_BLE_FEATURES (0x1F) /* LE Ping, Slave Initiated
|
|
||||||
* Feature request, Extended
|
#define RADIO_BLE_FEATURES (BT_LE_FEAT_BIT_ENC | \
|
||||||
* Reject Indication, Conn Param
|
BT_LE_FEAT_BIT_CONN_PARAM_REQ | \
|
||||||
* Req Procedure, LE encryption.
|
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)
|
* 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_version_ind_send(uint16_t handle);
|
||||||
uint32_t radio_terminate_ind_send(uint16_t handle, uint8_t reason);
|
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);
|
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,
|
uint8_t radio_rx_get(struct radio_pdu_node_rx **radio_pdu_node_rx,
|
||||||
uint16_t *handle);
|
uint16_t *handle);
|
||||||
void radio_rx_dequeue(void);
|
void radio_rx_dequeue(void);
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct connection {
|
||||||
uint16_t latency;
|
uint16_t latency;
|
||||||
uint16_t latency_prepare;
|
uint16_t latency_prepare;
|
||||||
uint16_t latency_event;
|
uint16_t latency_event;
|
||||||
uint16_t sug_tx_octets;
|
uint16_t default_tx_octets;
|
||||||
uint16_t max_tx_octets;
|
uint16_t max_tx_octets;
|
||||||
uint16_t max_rx_octets;
|
uint16_t max_rx_octets;
|
||||||
uint16_t supervision_reload;
|
uint16_t supervision_reload;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue