From a1b3258beacd210012ba668e9e92e6586a4f72cb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Jul 2012 08:50:00 +0200 Subject: [PATCH] add (optional) hwsim code As an example, the hwsim code was useful, but for normal distros it's not. Allow developers to build hwsim code into the iw binary with "make HWSIM=y". --- Makefile | 9 ++-- hwsim.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 hwsim.c diff --git a/Makefile b/Makefile index ac238be..9cf8a8e 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ OBJS = iw.o genl.o event.o info.o phy.o \ reason.o status.o connect.o link.o offch.o ps.o cqm.o \ bitrate.o wowlan.o roc.o OBJS += sections.o + +OBJS-$(HWSIM) += hwsim.o + ALL = iw NL3xFOUND := $(shell $(PKG_CONFIG) --atleast-version=3.2 libnl-3.0 && echo Y) @@ -85,7 +88,7 @@ endif all: $(ALL) -VERSION_OBJS := $(filter-out version.o, $(OBJS)) +VERSION_OBJS := $(filter-out version.o, $(OBJS) $(OBJS-y)) version.c: version.sh $(patsubst %.o,%.c,$(VERSION_OBJS)) nl80211.h iw.h Makefile \ $(wildcard .git/index .git/refs/tags) @@ -96,9 +99,9 @@ version.c: version.sh $(patsubst %.o,%.c,$(VERSION_OBJS)) nl80211.h iw.h Makefil @$(NQ) ' CC ' $@ $(Q)$(CC) $(CFLAGS) -c -o $@ $< -iw: $(OBJS) +iw: $(OBJS) $(OBJS-y) @$(NQ) ' CC ' iw - $(Q)$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o iw + $(Q)$(CC) $(LDFLAGS) $(OBJS) $(OBJS-y) $(LIBS) -o iw check: $(Q)$(MAKE) all CC="REAL_CC=$(CC) CHECK=\"sparse -Wall\" cgcc" diff --git a/hwsim.c b/hwsim.c new file mode 100644 index 0000000..188c1cb --- /dev/null +++ b/hwsim.c @@ -0,0 +1,147 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#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) +{ + 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) +{ + 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, "", 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) +{ + 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) +{ + 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, ""); -- 2.47.2