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