Home | History | Annotate | Download | only in wifi_hal
      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...)> {
     30     static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
     31 };
     32 
     33 template<typename... Args>
     34 struct NotSupportedFunction<void (*)(Args...)> {
     35     static constexpr void invoke(Args...) { }
     36 };
     37 
     38 template<typename T>
     39 void notSupported(T& val) {
     40     val = &NotSupportedFunction<T>::invoke;
     41 }
     42 
     43 HalState* asHalState(wifi_handle h) {
     44     return reinterpret_cast<HalState*>(h);
     45 }
     46 
     47 Info* asInfo(wifi_handle h) {
     48     return asHalState(h)->info();
     49 }
     50 
     51 Interface* asInterface(wifi_interface_handle h) {
     52     return reinterpret_cast<Interface*>(h);
     53 }
     54 
     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 
     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 
    113 void wifi_event_loop(wifi_handle handle) {
    114     if (handle == nullptr) {
    115         return;
    116     }
    117 
    118     asHalState(handle)->eventLoop();
    119 }
    120 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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