nl802154: introduce support for cca settings
This patch adds support for setting cca parameters via nl802154. Signed-off-by: Alexander Aring <alex.aring@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
7fe9a3882b
commit
ba2a9506a7
|
@ -25,6 +25,7 @@
|
|||
#include <net/nl802154.h>
|
||||
|
||||
struct wpan_phy;
|
||||
struct wpan_phy_cca;
|
||||
|
||||
struct cfg802154_ops {
|
||||
struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
|
||||
|
@ -39,6 +40,8 @@ struct cfg802154_ops {
|
|||
int (*del_virtual_intf)(struct wpan_phy *wpan_phy,
|
||||
struct wpan_dev *wpan_dev);
|
||||
int (*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
|
||||
int (*set_cca_mode)(struct wpan_phy *wpan_phy,
|
||||
const struct wpan_phy_cca *cca);
|
||||
int (*set_pan_id)(struct wpan_phy *wpan_phy,
|
||||
struct wpan_dev *wpan_dev, __le16 pan_id);
|
||||
int (*set_short_addr)(struct wpan_phy *wpan_phy,
|
||||
|
|
|
@ -82,7 +82,7 @@ enum nl802154_attrs {
|
|||
NL802154_ATTR_TX_POWER,
|
||||
|
||||
NL802154_ATTR_CCA_MODE,
|
||||
NL802154_ATTR_CCA_MODE3_AND,
|
||||
NL802154_ATTR_CCA_OPT,
|
||||
NL802154_ATTR_CCA_ED_LEVEL,
|
||||
|
||||
NL802154_ATTR_MAX_FRAME_RETRIES,
|
||||
|
|
|
@ -209,7 +209,8 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
|
|||
|
||||
[NL802154_ATTR_TX_POWER] = { .type = NLA_S8, },
|
||||
|
||||
[NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
|
||||
[NL802154_ATTR_CCA_MODE] = { .type = NLA_U32, },
|
||||
[NL802154_ATTR_CCA_OPT] = { .type = NLA_U32, },
|
||||
|
||||
[NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
|
||||
|
||||
|
@ -290,10 +291,16 @@ static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
|
|||
goto nla_put_failure;
|
||||
|
||||
/* cca mode */
|
||||
if (nla_put_u8(msg, NL802154_ATTR_CCA_MODE,
|
||||
if (nla_put_u32(msg, NL802154_ATTR_CCA_MODE,
|
||||
rdev->wpan_phy.cca.mode))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rdev->wpan_phy.cca.mode == NL802154_CCA_ENERGY_CARRIER) {
|
||||
if (nla_put_u32(msg, NL802154_ATTR_CCA_OPT,
|
||||
rdev->wpan_phy.cca.opt))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put_s8(msg, NL802154_ATTR_TX_POWER,
|
||||
rdev->wpan_phy.transmit_power))
|
||||
goto nla_put_failure;
|
||||
|
@ -622,6 +629,31 @@ static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
|
|||
return rdev_set_channel(rdev, page, channel);
|
||||
}
|
||||
|
||||
static int nl802154_set_cca_mode(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg802154_registered_device *rdev = info->user_ptr[0];
|
||||
struct wpan_phy_cca cca;
|
||||
|
||||
if (!info->attrs[NL802154_ATTR_CCA_MODE])
|
||||
return -EINVAL;
|
||||
|
||||
cca.mode = nla_get_u32(info->attrs[NL802154_ATTR_CCA_MODE]);
|
||||
/* checking 802.15.4 constraints */
|
||||
if (cca.mode < NL802154_CCA_ENERGY || cca.mode > NL802154_CCA_ATTR_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (cca.mode == NL802154_CCA_ENERGY_CARRIER) {
|
||||
if (!info->attrs[NL802154_ATTR_CCA_OPT])
|
||||
return -EINVAL;
|
||||
|
||||
cca.opt = nla_get_u32(info->attrs[NL802154_ATTR_CCA_OPT]);
|
||||
if (cca.opt > NL802154_CCA_OPT_ATTR_MAX)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rdev_set_cca_mode(rdev, &cca);
|
||||
}
|
||||
|
||||
static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg802154_registered_device *rdev = info->user_ptr[0];
|
||||
|
@ -894,6 +926,14 @@ static const struct genl_ops nl802154_ops[] = {
|
|||
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
|
||||
NL802154_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL802154_CMD_SET_CCA_MODE,
|
||||
.doit = nl802154_set_cca_mode,
|
||||
.policy = nl802154_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
|
||||
NL802154_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL802154_CMD_SET_PAN_ID,
|
||||
.doit = nl802154_set_pan_id,
|
||||
|
|
|
@ -41,6 +41,13 @@ rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel)
|
|||
return rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
|
||||
}
|
||||
|
||||
static inline int
|
||||
rdev_set_cca_mode(struct cfg802154_registered_device *rdev,
|
||||
const struct wpan_phy_cca *cca)
|
||||
{
|
||||
return rdev->ops->set_cca_mode(&rdev->wpan_phy, cca);
|
||||
}
|
||||
|
||||
static inline int
|
||||
rdev_set_pan_id(struct cfg802154_registered_device *rdev,
|
||||
struct wpan_dev *wpan_dev, __le16 pan_id)
|
||||
|
|
|
@ -86,6 +86,26 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee802154_set_cca_mode(struct wpan_phy *wpan_phy,
|
||||
const struct wpan_phy_cca *cca)
|
||||
{
|
||||
struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
|
||||
int ret;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* check if phy support this setting */
|
||||
if (!(local->hw.flags & IEEE802154_HW_CCA_MODE))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = drv_set_cca_mode(local, cca);
|
||||
if (!ret)
|
||||
wpan_phy->cca = *cca;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
|
||||
__le16 pan_id)
|
||||
|
@ -201,6 +221,7 @@ const struct cfg802154_ops mac802154_config_ops = {
|
|||
.add_virtual_intf = ieee802154_add_iface,
|
||||
.del_virtual_intf = ieee802154_del_iface,
|
||||
.set_channel = ieee802154_set_channel,
|
||||
.set_cca_mode = ieee802154_set_cca_mode,
|
||||
.set_pan_id = ieee802154_set_pan_id,
|
||||
.set_short_addr = ieee802154_set_short_addr,
|
||||
.set_backoff_exponent = ieee802154_set_backoff_exponent,
|
||||
|
|
Loading…
Reference in New Issue