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