You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
3.6 KiB
152 lines
3.6 KiB
#include <net/if.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#include <netlink/genl/genl.h>
|
|
#include <netlink/genl/family.h>
|
|
#include <netlink/genl/ctrl.h>
|
|
#include <netlink/msg.h>
|
|
#include <netlink/attr.h>
|
|
|
|
#include "nl80211.h"
|
|
#include "iw.h"
|
|
|
|
/* These enums need to be kept in sync with the kernel */
|
|
enum hwsim_testmode_attr {
|
|
__HWSIM_TM_ATTR_INVALID = 0,
|
|
HWSIM_TM_ATTR_CMD = 1,
|
|
HWSIM_TM_ATTR_PS = 2,
|
|
|
|
/* keep last */
|
|
__HWSIM_TM_ATTR_AFTER_LAST,
|
|
HWSIM_TM_ATTR_MAX = __HWSIM_TM_ATTR_AFTER_LAST - 1
|
|
};
|
|
|
|
enum hwsim_testmode_cmd {
|
|
HWSIM_TM_CMD_SET_PS = 0,
|
|
HWSIM_TM_CMD_GET_PS = 1,
|
|
HWSIM_TM_CMD_STOP_QUEUES = 2,
|
|
HWSIM_TM_CMD_WAKE_QUEUES = 3,
|
|
};
|
|
|
|
|
|
SECTION(hwsim);
|
|
|
|
static int print_hwsim_ps_handler(struct nl_msg *msg, void *arg)
|
|
{
|
|
struct nlattr *attrs[NL80211_ATTR_MAX + 1];
|
|
struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
|
|
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
|
|
|
|
nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
|
|
genlmsg_attrlen(gnlh, 0), NULL);
|
|
|
|
if (!attrs[NL80211_ATTR_TESTDATA])
|
|
return NL_SKIP;
|
|
|
|
nla_parse(tb, HWSIM_TM_ATTR_MAX, nla_data(attrs[NL80211_ATTR_TESTDATA]),
|
|
nla_len(attrs[NL80211_ATTR_TESTDATA]), NULL);
|
|
|
|
printf("HWSIM PS: %d\n", nla_get_u32(tb[HWSIM_TM_ATTR_PS]));
|
|
|
|
return NL_SKIP;
|
|
}
|
|
|
|
static int handle_hwsim_getps(struct nl80211_state *state, struct nl_cb *cb,
|
|
struct nl_msg *msg, int argc, char **argv,
|
|
enum id_input id)
|
|
{
|
|
struct nlattr *tmdata;
|
|
|
|
tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
|
|
if (!tmdata)
|
|
goto nla_put_failure;
|
|
|
|
NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_GET_PS);
|
|
|
|
nla_nest_end(msg, tmdata);
|
|
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
|
|
print_hwsim_ps_handler, NULL);
|
|
return 0;
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
}
|
|
COMMAND(hwsim, getps, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_getps, "");
|
|
|
|
static int handle_hwsim_setps(struct nl80211_state *state, struct nl_cb *cb,
|
|
struct nl_msg *msg, int argc, char **argv,
|
|
enum id_input id)
|
|
{
|
|
struct nlattr *tmdata;
|
|
__u32 ps;
|
|
char *end;
|
|
|
|
if (argc != 1)
|
|
return 1;
|
|
|
|
ps = strtoul(argv[0], &end, 0);
|
|
if (*end)
|
|
return 1;
|
|
|
|
tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
|
|
if (!tmdata)
|
|
goto nla_put_failure;
|
|
|
|
NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_SET_PS);
|
|
NLA_PUT_U32(msg, HWSIM_TM_ATTR_PS, ps);
|
|
|
|
nla_nest_end(msg, tmdata);
|
|
|
|
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
|
|
print_hwsim_ps_handler, NULL);
|
|
return 0;
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
}
|
|
COMMAND(hwsim, setps, "<value>", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_setps, "");
|
|
|
|
static int handle_hwsim_stop_queues(struct nl80211_state *state, struct nl_cb *cb,
|
|
struct nl_msg *msg, int argc, char **argv,
|
|
enum id_input id)
|
|
{
|
|
struct nlattr *tmdata;
|
|
|
|
if (argc != 0)
|
|
return 1;
|
|
|
|
tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
|
|
if (!tmdata)
|
|
goto nla_put_failure;
|
|
|
|
NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_STOP_QUEUES);
|
|
|
|
nla_nest_end(msg, tmdata);
|
|
return 0;
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
}
|
|
COMMAND(hwsim, stopqueues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_stop_queues, "");
|
|
|
|
static int handle_hwsim_wake_queues(struct nl80211_state *state, struct nl_cb *cb,
|
|
struct nl_msg *msg, int argc, char **argv,
|
|
enum id_input id)
|
|
{
|
|
struct nlattr *tmdata;
|
|
|
|
if (argc != 0)
|
|
return 1;
|
|
|
|
tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
|
|
if (!tmdata)
|
|
goto nla_put_failure;
|
|
|
|
NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_WAKE_QUEUES);
|
|
|
|
nla_nest_end(msg, tmdata);
|
|
return 0;
|
|
nla_put_failure:
|
|
return -ENOBUFS;
|
|
}
|
|
COMMAND(hwsim, wakequeues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_wake_queues, "");
|