xref: /aosp_15_r20/external/iw/hwsim.c (revision 92022041c981f431db0b590d0c3272306d0ea2a2)
1*92022041SSam Saccone #include <errno.h>
2*92022041SSam Saccone #include <string.h>
3*92022041SSam Saccone 
4*92022041SSam Saccone #include <netlink/genl/genl.h>
5*92022041SSam Saccone #include <netlink/genl/family.h>
6*92022041SSam Saccone #include <netlink/genl/ctrl.h>
7*92022041SSam Saccone #include <netlink/msg.h>
8*92022041SSam Saccone #include <netlink/attr.h>
9*92022041SSam Saccone 
10*92022041SSam Saccone #include "nl80211.h"
11*92022041SSam Saccone #include "iw.h"
12*92022041SSam Saccone 
13*92022041SSam Saccone /* These enums need to be kept in sync with the kernel */
14*92022041SSam Saccone enum hwsim_testmode_attr {
15*92022041SSam Saccone 	__HWSIM_TM_ATTR_INVALID	= 0,
16*92022041SSam Saccone 	HWSIM_TM_ATTR_CMD	= 1,
17*92022041SSam Saccone 	HWSIM_TM_ATTR_PS	= 2,
18*92022041SSam Saccone 
19*92022041SSam Saccone 	/* keep last */
20*92022041SSam Saccone 	__HWSIM_TM_ATTR_AFTER_LAST,
21*92022041SSam Saccone 	HWSIM_TM_ATTR_MAX	= __HWSIM_TM_ATTR_AFTER_LAST - 1
22*92022041SSam Saccone };
23*92022041SSam Saccone 
24*92022041SSam Saccone enum hwsim_testmode_cmd {
25*92022041SSam Saccone 	HWSIM_TM_CMD_SET_PS		= 0,
26*92022041SSam Saccone 	HWSIM_TM_CMD_GET_PS		= 1,
27*92022041SSam Saccone 	HWSIM_TM_CMD_STOP_QUEUES	= 2,
28*92022041SSam Saccone 	HWSIM_TM_CMD_WAKE_QUEUES	= 3,
29*92022041SSam Saccone };
30*92022041SSam Saccone 
31*92022041SSam Saccone 
32*92022041SSam Saccone SECTION(hwsim);
33*92022041SSam Saccone 
print_hwsim_ps_handler(struct nl_msg * msg,void * arg)34*92022041SSam Saccone static int print_hwsim_ps_handler(struct nl_msg *msg, void *arg)
35*92022041SSam Saccone {
36*92022041SSam Saccone 	struct nlattr *attrs[NL80211_ATTR_MAX + 1];
37*92022041SSam Saccone 	struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1];
38*92022041SSam Saccone 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
39*92022041SSam Saccone 
40*92022041SSam Saccone 	nla_parse(attrs, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
41*92022041SSam Saccone 		  genlmsg_attrlen(gnlh, 0), NULL);
42*92022041SSam Saccone 
43*92022041SSam Saccone 	if (!attrs[NL80211_ATTR_TESTDATA])
44*92022041SSam Saccone 		return NL_SKIP;
45*92022041SSam Saccone 
46*92022041SSam Saccone 	nla_parse(tb, HWSIM_TM_ATTR_MAX, nla_data(attrs[NL80211_ATTR_TESTDATA]),
47*92022041SSam Saccone 		  nla_len(attrs[NL80211_ATTR_TESTDATA]), NULL);
48*92022041SSam Saccone 
49*92022041SSam Saccone 	printf("HWSIM PS: %d\n", nla_get_u32(tb[HWSIM_TM_ATTR_PS]));
50*92022041SSam Saccone 
51*92022041SSam Saccone 	return NL_SKIP;
52*92022041SSam Saccone }
53*92022041SSam Saccone 
handle_hwsim_getps(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)54*92022041SSam Saccone static int handle_hwsim_getps(struct nl80211_state *state,
55*92022041SSam Saccone 			      struct nl_msg *msg, int argc, char **argv,
56*92022041SSam Saccone 			      enum id_input id)
57*92022041SSam Saccone {
58*92022041SSam Saccone 	struct nlattr *tmdata;
59*92022041SSam Saccone 
60*92022041SSam Saccone 	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
61*92022041SSam Saccone 	if (!tmdata)
62*92022041SSam Saccone 		goto nla_put_failure;
63*92022041SSam Saccone 
64*92022041SSam Saccone 	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_GET_PS);
65*92022041SSam Saccone 
66*92022041SSam Saccone 	nla_nest_end(msg, tmdata);
67*92022041SSam Saccone 
68*92022041SSam Saccone 	register_handler(print_hwsim_ps_handler, NULL);
69*92022041SSam Saccone 	return 0;
70*92022041SSam Saccone  nla_put_failure:
71*92022041SSam Saccone 	return -ENOBUFS;
72*92022041SSam Saccone }
73*92022041SSam Saccone COMMAND(hwsim, getps, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_getps, "");
74*92022041SSam Saccone 
handle_hwsim_setps(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)75*92022041SSam Saccone static int handle_hwsim_setps(struct nl80211_state *state,
76*92022041SSam Saccone 			      struct nl_msg *msg, int argc, char **argv,
77*92022041SSam Saccone 			      enum id_input id)
78*92022041SSam Saccone {
79*92022041SSam Saccone 	struct nlattr *tmdata;
80*92022041SSam Saccone 	__u32 ps;
81*92022041SSam Saccone 	char *end;
82*92022041SSam Saccone 
83*92022041SSam Saccone 	if (argc != 1)
84*92022041SSam Saccone 		return 1;
85*92022041SSam Saccone 
86*92022041SSam Saccone 	ps = strtoul(argv[0], &end, 0);
87*92022041SSam Saccone 	if (*end)
88*92022041SSam Saccone 		return 1;
89*92022041SSam Saccone 
90*92022041SSam Saccone 	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
91*92022041SSam Saccone 	if (!tmdata)
92*92022041SSam Saccone 		goto nla_put_failure;
93*92022041SSam Saccone 
94*92022041SSam Saccone 	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_SET_PS);
95*92022041SSam Saccone 	NLA_PUT_U32(msg, HWSIM_TM_ATTR_PS, ps);
96*92022041SSam Saccone 
97*92022041SSam Saccone 	nla_nest_end(msg, tmdata);
98*92022041SSam Saccone 
99*92022041SSam Saccone 	register_handler(print_hwsim_ps_handler, NULL);
100*92022041SSam Saccone 	return 0;
101*92022041SSam Saccone  nla_put_failure:
102*92022041SSam Saccone 	return -ENOBUFS;
103*92022041SSam Saccone }
104*92022041SSam Saccone COMMAND(hwsim, setps, "<value>", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_setps, "");
105*92022041SSam Saccone 
handle_hwsim_stop_queues(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)106*92022041SSam Saccone static int handle_hwsim_stop_queues(struct nl80211_state *state,
107*92022041SSam Saccone 				    struct nl_msg *msg, int argc, char **argv,
108*92022041SSam Saccone 				    enum id_input id)
109*92022041SSam Saccone {
110*92022041SSam Saccone 	struct nlattr *tmdata;
111*92022041SSam Saccone 
112*92022041SSam Saccone 	if (argc != 0)
113*92022041SSam Saccone 		return 1;
114*92022041SSam Saccone 
115*92022041SSam Saccone 	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
116*92022041SSam Saccone 	if (!tmdata)
117*92022041SSam Saccone 		goto nla_put_failure;
118*92022041SSam Saccone 
119*92022041SSam Saccone 	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_STOP_QUEUES);
120*92022041SSam Saccone 
121*92022041SSam Saccone 	nla_nest_end(msg, tmdata);
122*92022041SSam Saccone 	return 0;
123*92022041SSam Saccone  nla_put_failure:
124*92022041SSam Saccone 	return -ENOBUFS;
125*92022041SSam Saccone }
126*92022041SSam Saccone COMMAND(hwsim, stopqueues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_stop_queues, "");
127*92022041SSam Saccone 
handle_hwsim_wake_queues(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)128*92022041SSam Saccone static int handle_hwsim_wake_queues(struct nl80211_state *state,
129*92022041SSam Saccone 				    struct nl_msg *msg, int argc, char **argv,
130*92022041SSam Saccone 				    enum id_input id)
131*92022041SSam Saccone {
132*92022041SSam Saccone 	struct nlattr *tmdata;
133*92022041SSam Saccone 
134*92022041SSam Saccone 	if (argc != 0)
135*92022041SSam Saccone 		return 1;
136*92022041SSam Saccone 
137*92022041SSam Saccone 	tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA);
138*92022041SSam Saccone 	if (!tmdata)
139*92022041SSam Saccone 		goto nla_put_failure;
140*92022041SSam Saccone 
141*92022041SSam Saccone 	NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_WAKE_QUEUES);
142*92022041SSam Saccone 
143*92022041SSam Saccone 	nla_nest_end(msg, tmdata);
144*92022041SSam Saccone 	return 0;
145*92022041SSam Saccone  nla_put_failure:
146*92022041SSam Saccone 	return -ENOBUFS;
147*92022041SSam Saccone }
148*92022041SSam Saccone COMMAND(hwsim, wakequeues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_wake_queues, "");
149