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