1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <memory>
18 #include "halstate.h"
19 #include "info.h"
20 #include "interface.h"
21
22 template<typename>
23 struct NotSupportedFunction;
24
25 template<typename R, typename... Args>
26 struct NotSupportedFunction<R (*)(Args...)> {
invokeNotSupportedFunction27 static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
28 };
29
30 template<typename... Args>
31 struct NotSupportedFunction<void (*)(Args...)> {
invokeNotSupportedFunction32 static constexpr void invoke(Args...) { }
33 };
34
35 template<typename T>
notSupported(T & val)36 void notSupported(T& val) {
37 val = &NotSupportedFunction<T>::invoke;
38 }
39
asHalState(wifi_handle h)40 HalState* asHalState(wifi_handle h) {
41 return reinterpret_cast<HalState*>(h);
42 }
43
asInfo(wifi_handle h)44 Info* asInfo(wifi_handle h) {
45 return asHalState(h)->info();
46 }
47
asInterface(wifi_interface_handle h)48 Interface* asInterface(wifi_interface_handle h) {
49 return reinterpret_cast<Interface*>(h);
50 }
51
wifi_initialize(wifi_handle * handle)52 wifi_error wifi_initialize(wifi_handle* handle) {
53 if (handle == nullptr) {
54 return WIFI_ERROR_INVALID_ARGS;
55 }
56
57 // Make the HAL state static inside the function for lazy construction. When
58 // stopping we want to keep track of the current HAL state because if the
59 // HAL starts again we need to know if we're in a state where we can start
60 // or not. If we're stopping with the intention of never starting back up
61 // again we could destroy the HAL state. Unfortunately there is no
62 // distinction between these two events so the safe choice is to leak this
63 // memory and always keep track of the HAL state. This is allocated on the
64 // heap instead of the stack to prevent any destructors being called when
65 // the dynamic library is being unloaded since the program state could be
66 // unreliable at this point.
67 static HalState* sHalState = new HalState();
68
69 if (!sHalState->init()) {
70 return WIFI_ERROR_UNKNOWN;
71 }
72 *handle = reinterpret_cast<wifi_handle>(sHalState);
73
74 return WIFI_SUCCESS;
75 }
76
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)77 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) {
78 if (handle == nullptr) {
79 return;
80 }
81
82 std::condition_variable condition;
83 std::mutex mutex;
84 std::unique_lock<std::mutex> lock(mutex);
85 bool stopped = false;
86 // This lambda will be called when the stop completes. That will notify the
87 // condition variable and this function will wake up and exit. This ensures
88 // that this function is synchronous. The boolean is to ensure that when
89 // waiting we're protected against spurious wakeups, we only exit once the
90 // callback has signaled that it's been called.
91 auto callback = [&mutex, &stopped, &condition] {
92 std::unique_lock<std::mutex> lock(mutex);
93 stopped = true;
94 condition.notify_all();
95 };
96 if (asHalState(handle)->stop(callback)) {
97 // The handler succeeded and will call our callback, wait for it. If the
98 // stop call did not succeed we can't wait for this condition since our
99 // callback will never call notify on it.
100 while (!stopped) {
101 condition.wait(lock);
102 }
103 }
104 // The HAL seems to expect this callback to happen on the same thread, or at
105 // least that's what happens in other WiFi HALs. This is why this method has
106 // to be synchronous.
107 handler(handle);
108 }
109
wifi_event_loop(wifi_handle handle)110 void wifi_event_loop(wifi_handle handle) {
111 if (handle == nullptr) {
112 return;
113 }
114
115 asHalState(handle)->eventLoop();
116 }
117
wifi_get_supported_feature_set(wifi_interface_handle handle,feature_set * set)118 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle,
119 feature_set* set) {
120 if (handle == nullptr) {
121 return WIFI_ERROR_INVALID_ARGS;
122 }
123
124 return asInterface(handle)->getSupportedFeatureSet(set);
125 }
126
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)127 wifi_error wifi_get_ifaces(wifi_handle handle,
128 int* num,
129 wifi_interface_handle** interfaces) {
130 if (handle == nullptr) {
131 return WIFI_ERROR_INVALID_ARGS;
132 }
133
134 return asInfo(handle)->getInterfaces(num, interfaces);
135 }
136
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)137 wifi_error wifi_get_iface_name(wifi_interface_handle handle,
138 char* name,
139 size_t size) {
140 if (handle == nullptr || (name == nullptr && size > 0)) {
141 return WIFI_ERROR_INVALID_ARGS;
142 }
143
144 return asInterface(handle)->getName(name, size);
145 }
146
wifi_get_link_stats(wifi_request_id id,wifi_interface_handle handle,wifi_stats_result_handler handler)147 wifi_error wifi_get_link_stats(wifi_request_id id,
148 wifi_interface_handle handle,
149 wifi_stats_result_handler handler) {
150 if (handle == nullptr) {
151 return WIFI_ERROR_INVALID_ARGS;
152 }
153
154 return asInterface(handle)->getLinkStats(id, handler);
155 }
156
wifi_set_link_stats(wifi_interface_handle handle,wifi_link_layer_params params)157 wifi_error wifi_set_link_stats(wifi_interface_handle handle,
158 wifi_link_layer_params params) {
159 if (handle == nullptr) {
160 return WIFI_ERROR_INVALID_ARGS;
161 }
162
163 return asInterface(handle)->setLinkStats(params);
164 }
165
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle handle,wifi_alert_handler handler)166 wifi_error wifi_set_alert_handler(wifi_request_id id,
167 wifi_interface_handle handle,
168 wifi_alert_handler handler) {
169 if (handle == nullptr) {
170 return WIFI_ERROR_INVALID_ARGS;
171 }
172
173 return asInterface(handle)->setAlertHandler(id, handler);
174 }
175
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle handle)176 wifi_error wifi_reset_alert_handler(wifi_request_id id,
177 wifi_interface_handle handle) {
178 if (handle == nullptr) {
179 return WIFI_ERROR_INVALID_ARGS;
180 }
181
182 return asInterface(handle)->resetAlertHandler(id);
183 }
184
wifi_get_firmware_version(wifi_interface_handle handle,char * buffer,int buffer_size)185 wifi_error wifi_get_firmware_version(wifi_interface_handle handle,
186 char* buffer,
187 int buffer_size) {
188 if (handle == nullptr) {
189 return WIFI_ERROR_INVALID_ARGS;
190 }
191
192 return asInterface(handle)->getFirmwareVersion(buffer, buffer_size);
193 }
194
wifi_get_driver_version(wifi_interface_handle handle,char * buffer,int buffer_size)195 wifi_error wifi_get_driver_version(wifi_interface_handle handle,
196 char* buffer,
197 int buffer_size) {
198 if (handle == nullptr) {
199 return WIFI_ERROR_INVALID_ARGS;
200 }
201
202 return asInterface(handle)->getDriverVersion(buffer, buffer_size);
203 }
204
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)205 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle,
206 oui scan_oui) {
207 if (handle == nullptr) {
208 return WIFI_ERROR_INVALID_ARGS;
209 }
210
211 return asInterface(handle)->setScanningMacOui(scan_oui);
212 }
213
wifi_clear_link_stats(wifi_interface_handle handle,u32 stats_clear_req_mask,u32 * stats_clear_rsp_mask,u8 stop_req,u8 * stop_rsp)214 wifi_error wifi_clear_link_stats(wifi_interface_handle handle,
215 u32 stats_clear_req_mask,
216 u32 *stats_clear_rsp_mask,
217 u8 stop_req,
218 u8 *stop_rsp) {
219 if (handle == nullptr) {
220 return WIFI_ERROR_INVALID_ARGS;
221 }
222
223 return asInterface(handle)->clearLinkStats(stats_clear_req_mask,
224 stats_clear_rsp_mask,
225 stop_req,
226 stop_rsp);
227 }
228
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)229 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
230 int band,
231 int max_channels,
232 wifi_channel *channels,
233 int *num_channels)
234 {
235 if (handle == nullptr) {
236 return WIFI_ERROR_INVALID_ARGS;
237 }
238
239 return asInterface(handle)->getValidChannels(band,
240 max_channels,
241 channels,
242 num_channels);
243 }
244
wifi_start_logging(wifi_interface_handle handle,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)245 wifi_error wifi_start_logging(wifi_interface_handle handle,
246 u32 verbose_level,
247 u32 flags,
248 u32 max_interval_sec,
249 u32 min_data_size,
250 char *ring_name) {
251 if (handle == nullptr) {
252 return WIFI_ERROR_INVALID_ARGS;
253 }
254
255 return asInterface(handle)->startLogging(verbose_level,
256 flags,
257 max_interval_sec,
258 min_data_size,
259 ring_name);
260 }
261
wifi_set_country_code(wifi_interface_handle handle,const char * country_code)262 wifi_error wifi_set_country_code(wifi_interface_handle handle,
263 const char *country_code) {
264 if (handle == nullptr) {
265 return WIFI_ERROR_INVALID_ARGS;
266 }
267
268 return asInterface(handle)->setCountryCode(country_code);
269 }
270
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle handle,wifi_ring_buffer_data_handler handler)271 wifi_error wifi_set_log_handler(wifi_request_id id,
272 wifi_interface_handle handle,
273 wifi_ring_buffer_data_handler handler) {
274 if (handle == nullptr) {
275 return WIFI_ERROR_INVALID_ARGS;
276 }
277
278 return asInterface(handle)->setLogHandler(id, handler);
279 }
280
wifi_get_ring_buffers_status(wifi_interface_handle handle,u32 * num_rings,wifi_ring_buffer_status * status)281 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle handle,
282 u32 *num_rings,
283 wifi_ring_buffer_status *status) {
284 if (handle == nullptr) {
285 return WIFI_ERROR_INVALID_ARGS;
286 }
287
288 return asInterface(handle)->getRingBuffersStatus(num_rings, status);
289 }
290
wifi_get_logger_supported_feature_set(wifi_interface_handle handle,unsigned int * support)291 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle handle,
292 unsigned int *support) {
293 if (handle == nullptr) {
294 return WIFI_ERROR_INVALID_ARGS;
295 }
296
297 return asInterface(handle)->getLoggerSupportedFeatureSet(support);
298 }
299
wifi_get_ring_data(wifi_interface_handle handle,char * ring_name)300 wifi_error wifi_get_ring_data(wifi_interface_handle handle, char *ring_name) {
301 if (handle == nullptr) {
302 return WIFI_ERROR_INVALID_ARGS;
303 }
304
305 return asInterface(handle)->getRingData(ring_name);
306 }
307
wifi_configure_nd_offload(wifi_interface_handle handle,u8 enable)308 wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable) {
309 if (handle == nullptr) {
310 return WIFI_ERROR_INVALID_ARGS;
311 }
312
313 return asInterface(handle)->configureNdOffload(enable);
314 }
315
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)316 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle) {
317 if (handle == nullptr) {
318 return WIFI_ERROR_INVALID_ARGS;
319 }
320
321 return asInterface(handle)->startPacketFateMonitoring();
322 }
323
wifi_get_tx_pkt_fates(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)324 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
325 wifi_tx_report *tx_report_bufs,
326 size_t n_requested_fates,
327 size_t *n_provided_fates) {
328 if (handle == nullptr) {
329 return WIFI_ERROR_INVALID_ARGS;
330 }
331
332 return asInterface(handle)->getTxPacketFates(tx_report_bufs,
333 n_requested_fates,
334 n_provided_fates);
335 }
336
wifi_get_rx_pkt_fates(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)337 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
338 wifi_rx_report *rx_report_bufs,
339 size_t n_requested_fates,
340 size_t *n_provided_fates) {
341 if (handle == nullptr) {
342 return WIFI_ERROR_INVALID_ARGS;
343 }
344
345 return asInterface(handle)->getRxPacketFates(rx_report_bufs,
346 n_requested_fates,
347 n_provided_fates);
348 }
349
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)350 wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
351 u32 *version,
352 u32 *max_len) {
353 if (handle == nullptr) {
354 return WIFI_ERROR_INVALID_ARGS;
355 }
356
357 return asInterface(handle)->getPacketFilterCapabilities(version, max_len);
358 }
359
360 wifi_error
wifi_get_wake_reason_stats(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)361 wifi_get_wake_reason_stats(wifi_interface_handle handle,
362 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) {
363 if (handle == nullptr) {
364 return WIFI_ERROR_INVALID_ARGS;
365 }
366
367 return asInterface(handle)->getWakeReasonStats(wifi_wake_reason_cnt);
368 }
wifi_start_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle handle,u16 ether_type,u8 * ip_packet,u16 ip_packet_len,u8 * src_mac_addr,u8 * dst_mac_addr,u32 period_msec)369 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
370 wifi_interface_handle handle,
371 u16 ether_type,
372 u8 *ip_packet,
373 u16 ip_packet_len,
374 u8 *src_mac_addr,
375 u8 *dst_mac_addr,
376 u32 period_msec) {
377 if (handle == nullptr) {
378 return WIFI_ERROR_INVALID_ARGS;
379 }
380
381 return asInterface(handle)->startSendingOffloadedPacket(id,
382 ether_type,
383 ip_packet,
384 ip_packet_len,
385 src_mac_addr,
386 dst_mac_addr,
387 period_msec);
388 }
389
wifi_stop_sending_offloaded_packet(wifi_request_id id,wifi_interface_handle handle)390 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
391 wifi_interface_handle handle) {
392 if (handle == nullptr) {
393 return WIFI_ERROR_INVALID_ARGS;
394 }
395
396 return asInterface(handle)->stopSendingOffloadedPacket(id);
397 }
398
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)399 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn* fn)
400 {
401 if (fn == NULL) {
402 return WIFI_ERROR_UNKNOWN;
403 }
404 fn->wifi_initialize = wifi_initialize;
405 fn->wifi_cleanup = wifi_cleanup;
406 fn->wifi_event_loop = wifi_event_loop;
407 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
408
409 fn->wifi_get_ifaces = wifi_get_ifaces;
410 fn->wifi_get_iface_name = wifi_get_iface_name;
411 fn->wifi_get_link_stats = wifi_get_link_stats;
412 fn->wifi_set_link_stats = wifi_set_link_stats;
413 fn->wifi_clear_link_stats = wifi_clear_link_stats;
414
415 fn->wifi_set_alert_handler = wifi_set_alert_handler;
416 fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
417 fn->wifi_get_firmware_version = wifi_get_firmware_version;
418 fn->wifi_get_driver_version = wifi_get_driver_version;
419
420 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
421 fn->wifi_get_valid_channels = wifi_get_valid_channels;
422 fn->wifi_start_logging = wifi_start_logging;
423 fn->wifi_set_country_code = wifi_set_country_code;
424 fn->wifi_set_log_handler = wifi_set_log_handler;
425 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
426 fn->wifi_get_logger_supported_feature_set
427 = wifi_get_logger_supported_feature_set;
428 fn->wifi_get_ring_data = wifi_get_ring_data;
429 fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
430 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
431 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
432 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
433 fn->wifi_get_packet_filter_capabilities
434 = wifi_get_packet_filter_capabilities;
435 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
436
437 fn->wifi_start_sending_offloaded_packet
438 = wifi_start_sending_offloaded_packet;
439 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
440
441 // These function will either return WIFI_ERROR_NOT_SUPPORTED or do nothing
442 notSupported(fn->wifi_set_nodfs_flag);
443 notSupported(fn->wifi_get_concurrency_matrix);
444 notSupported(fn->wifi_start_gscan);
445 notSupported(fn->wifi_stop_gscan);
446 notSupported(fn->wifi_get_cached_gscan_results);
447 notSupported(fn->wifi_set_bssid_hotlist);
448 notSupported(fn->wifi_reset_bssid_hotlist);
449 notSupported(fn->wifi_set_significant_change_handler);
450 notSupported(fn->wifi_reset_significant_change_handler);
451 notSupported(fn->wifi_get_gscan_capabilities);
452 notSupported(fn->wifi_rtt_range_request);
453 notSupported(fn->wifi_rtt_range_cancel);
454 notSupported(fn->wifi_get_rtt_capabilities);
455 notSupported(fn->wifi_rtt_get_responder_info);
456 notSupported(fn->wifi_enable_responder);
457 notSupported(fn->wifi_disable_responder);
458 notSupported(fn->wifi_set_epno_list);
459 notSupported(fn->wifi_reset_epno_list);
460 notSupported(fn->wifi_get_firmware_memory_dump);
461 notSupported(fn->wifi_reset_log_handler);
462 notSupported(fn->wifi_start_rssi_monitoring);
463 notSupported(fn->wifi_stop_rssi_monitoring);
464 notSupported(fn->wifi_set_packet_filter);
465
466 return WIFI_SUCCESS;
467 }
468
469