Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba2a9506 authored by Alexander Aring's avatar Alexander Aring Committed by Marcel Holtmann
Browse files

nl802154: introduce support for cca settings



This patch adds support for setting cca parameters via nl802154.

Signed-off-by: default avatarAlexander Aring <alex.aring@gmail.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 7fe9a388
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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,
+1 −1
Original line number Diff line number Diff line
@@ -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,
+43 −3
Original line number Diff line number Diff line
@@ -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,
+7 −0
Original line number Diff line number Diff line
@@ -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)
+21 −0
Original line number Diff line number Diff line
@@ -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,