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