• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 template<typename>
26 struct NotSupportedFunction;
27 
28 template<typename R, typename... Args>
29 struct NotSupportedFunction<R (*)(Args...)> {
invokeNotSupportedFunction30     static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
31 };
32 
33 template<typename... Args>
34 struct NotSupportedFunction<void (*)(Args...)> {
invokeNotSupportedFunction35     static constexpr void invoke(Args...) { }
36 };
37 
38 template<typename T>
notSupported(T & val)39 void notSupported(T& val) {
40     val = &NotSupportedFunction<T>::invoke;
41 }
42 
asHalState(wifi_handle h)43 HalState* asHalState(wifi_handle h) {
44     return reinterpret_cast<HalState*>(h);
45 }
46 
asInfo(wifi_handle h)47 Info* asInfo(wifi_handle h) {
48     return asHalState(h)->info();
49 }
50 
asInterface(wifi_interface_handle h)51 Interface* asInterface(wifi_interface_handle h) {
52     return reinterpret_cast<Interface*>(h);
53 }
54 
wifi_initialize(wifi_handle * handle)55 wifi_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 
wifi_cleanup(wifi_handle handle,wifi_cleaned_up_handler handler)80 void 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 
wifi_event_loop(wifi_handle handle)113 void wifi_event_loop(wifi_handle handle) {
114     if (handle == nullptr) {
115         return;
116     }
117 
118     asHalState(handle)->eventLoop();
119 }
120 
wifi_get_supported_feature_set(wifi_interface_handle handle,feature_set * set)121 wifi_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 
wifi_get_ifaces(wifi_handle handle,int * num,wifi_interface_handle ** interfaces)130 wifi_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 
wifi_get_iface_name(wifi_interface_handle handle,char * name,size_t size)140 wifi_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 
wifi_get_link_stats(wifi_request_id id,wifi_interface_handle handle,wifi_stats_result_handler handler)150 wifi_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 
wifi_set_link_stats(wifi_interface_handle handle,wifi_link_layer_params params)160 wifi_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 
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle handle,wifi_alert_handler handler)169 wifi_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 
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle handle)179 wifi_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 
wifi_get_firmware_version(wifi_interface_handle handle,char * buffer,int buffer_size)188 wifi_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 
wifi_get_driver_version(wifi_interface_handle handle,char * buffer,int buffer_size)198 wifi_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 
wifi_set_scanning_mac_oui(wifi_interface_handle handle,oui scan_oui)208 wifi_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 
wifi_clear_link_stats(wifi_interface_handle handle,u32 stats_clear_req_mask,u32 * stats_clear_rsp_mask,u8 stop_req,u8 * stop_rsp)217 wifi_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 
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)232 wifi_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 
wifi_start_logging(wifi_interface_handle handle,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)248 wifi_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 
wifi_set_country_code(wifi_interface_handle handle,const char * country_code)265 wifi_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 
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle handle,wifi_ring_buffer_data_handler handler)274 wifi_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 
wifi_get_ring_buffers_status(wifi_interface_handle handle,u32 * num_rings,wifi_ring_buffer_status * status)284 wifi_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 
wifi_get_logger_supported_feature_set(wifi_interface_handle handle,unsigned int * support)294 wifi_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 
wifi_get_ring_data(wifi_interface_handle handle,char * ring_name)303 wifi_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 
wifi_configure_nd_offload(wifi_interface_handle handle,u8 enable)311 wifi_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 
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)319 wifi_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 
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)327 wifi_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 
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)340 wifi_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 
wifi_get_packet_filter_capabilities(wifi_interface_handle handle,u32 * version,u32 * max_len)353 wifi_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 
363 wifi_error
wifi_get_wake_reason_stats(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)364 wifi_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 
init_wifi_vendor_hal_func_table(wifi_hal_fn * fn)373 wifi_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