Commit | Line | Data |
---|---|---|
7753f181 DD |
1 | |
2 | #include "wifi_hal.h" | |
3 | #include "common.h" | |
4 | #include "sync.h" | |
5 | ||
6 | class WifiEvent | |
7 | { | |
8 | /* TODO: remove this when nl headers are updated */ | |
9 | static const unsigned NL80211_ATTR_MAX_INTERNAL = 256; | |
10 | private: | |
11 | struct nl_msg *mMsg; | |
12 | struct genlmsghdr *mHeader; | |
13 | struct nlattr *mAttributes[NL80211_ATTR_MAX_INTERNAL + 1]; | |
14 | ||
15 | public: | |
16 | WifiEvent(nl_msg *msg) { | |
17 | mMsg = msg; | |
18 | mHeader = NULL; | |
19 | memset(mAttributes, 0, sizeof(mAttributes)); | |
20 | } | |
21 | ~WifiEvent() { | |
22 | /* don't destroy mMsg; it doesn't belong to us */ | |
23 | } | |
24 | ||
25 | void log(); | |
26 | ||
27 | int parse(); | |
28 | ||
29 | genlmsghdr *header() { | |
30 | return mHeader; | |
31 | } | |
32 | ||
33 | int get_cmd() { | |
34 | return mHeader->cmd; | |
35 | } | |
36 | ||
37 | int get_vendor_id() { | |
38 | return get_u32(NL80211_ATTR_VENDOR_ID); | |
39 | } | |
40 | ||
41 | int get_vendor_subcmd() { | |
42 | return get_u32(NL80211_ATTR_VENDOR_SUBCMD); | |
43 | } | |
44 | ||
45 | void *get_vendor_data() { | |
46 | return get_data(NL80211_ATTR_VENDOR_DATA); | |
47 | } | |
48 | ||
49 | int get_vendor_data_len() { | |
50 | return get_len(NL80211_ATTR_VENDOR_DATA); | |
51 | } | |
52 | ||
53 | const char *get_cmdString(); | |
54 | ||
55 | nlattr ** attributes() { | |
56 | return mAttributes; | |
57 | } | |
58 | ||
59 | nlattr *get_attribute(int attribute) { | |
60 | return mAttributes[attribute]; | |
61 | } | |
62 | ||
63 | uint8_t get_u8(int attribute) { | |
64 | return mAttributes[attribute] ? nla_get_u8(mAttributes[attribute]) : 0; | |
65 | } | |
66 | ||
67 | uint16_t get_u16(int attribute) { | |
68 | return mAttributes[attribute] ? nla_get_u16(mAttributes[attribute]) : 0; | |
69 | } | |
70 | ||
71 | uint32_t get_u32(int attribute) { | |
72 | return mAttributes[attribute] ? nla_get_u32(mAttributes[attribute]) : 0; | |
73 | } | |
74 | ||
75 | uint64_t get_u64(int attribute) { | |
76 | return mAttributes[attribute] ? nla_get_u64(mAttributes[attribute]) : 0; | |
77 | } | |
78 | ||
79 | int get_len(int attribute) { | |
80 | return mAttributes[attribute] ? nla_len(mAttributes[attribute]) : 0; | |
81 | } | |
82 | ||
83 | void *get_data(int attribute) { | |
84 | return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL; | |
85 | } | |
86 | ||
87 | private: | |
88 | WifiEvent(const WifiEvent&); // hide copy constructor to prevent copies | |
89 | }; | |
90 | ||
91 | class nl_iterator { | |
92 | struct nlattr *pos; | |
93 | int rem; | |
94 | public: | |
95 | nl_iterator(struct nlattr *attr) { | |
96 | pos = (struct nlattr *)nla_data(attr); | |
97 | rem = nla_len(attr); | |
98 | } | |
99 | bool has_next() { | |
100 | return nla_ok(pos, rem); | |
101 | } | |
102 | void next() { | |
103 | pos = (struct nlattr *)nla_next(pos, &(rem)); | |
104 | } | |
105 | struct nlattr *get() { | |
106 | return pos; | |
107 | } | |
108 | uint16_t get_type() { | |
109 | return pos->nla_type; | |
110 | } | |
111 | uint8_t get_u8() { | |
112 | return nla_get_u8(pos); | |
113 | } | |
114 | uint16_t get_u16() { | |
115 | return nla_get_u16(pos); | |
116 | } | |
117 | uint32_t get_u32() { | |
118 | return nla_get_u32(pos); | |
119 | } | |
120 | uint64_t get_u64() { | |
121 | return nla_get_u64(pos); | |
122 | } | |
123 | void* get_data() { | |
124 | return nla_data(pos); | |
125 | } | |
126 | int get_len() { | |
127 | return nla_len(pos); | |
128 | } | |
129 | private: | |
130 | nl_iterator(const nl_iterator&); // hide copy constructor to prevent copies | |
131 | }; | |
132 | ||
133 | class WifiRequest | |
134 | { | |
135 | private: | |
136 | int mFamily; | |
137 | int mIface; | |
138 | struct nl_msg *mMsg; | |
139 | ||
140 | public: | |
141 | WifiRequest(int family) { | |
142 | mMsg = NULL; | |
143 | mFamily = family; | |
144 | mIface = -1; | |
145 | } | |
146 | ||
147 | WifiRequest(int family, int iface) { | |
148 | mMsg = NULL; | |
149 | mFamily = family; | |
150 | mIface = iface; | |
151 | } | |
152 | ||
153 | ~WifiRequest() { | |
154 | destroy(); | |
155 | } | |
156 | ||
157 | void destroy() { | |
158 | if (mMsg) { | |
159 | nlmsg_free(mMsg); | |
160 | mMsg = NULL; | |
161 | } | |
162 | } | |
163 | ||
164 | nl_msg *getMessage() { | |
165 | return mMsg; | |
166 | } | |
167 | ||
168 | /* Command assembly helpers */ | |
169 | int create(int family, uint8_t cmd, int flags, int hdrlen); | |
170 | int create(uint8_t cmd) { | |
171 | return create(mFamily, cmd, 0, 0); | |
172 | } | |
173 | ||
174 | int create(uint32_t id, int subcmd); | |
175 | ||
176 | int put(int attribute, void *ptr, unsigned len) { | |
177 | return nla_put(mMsg, attribute, len, ptr); | |
178 | } | |
179 | int put_u8(int attribute, uint8_t value) { | |
180 | return nla_put(mMsg, attribute, sizeof(value), &value); | |
181 | } | |
182 | int put_u16(int attribute, uint16_t value) { | |
183 | return nla_put(mMsg, attribute, sizeof(value), &value); | |
184 | } | |
185 | int put_u32(int attribute, uint32_t value) { | |
186 | return nla_put(mMsg, attribute, sizeof(value), &value); | |
187 | } | |
188 | int put_u64(int attribute, uint64_t value) { | |
189 | return nla_put(mMsg, attribute, sizeof(value), &value); | |
190 | } | |
191 | int put_string(int attribute, const char *value) { | |
192 | return nla_put(mMsg, attribute, strlen(value) + 1, value); | |
193 | } | |
194 | int put_addr(int attribute, mac_addr value) { | |
195 | return nla_put(mMsg, attribute, sizeof(mac_addr), value); | |
196 | } | |
197 | ||
198 | struct nlattr * attr_start(int attribute) { | |
199 | return nla_nest_start(mMsg, attribute); | |
200 | } | |
201 | void attr_end(struct nlattr *attr) { | |
202 | nla_nest_end(mMsg, attr); | |
203 | } | |
204 | ||
205 | int set_iface_id(int ifindex) { | |
206 | return put_u32(NL80211_ATTR_IFINDEX, ifindex); | |
207 | } | |
208 | private: | |
209 | WifiRequest(const WifiRequest&); // hide copy constructor to prevent copies | |
210 | ||
211 | }; | |
212 | ||
213 | class WifiCommand | |
214 | { | |
215 | protected: | |
216 | hal_info *mInfo; | |
217 | WifiRequest mMsg; | |
218 | Condition mCondition; | |
219 | wifi_request_id mId; | |
220 | interface_info *mIfaceInfo; | |
221 | int mRefs; | |
222 | public: | |
223 | WifiCommand(wifi_handle handle, wifi_request_id id) | |
224 | : mMsg(getHalInfo(handle)->nl80211_family_id), mId(id), mRefs(1) | |
225 | { | |
226 | mIfaceInfo = NULL; | |
227 | mInfo = getHalInfo(handle); | |
228 | // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); | |
229 | } | |
230 | ||
231 | WifiCommand(wifi_interface_handle iface, wifi_request_id id) | |
232 | : mMsg(getHalInfo(iface)->nl80211_family_id, getIfaceInfo(iface)->id), mId(id), mRefs(1) | |
233 | { | |
234 | mIfaceInfo = getIfaceInfo(iface); | |
235 | mInfo = getHalInfo(iface); | |
236 | // ALOGD("WifiCommand %p created, mInfo = %p, mIfaceInfo = %p", this, mInfo, mIfaceInfo); | |
237 | } | |
238 | ||
239 | virtual ~WifiCommand() { | |
240 | // ALOGD("WifiCommand %p destroyed", this); | |
241 | } | |
242 | ||
243 | wifi_request_id id() { | |
244 | return mId; | |
245 | } | |
246 | ||
247 | virtual void addRef() { | |
de2a8779 PG |
248 | __sync_add_and_fetch(&mRefs, 1); |
249 | //int refs = __sync_add_and_fetch(&mRefs, 1); | |
7753f181 DD |
250 | // ALOGD("addRef: WifiCommand %p has %d references", this, refs); |
251 | } | |
252 | ||
253 | virtual void releaseRef() { | |
254 | int refs = __sync_sub_and_fetch(&mRefs, 1); | |
255 | if (refs == 0) { | |
256 | delete this; | |
257 | } else { | |
258 | // ALOGD("releaseRef: WifiCommand %p has %d references", this, refs); | |
259 | } | |
260 | } | |
261 | ||
262 | virtual int create() { | |
263 | /* by default there is no way to cancel */ | |
d20effd2 | 264 | //ALOGD("WifiCommand %p can't be created", this); |
7753f181 DD |
265 | return WIFI_ERROR_NOT_SUPPORTED; |
266 | } | |
267 | ||
268 | virtual int cancel() { | |
269 | /* by default there is no way to cancel */ | |
270 | return WIFI_ERROR_NOT_SUPPORTED; | |
271 | } | |
272 | ||
273 | int requestResponse(); | |
274 | int requestEvent(int cmd); | |
275 | int requestVendorEvent(uint32_t id, int subcmd); | |
276 | int requestResponse(WifiRequest& request); | |
277 | ||
278 | protected: | |
279 | wifi_handle wifiHandle() { | |
280 | return getWifiHandle(mInfo); | |
281 | } | |
282 | ||
283 | wifi_interface_handle ifaceHandle() { | |
284 | return getIfaceHandle(mIfaceInfo); | |
285 | } | |
286 | ||
287 | int familyId() { | |
288 | return mInfo->nl80211_family_id; | |
289 | } | |
290 | ||
291 | int ifaceId() { | |
292 | return mIfaceInfo->id; | |
293 | } | |
294 | ||
295 | /* Override this method to parse reply and dig out data; save it in the object */ | |
296 | virtual int handleResponse(WifiEvent& reply) { | |
297 | ALOGI("skipping a response"); | |
298 | return NL_SKIP; | |
299 | } | |
300 | ||
301 | /* Override this method to parse event and dig out data; save it in the object */ | |
302 | virtual int handleEvent(WifiEvent& event) { | |
303 | ALOGI("skipping an event"); | |
304 | return NL_SKIP; | |
305 | } | |
306 | ||
307 | int registerHandler(int cmd) { | |
308 | return wifi_register_handler(wifiHandle(), cmd, &event_handler, this); | |
309 | } | |
310 | ||
311 | void unregisterHandler(int cmd) { | |
312 | wifi_unregister_handler(wifiHandle(), cmd); | |
313 | } | |
314 | ||
315 | int registerVendorHandler(uint32_t id, int subcmd) { | |
316 | return wifi_register_vendor_handler(wifiHandle(), id, subcmd, &event_handler, this); | |
317 | } | |
318 | ||
319 | void unregisterVendorHandler(uint32_t id, int subcmd) { | |
320 | wifi_unregister_vendor_handler(wifiHandle(), id, subcmd); | |
321 | } | |
322 | ||
323 | private: | |
324 | WifiCommand(const WifiCommand& ); // hide copy constructor to prevent copies | |
325 | ||
326 | /* Event handling */ | |
327 | static int response_handler(struct nl_msg *msg, void *arg); | |
328 | ||
329 | static int event_handler(struct nl_msg *msg, void *arg); | |
330 | ||
331 | /* Other event handlers */ | |
332 | static int valid_handler(struct nl_msg *msg, void *arg); | |
333 | ||
334 | static int ack_handler(struct nl_msg *msg, void *arg); | |
335 | ||
336 | static int finish_handler(struct nl_msg *msg, void *arg); | |
337 | ||
338 | static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg); | |
339 | }; | |
340 | ||
341 | /* nl message processing macros (required to pass C++ type checks) */ | |
342 | ||
343 | #define for_each_attr(pos, nla, rem) \ | |
344 | for (pos = (nlattr *)nla_data(nla), rem = nla_len(nla); \ | |
345 | nla_ok(pos, rem); \ | |
346 | pos = (nlattr *)nla_next(pos, &(rem))) | |
347 |