]>
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 | ||
55 | static int handle_hwsim_getps(struct nl80211_state *state, struct nl_cb *cb, | |
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 | ||
69 | nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, | |
70 | print_hwsim_ps_handler, NULL); | |
71 | return 0; | |
72 | nla_put_failure: | |
73 | return -ENOBUFS; | |
74 | } | |
75 | COMMAND(hwsim, getps, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_getps, ""); | |
76 | ||
77 | static int handle_hwsim_setps(struct nl80211_state *state, struct nl_cb *cb, | |
05514f95 JB |
78 | struct nl_msg *msg, int argc, char **argv, |
79 | enum id_input id) | |
a1b3258b JB |
80 | { |
81 | struct nlattr *tmdata; | |
82 | __u32 ps; | |
83 | char *end; | |
84 | ||
85 | if (argc != 1) | |
86 | return 1; | |
87 | ||
88 | ps = strtoul(argv[0], &end, 0); | |
89 | if (*end) | |
90 | return 1; | |
91 | ||
92 | tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA); | |
93 | if (!tmdata) | |
94 | goto nla_put_failure; | |
95 | ||
96 | NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_SET_PS); | |
97 | NLA_PUT_U32(msg, HWSIM_TM_ATTR_PS, ps); | |
98 | ||
99 | nla_nest_end(msg, tmdata); | |
100 | ||
101 | nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, | |
102 | print_hwsim_ps_handler, NULL); | |
103 | return 0; | |
104 | nla_put_failure: | |
105 | return -ENOBUFS; | |
106 | } | |
107 | COMMAND(hwsim, setps, "<value>", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_setps, ""); | |
108 | ||
109 | static int handle_hwsim_stop_queues(struct nl80211_state *state, struct nl_cb *cb, | |
05514f95 JB |
110 | struct nl_msg *msg, int argc, char **argv, |
111 | enum id_input id) | |
a1b3258b JB |
112 | { |
113 | struct nlattr *tmdata; | |
114 | ||
115 | if (argc != 0) | |
116 | return 1; | |
117 | ||
118 | tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA); | |
119 | if (!tmdata) | |
120 | goto nla_put_failure; | |
121 | ||
122 | NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_STOP_QUEUES); | |
123 | ||
124 | nla_nest_end(msg, tmdata); | |
125 | return 0; | |
126 | nla_put_failure: | |
127 | return -ENOBUFS; | |
128 | } | |
129 | COMMAND(hwsim, stopqueues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_stop_queues, ""); | |
130 | ||
131 | static int handle_hwsim_wake_queues(struct nl80211_state *state, struct nl_cb *cb, | |
05514f95 JB |
132 | struct nl_msg *msg, int argc, char **argv, |
133 | enum id_input id) | |
a1b3258b JB |
134 | { |
135 | struct nlattr *tmdata; | |
136 | ||
137 | if (argc != 0) | |
138 | return 1; | |
139 | ||
140 | tmdata = nla_nest_start(msg, NL80211_ATTR_TESTDATA); | |
141 | if (!tmdata) | |
142 | goto nla_put_failure; | |
143 | ||
144 | NLA_PUT_U32(msg, HWSIM_TM_ATTR_CMD, HWSIM_TM_CMD_WAKE_QUEUES); | |
145 | ||
146 | nla_nest_end(msg, tmdata); | |
147 | return 0; | |
148 | nla_put_failure: | |
149 | return -ENOBUFS; | |
150 | } | |
151 | COMMAND(hwsim, wakequeues, "", NL80211_CMD_TESTMODE, 0, CIB_PHY, handle_hwsim_wake_queues, ""); |