Bluetooth: controller: Fix supported cmds and states

Properly use the role and feature Kconfig variables to populate both the
supported commands and the supported states in the controller.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2017-06-23 12:18:21 +02:00 committed by Johan Hedberg
commit 7df0ab780d

View file

@ -89,6 +89,7 @@ static void *cmd_complete(struct net_buf **buf, u8_t plen)
return net_buf_add(*buf, plen);
}
#if defined(CONFIG_BLUETOOTH_CONN)
static struct net_buf *cmd_status(u8_t status)
{
struct bt_hci_evt_cmd_status *cs;
@ -104,6 +105,7 @@ static struct net_buf *cmd_status(u8_t status)
return buf;
}
#endif
static void *meta_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
{
@ -116,6 +118,7 @@ static void *meta_evt(struct net_buf *buf, u8_t subevt, u8_t melen)
return net_buf_add(buf, melen);
}
#if defined(CONFIG_BLUETOOTH_CONN)
static void disconnect(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_disconnect *cmd = (void *)buf->data;
@ -139,17 +142,20 @@ static void read_remote_ver_info(struct net_buf *buf, struct net_buf **evt)
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
#endif /* CONFIG_BLUETOOTH_CONN */
static int link_control_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt)
{
switch (ocf) {
#if defined(CONFIG_BLUETOOTH_CONN)
case BT_OCF(BT_HCI_OP_DISCONNECT):
disconnect(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_READ_REMOTE_VERSION_INFO):
read_remote_ver_info(cmd, evt);
break;
#endif /* CONFIG_BLUETOOTH_CONN */
default:
return -EINVAL;
}
@ -347,56 +353,83 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
rp->status = 0x00;
memset(&rp->commands[0], 0, sizeof(rp->commands));
/* Disconnect. */
rp->commands[0] = (1 << 5);
/* Set Event Mask, and Reset. */
rp->commands[5] = (1 << 6) | (1 << 7);
rp->commands[5] |= BIT(6) | BIT(7);
#if defined(CONFIG_BLUETOOTH_HCI_ACL_FLOW_CONTROL)
/* Set FC, Host Buffer Size and Host Num Completed */
rp->commands[10] = (1 << 5) | (1 << 6) | (1 << 7);
rp->commands[10] |= BIT(5) | BIT(6) | BIT(7);
#endif
/* Read Local Version Info, Read Local Supported Features. */
rp->commands[14] = (1 << 3) | (1 << 5);
rp->commands[14] |= BIT(3) | BIT(5);
/* Read BD ADDR. */
rp->commands[15] = (1 << 1);
/* All LE commands in this octet. */
rp->commands[25] = 0xF7;
/* All LE commands in this octet. */
rp->commands[26] = 0xFF;
/* All LE commands in this octet,
rp->commands[15] |= BIT(1);
/* LE Set Event Mask, LE Read Buffer Size, LE Read Local Supp Feats,
* Set Random Addr
*/
rp->commands[27] = 0xFF;
/* LE Start Encryption, LE Long Term Key Req Reply,
* LE Long Term Key Req Neg Reply. and
* LE Read Supported States.
*/
rp->commands[28] = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
rp->commands[25] |= BIT(0) | BIT(1) | BIT(2) | BIT(4);
/* LE Read WL Size, LE Clear WL */
rp->commands[26] |= BIT(6) | BIT(7);
/* LE Add Dev to WL, LE Remove Dev from WL */
rp->commands[27] |= BIT(0) | BIT(1);
/* LE Encrypt, LE Rand */
rp->commands[27] |= BIT(6) | BIT(7);
/* LE Read Supported States */
rp->commands[28] |= BIT(3);
#if defined(CONFIG_BLUETOOTH_BROADCASTER)
/* LE Set Adv Params, LE Read Adv Channel TX Power, LE Set Adv Data */
rp->commands[25] |= BIT(5) | BIT(6) | BIT(7);
/* LE Set Scan Response Data, LE Set Adv Enable */
rp->commands[26] |= BIT(0) | BIT(1);
#endif
#if defined(CONFIG_BLUETOOTH_OBSERVER)
/* LE Set Scan Params, LE Set Scan Enable */
rp->commands[26] |= BIT(2) | BIT(3);
#endif
#if defined(CONFIG_BLUETOOTH_CENTRAL)
/* LE Create Connection, LE Create Connection Cancel */
rp->commands[26] |= BIT(4) | BIT(5);
/* Set Host Channel Classification */
rp->commands[27] |= BIT(3);
#if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_ENC)
/* LE Start Encryption */
rp->commands[28] |= BIT(0);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_LE_ENC */
#endif /* CONFIG_BLUETOOTH_CENTRAL */
#if defined(CONFIG_BLUETOOTH_PERIPHERAL)
#if defined(CONFIG_BLUETOOTH_CONTROLLER_LE_ENC)
/* LE LTK Request Reply, LE LTK Request Negative Reply */
rp->commands[28] |= BIT(1) | BIT(2);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_LE_ENC */
#endif
#if defined(CONFIG_BLUETOOTH_CONN)
/* Disconnect. */
rp->commands[0] |= BIT(5);
/* LE Connection Update, LE Read Remote Features */
rp->commands[27] |= BIT(2) | BIT(5);
/* LE Remote Conn Param Req and Neg Reply */
rp->commands[33] = (1 << 4) | (1 << 5);
rp->commands[33] |= BIT(4) | BIT(5);
#endif /* CONFIG_BLUETOOTH_CONN */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
/* LE resolving list commands, LE Read Peer RPA */
rp->commands[34] |= (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7);
rp->commands[34] |= BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7);
/* LE Read Local RPA, LE Set AR Enable, Set RPA Timeout */
rp->commands[35] |= (1 << 0) | (1 << 1) | (1 << 2);
rp->commands[35] |= BIT(0) | BIT(1) | BIT(2);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH)
/* LE Set Data Length, and LE Read Suggested Data Length. */
rp->commands[33] |= (1 << 6) | (1 << 7);
rp->commands[33] |= BIT(6) | BIT(7);
/* LE Write Suggested Data Length. */
rp->commands[34] |= (1 << 0);
rp->commands[34] |= BIT(0);
/* LE Read Maximum Data Length. */
rp->commands[35] |= BIT(3);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */
#if defined(CONFIG_BLUETOOTH_HCI_RAW) && defined(CONFIG_BLUETOOTH_TINYCRYPT_ECC)
/* LE Read Local P256 Public Key and LE Generate DH Key*/
rp->commands[34] |= (1 << 1) | (1 << 2);
rp->commands[34] |= BIT(1) | BIT(2);
#endif
#if defined(CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH)
/* LE Read Maximum Data Length. */
rp->commands[35] |= (1 << 3);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */
}
static void read_local_features(struct net_buf *buf, struct net_buf **evt)
@ -566,16 +599,59 @@ static void le_rand(struct net_buf *buf, struct net_buf **evt)
static void le_read_supp_states(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_rp_le_read_supp_states *rp;
u64_t states = 0;
rp = cmd_complete(evt, sizeof(*rp));
rp->status = 0x00;
#define ST_ADV (BIT64(0) | BIT64(1) | BIT64(8) | BIT64(9) | BIT64(12) | \
BIT64(13) | BIT64(16) | BIT64(17) | BIT64(18) | BIT64(19) | \
BIT64(20) | BIT64(21))
#define ST_SCA (BIT64(4) | BIT64(5) | BIT64(8) | BIT64(9) | BIT64(10) | \
BIT64(11) | BIT64(12) | BIT64(13) | BIT64(14) | BIT64(15) | \
BIT64(22) | BIT64(23) | BIT64(24) | BIT64(25) | BIT64(26) | \
BIT64(27) | BIT64(30) | BIT64(31))
#define ST_SLA (BIT64(2) | BIT64(3) | BIT64(7) | BIT64(10) | BIT64(11) | \
BIT64(14) | BIT64(15) | BIT64(20) | BIT64(21) | BIT64(26) | \
BIT64(27) | BIT64(29) | BIT64(30) | BIT64(31) | BIT64(32) | \
BIT64(33) | BIT64(34) | BIT64(35) | BIT64(36) | BIT64(37) | \
BIT64(38) | BIT64(39) | BIT64(40) | BIT64(41))
#define ST_MAS (BIT64(6) | BIT64(16) | BIT64(17) | BIT64(18) | BIT64(19) | \
BIT64(22) | BIT64(23) | BIT64(24) | BIT64(25) | BIT64(28) | \
BIT64(32) | BIT64(33) | BIT64(34) | BIT64(35) | BIT64(36) | \
BIT64(37) | BIT64(41))
#if defined(CONFIG_BLUETOOTH_BROADCASTER)
states |= ST_ADV;
#else
states &= ~ST_ADV;
#endif
#if defined(CONFIG_BLUETOOTH_OBSERVER)
states |= ST_SCA;
#else
states &= ~ST_SCA;
#endif
#if defined(CONFIG_BLUETOOTH_PERIPHERAL)
states |= ST_SLA;
#else
states &= ~ST_SLA;
#endif
#if defined(CONFIG_BLUETOOTH_CENTRAL)
states |= ST_MAS;
#else
states &= ~ST_MAS;
#endif
/* All states and combinations supported except:
* Initiating State + Passive Scanning
* Initiating State + Active Scanning
*/
/*@todo: conditionally disable states based on Kconfig variables */
sys_put_le64(0x000003ffff3fffff, rp->le_states);
states &= ~(BIT64(22) | BIT64(23));
BT_DBG("states: 0x%08x%08x", (u32_t)(states >> 32),
(u32_t)(states & 0xffffffff));
sys_put_le64(states, rp->le_states);
}
#if defined(CONFIG_BLUETOOTH_BROADCASTER)
@ -923,6 +999,76 @@ static void le_read_max_data_len(struct net_buf *buf, struct net_buf **evt)
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PHY)
static void le_read_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_read_phy *cmd = (void *) buf->data;
struct bt_hci_rp_le_read_phy *rp;
u16_t handle;
u32_t status;
handle = sys_le16_to_cpu(cmd->handle);
rp = cmd_complete(evt, sizeof(*rp));
status = ll_phy_get(handle, &rp->tx_phy, &rp->rx_phy);
rp->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
rp->handle = sys_cpu_to_le16(handle);
rp->tx_phy = find_lsb_set(rp->tx_phy);
rp->rx_phy = find_lsb_set(rp->rx_phy);
}
static void le_set_default_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_default_phy *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
cmd->tx_phys = 0x07;
}
if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
cmd->rx_phys = 0x07;
}
status = ll_phy_default_set(cmd->tx_phys, cmd->rx_phys);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_INVALID_LL_PARAM;
}
static void le_set_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_phy *cmd = (void *)buf->data;
u32_t status;
u16_t handle;
u16_t phy_opts;
handle = sys_le16_to_cpu(cmd->handle);
phy_opts = sys_le16_to_cpu(cmd->phy_opts);
if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
cmd->tx_phys = 0x07;
}
if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
cmd->rx_phys = 0x07;
}
if (phy_opts & 0x03) {
phy_opts -= 1;
phy_opts &= 1;
} else {
phy_opts = 0;
}
status = ll_phy_req_send(handle, cmd->tx_phys, phy_opts,
cmd->rx_phys);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PHY */
#endif /* CONFIG_BLUETOOTH_CONN */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
static void le_add_dev_to_rl(struct net_buf *buf, struct net_buf **evt)
{
@ -1013,76 +1159,6 @@ static void le_set_rpa_timeout(struct net_buf *buf, struct net_buf **evt)
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PHY)
static void le_read_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_read_phy *cmd = (void *) buf->data;
struct bt_hci_rp_le_read_phy *rp;
u16_t handle;
u32_t status;
handle = sys_le16_to_cpu(cmd->handle);
rp = cmd_complete(evt, sizeof(*rp));
status = ll_phy_get(handle, &rp->tx_phy, &rp->rx_phy);
rp->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
rp->handle = sys_cpu_to_le16(handle);
rp->tx_phy = find_lsb_set(rp->tx_phy);
rp->rx_phy = find_lsb_set(rp->rx_phy);
}
static void le_set_default_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_default_phy *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
cmd->tx_phys = 0x07;
}
if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
cmd->rx_phys = 0x07;
}
status = ll_phy_default_set(cmd->tx_phys, cmd->rx_phys);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = (!status) ? 0x00 : BT_HCI_ERR_INVALID_LL_PARAM;
}
static void le_set_phy(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_phy *cmd = (void *)buf->data;
u32_t status;
u16_t handle;
u16_t phy_opts;
handle = sys_le16_to_cpu(cmd->handle);
phy_opts = sys_le16_to_cpu(cmd->phy_opts);
if (cmd->all_phys & BT_HCI_LE_PHY_TX_ANY) {
cmd->tx_phys = 0x07;
}
if (cmd->all_phys & BT_HCI_LE_PHY_RX_ANY) {
cmd->rx_phys = 0x07;
}
if (phy_opts & 0x03) {
phy_opts -= 1;
phy_opts &= 1;
} else {
phy_opts = 0;
}
status = ll_phy_req_send(handle, cmd->tx_phys, phy_opts,
cmd->rx_phys);
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PHY */
#endif /* CONFIG_BLUETOOTH_CONN */
static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt)
{
@ -1230,6 +1306,21 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PHY)
case BT_OCF(BT_HCI_OP_LE_READ_PHY):
le_read_phy(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_DEFAULT_PHY):
le_set_default_phy(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_PHY):
le_set_phy(cmd, evt);
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PHY */
#endif /* CONFIG_BLUETOOTH_CONN */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
case BT_OCF(BT_HCI_OP_LE_ADD_DEV_TO_RL):
le_add_dev_to_rl(cmd, evt);
@ -1257,20 +1348,6 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PHY)
case BT_OCF(BT_HCI_OP_LE_READ_PHY):
le_read_phy(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_DEFAULT_PHY):
le_set_default_phy(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_PHY):
le_set_phy(cmd, evt);
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PHY */
#endif /* CONFIG_BLUETOOTH_CONN */
default:
return -EINVAL;