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