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)
|
||||
|
||||
/* 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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#ifndef _CTRL_H_
|
||||
#define _CTRL_H_
|
||||
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue