/* * Copyright (C) 2017 The Android Open Source Project * * Portions copyright (C) 2017 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "main.h" #include "wifi_command.h" #define SKW_BUFF_SIZE 256 #define WIFI_HAL_SOCK_DEFAULT_PORT 644 #define WIFI_HAL_SOCK_EVENT_PORT 645 #define SOCK_BUFF_SIZE 0x40000 struct nl_sock *getSock(wifi_interface_handle handle) { interface_info *info = (interface_info *)handle; return ((hal_info *)info->hal_handle)->nl_hal; } int getFamily(wifi_interface_handle handle) { interface_info *info = (interface_info *)handle; return ((hal_info *)info->hal_handle)->family_nl80211; } void skw_wifi_get_error_info(wifi_error error, const char **chr) { ALOGD("%s", __func__); } wifi_error skw_wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *feature) { ALOGD("%s, feature: 0x%x", __func__, *feature); *feature = 0; return WIFI_SUCCESS; } wifi_error skw_wifi_get_concurrency_matrix(wifi_interface_handle handle, int count, feature_set *feature, int *args) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_scanning_mac_oui(wifi_interface_handle handle, unsigned char *oui) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_supported_channels(wifi_handle handle, int *num, wifi_channel *channels) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_is_epr_supported(wifi_handle handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } class GetInterfacesCommand : public WifiCommand { private: int index; interface_info ifaces[SKW_NR_IFACE]; public: GetInterfacesCommand(struct nl_sock *sk, int family, int flags, int nl80211_cmd) : WifiCommand(sk, family, flags, nl80211_cmd) { index = 0; memset(ifaces, 0x0, sizeof(interface_info)); } virtual wifi_error build(wifi_interface_handle handle, void *param) { return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { if (attr[NL80211_ATTR_IFINDEX]) ifaces[index].iface_idx = nla_get_u32(attr[NL80211_ATTR_IFINDEX]); else ifaces[index].wdev_idx = nla_get_u32(attr[NL80211_ATTR_WDEV]); if (attr[NL80211_ATTR_IFNAME]) strcpy(ifaces[index].name, nla_get_string(attr[NL80211_ATTR_IFNAME])); index++; return WIFI_SUCCESS; } int getIfaceNum() { return index; } interface_info *iface(int idx) { return &ifaces[idx]; } }; wifi_error skw_wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **iface_handle) { int i; hal_info *hal = (hal_info *)handle; GetInterfacesCommand cmd(hal->nl_hal, hal->family_nl80211, NLM_F_DUMP, NL80211_CMD_GET_INTERFACE); memset(hal->interfaces, 0x0, sizeof(hal->interfaces)); cmd.build(NULL, NULL); cmd.send(); if (cmd.getIfaceNum() == 0) return WIFI_ERROR_UNKNOWN; hal->nr_interfaces = cmd.getIfaceNum(); for (i = 0; i < hal->nr_interfaces; i++) { strcpy(hal->interfaces[i].name, cmd.iface(i)->name); hal->interfaces[i].iface_idx = cmd.iface(i)->iface_idx; hal->interfaces[i].wdev_idx = cmd.iface(i)->wdev_idx; hal->interfaces[i].hal_handle = handle; hal->interface_handle[i] = (wifi_interface_handle)(&hal->interfaces[i]); } *iface_handle = &hal->interface_handle[0]; *num = hal->nr_interfaces; return WIFI_SUCCESS; } wifi_error skw_wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) { interface_info *iface = (interface_info *)handle; ALOGD("%s: name: %s", __func__, iface->name); strncpy(name, iface->name, size); return WIFI_SUCCESS; } wifi_error skw_wifi_set_iface_event_handler(wifi_request_id,wifi_interface_handle , wifi_event_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_iface_event_handler(wifi_request_id, wifi_interface_handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_start_gscan(wifi_request_id id, wifi_interface_handle iface, wifi_scan_cmd_params params, wifi_scan_result_handler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_stop_gscan(wifi_request_id, wifi_interface_handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_cached_gscan_results(wifi_interface_handle, byte, int, wifi_cached_scan_results *results, int *) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_bssid_hotlist(wifi_request_id, wifi_interface_handle, wifi_bssid_hotlist_params, wifi_hotlist_ap_found_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_bssid_hotlist(wifi_request_id, wifi_interface_handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_significant_change_handler(wifi_request_id, wifi_interface_handle, wifi_significant_change_params, wifi_significant_change_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_gscan_capabilities(wifi_interface_handle iface, wifi_gscan_capabilities *capa) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_link_stats(wifi_interface_handle iface, wifi_link_layer_params params) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_link_stats(wifi_request_id id, wifi_interface_handle handle, wifi_stats_result_handler result_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_clear_link_stats(wifi_interface_handle,u32, u32 *, u8, u8 *) { ALOGD("%s", __func__); return WIFI_SUCCESS; } class GetValidChannelsCommand : public WifiCommand { private: wifi_channel *mChannels; int max_channels, nr_channels; public: GetValidChannelsCommand(struct nl_sock *sk, int family, int flags, int nl80211_cmd, wifi_channel *channels, int max_chans) : WifiCommand(sk, family, flags, nl80211_cmd) { nr_channels = 0; mChannels = channels; max_channels = max_chans; memset(channels, 0x0, max_chans * sizeof(*channels)); } virtual wifi_error build(wifi_interface_handle handle, void *param) { #define SKW_ATTR_BAND 20 struct nlattr *data; interface_info *iface = (interface_info *)handle; put_u32(NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); put_u32(NL80211_ATTR_VENDOR_SUBCMD, SKW_VCMD_GET_CHANNELS); if (iface->wdev_idx) put_u32(NL80211_ATTR_WDEV, iface->wdev_idx); else put_u32(NL80211_ATTR_IFINDEX, iface->iface_idx); data =attr_start(); put_u32(SKW_ATTR_BAND, *(int *)param); attr_end(data); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { #define SKW_ATTR_NR_CAHNNELS 36 #define SKW_ATTR_VALID_CHANNELS 37 int left, type; struct nlattr *nla; struct nlattr *data = attr[NL80211_ATTR_VENDOR_DATA]; if (!data) return WIFI_ERROR_NOT_AVAILABLE; nla_for_each_attr(nla, (struct nlattr *)nla_data(data), nla_len(data), left) { type = nla_type(nla); switch (type) { case SKW_ATTR_NR_CAHNNELS: nr_channels = nla_get_u32(nla); break; case SKW_ATTR_VALID_CHANNELS: memcpy(mChannels, nla_data(nla), nla_len(nla)); break; default: break; } } return WIFI_SUCCESS; } int numChannels() { return nr_channels; } }; wifi_error skw_wifi_get_valid_channels(wifi_interface_handle iface, int band, int max_channels, wifi_channel *channels, int *num_channels) { int i; wifi_error err = WIFI_ERROR_UNKNOWN; GetValidChannelsCommand cmd(getSock(iface), getFamily(iface), 0, NL80211_CMD_VENDOR, channels, max_channels); cmd.build(iface, &band); err = cmd.send(); *num_channels = cmd.numChannels(); ALOGD("%s, BAND: %d, nr channels: %d", __func__, band, *num_channels); return err; } wifi_error skw_wifi_rtt_range_request(wifi_request_id, wifi_interface_handle, unsigned, wifi_rtt_config[], wifi_rtt_event_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface, unsigned range, mac_addr addr[]) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_rtt_capabilities(wifi_interface_handle handle, wifi_rtt_capabilities *capa) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_rtt_get_responder_info(wifi_interface_handle iface, wifi_rtt_responder *responder_info) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface, wifi_channel_info channel_hint, unsigned max_duration_seconds, wifi_rtt_responder *responder_info) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_nodfs_flag(wifi_interface_handle, u32) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_start_logging(wifi_interface_handle, u32, u32, u32, u32, char *) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_epno_list(wifi_request_id, wifi_interface_handle, const wifi_epno_params *, wifi_epno_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_epno_list(wifi_request_id, wifi_interface_handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } class SetCountryCodeCommand : public WifiCommand { public: SetCountryCodeCommand(struct nl_sock *sk, int family, int flags, int nl80211_cmd) : WifiCommand(sk, family, flags, nl80211_cmd) { } virtual wifi_error build(wifi_interface_handle handle, void *param) { struct nlattr *data; interface_info *iface = (interface_info *)handle; put_u32(NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); put_u32(NL80211_ATTR_VENDOR_SUBCMD, SKW_VCMD_SET_COUNTRY); if (iface->wdev_idx) put_u32(NL80211_ATTR_WDEV, iface->wdev_idx); else put_u32(NL80211_ATTR_IFINDEX, iface->iface_idx); data =attr_start(); put_string(5, (const char *)param); attr_end(data); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { return WIFI_SUCCESS; } }; static wifi_error skw_wifi_set_country_code(wifi_interface_handle handle, const char *country) { SetCountryCodeCommand cmd(getSock(handle), getFamily(handle), 0, NL80211_CMD_VENDOR); ALOGD("%s, country: %s", __func__, country); cmd.build(handle, (void *)country); return cmd.send(); } wifi_error skw_wifi_get_firmware_memory_dump( wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler) { ALOGD("%s", __func__); return WIFI_ERROR_NOT_SUPPORTED; } wifi_error skw_wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface, wifi_ring_buffer_data_handler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface, wifi_alert_handler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } class GetVersionCommand : public WifiCommand { private: char buff[SKW_BUFF_SIZE]; public: GetVersionCommand(struct nl_sock *sk, int family, int flags, int cmd) : WifiCommand(sk, family, flags, cmd) { memset(buff, 0x0, sizeof(buff)); } virtual wifi_error build(wifi_interface_handle handle, void *param) { struct nlattr *data; interface_info *info = (interface_info *)handle; put_u32(NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); put_u32(NL80211_ATTR_VENDOR_SUBCMD, SKW_VCMD_GET_VERSION); if (info->wdev_idx) put_u32(NL80211_ATTR_WDEV, info->wdev_idx); else put_u32(NL80211_ATTR_IFINDEX, info->iface_idx); data =attr_start(); put_u32(*(int *)param, 0); attr_end(data); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { if (attr[NL80211_ATTR_VENDOR_DATA]) strncpy(buff, (char *)nla_data(attr[NL80211_ATTR_VENDOR_DATA]), sizeof(buff)); return WIFI_SUCCESS; } char *getVersion() { return buff; } }; wifi_error skw_wifi_get_firmware_version(wifi_interface_handle iface, char *buffer, int buffer_size) { int subcmd = SKW_FW_VERSION; wifi_error err = WIFI_ERROR_UNKNOWN; GetVersionCommand cmd(getSock(iface), getFamily(iface), 0, NL80211_CMD_VENDOR); cmd.build(iface, &subcmd); err = cmd.send(); strncpy(buffer, cmd.getVersion(), buffer_size); ALOGD("%s: %s", __func__, buffer); return err; } class GetRingBuffStatus : public WifiCommand { private: u32 *num; wifi_ring_buffer_status *mStatus; public: GetRingBuffStatus(struct nl_sock *sk, int family, int flags, int nl80211_cmd, u32 *num_rings, wifi_ring_buffer_status *status) : WifiCommand(sk, family, flags, nl80211_cmd) { *num_rings = 0; num = num_rings; mStatus = status; } virtual wifi_error build(wifi_interface_handle handle, void *param) { interface_info *iface = (interface_info *)handle; put_u32(NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); put_u32(NL80211_ATTR_VENDOR_SUBCMD, SKW_VCMD_GET_RING_BUFFERS_STATUS); if (iface->wdev_idx) put_u32(NL80211_ATTR_WDEV, iface->wdev_idx); else put_u32(NL80211_ATTR_IFINDEX, iface->iface_idx); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { int type, left; struct nlattr *nla, *data; int i = 0, nr_buff = 0; #define SKW_ATTR_RING_BUFFERS_STATUS 13 #define SKW_ATTR_NUM_RING_BUFFERS 14 data = attr[NL80211_ATTR_VENDOR_DATA]; if (!data) return WIFI_ERROR_NOT_AVAILABLE; nla_for_each_attr(nla, (struct nlattr *)nla_data(data), nla_len(data), left) { type = nla_type(nla); switch (type) { case SKW_ATTR_NUM_RING_BUFFERS: nr_buff = nla_get_u32(nla); break; case SKW_ATTR_RING_BUFFERS_STATUS: if (nla_len(nla) == sizeof(wifi_ring_buffer_status)) { memcpy(&mStatus[i++], nla_data(nla), nla_len(nla)); *num = i; } else { ALOGE("wifi_ring_buffer_status not match"); } break; default: break; } } if (nr_buff != *(int *)num) ALOGE("num of ring buffs not match, %d - %d", nr_buff, *num); return WIFI_SUCCESS; } }; // There are no flags for these 3 in the legacy feature set. Adding them to // the set because all the current devices support it. // *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA; // *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS; // *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS; wifi_error skw_wifi_get_ring_buffers_status(wifi_interface_handle iface, u32 *num_rings, wifi_ring_buffer_status *status) { GetRingBuffStatus cmd(getSock(iface), getFamily(iface), 0, NL80211_CMD_VENDOR, num_rings, status); cmd.build(iface, NULL); cmd.send(); ALOGD("%s, num rings: %d", __func__, *num_rings); return WIFI_SUCCESS; } class GetLoggerFeature : public WifiCommand { private: unsigned int mFeatures; public: GetLoggerFeature(struct nl_sock *sk, int family, int flags, int nl80211_cmd) : WifiCommand(sk, family, flags, nl80211_cmd) { mFeatures = 0; } virtual wifi_error build(wifi_interface_handle handle, void *param) { interface_info *iface = (interface_info *)handle; put_u32(NL80211_ATTR_VENDOR_ID, OUI_GOOGLE); put_u32(NL80211_ATTR_VENDOR_SUBCMD, SKW_VCMD_GET_LOGGER_FEATURES); if (iface->wdev_idx) put_u32(NL80211_ATTR_WDEV, iface->wdev_idx); else put_u32(NL80211_ATTR_IFINDEX, iface->iface_idx); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { struct nlattr *data = attr[NL80211_ATTR_VENDOR_DATA]; if (!data) return WIFI_ERROR_NOT_AVAILABLE; mFeatures = nla_get_u32(data); return WIFI_SUCCESS; } int features() { return mFeatures; } }; wifi_error skw_wifi_get_logger_supported_feature_set(wifi_interface_handle iface, unsigned int *features) { GetLoggerFeature cmd(getSock(iface), getFamily(iface), 0, NL80211_CMD_VENDOR); cmd.build(iface, NULL); cmd.send(); *features = cmd.features(); ALOGD("%s, features: 0x%x", __func__, *features); return WIFI_SUCCESS; } wifi_error skw_wifi_get_ring_data(wifi_interface_handle iface, char *ring_name) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_enable_tdls(wifi_interface_handle, mac_addr, wifi_tdls_params *, wifi_tdls_handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_disable_tdls(wifi_interface_handle, mac_addr) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_tdls_status(wifi_interface_handle, mac_addr, wifi_tdls_status *) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_tdls_capabilities(wifi_interface_handle iface, wifi_tdls_capabilities *capabilities) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_driver_version(wifi_interface_handle handle, char *buffer, int buffer_size) { int subcmd = SKW_DRV_VERSION; wifi_error err = WIFI_ERROR_UNKNOWN; GetVersionCommand cmd(getSock(handle), getFamily(handle), 0, NL80211_CMD_VENDOR); if (cmd.build(handle, &subcmd) == WIFI_SUCCESS) err = cmd.send(); if (err == WIFI_SUCCESS) strncpy(buffer, cmd.getVersion(), buffer_size); ALOGD("%s: %s", __func__, buffer); return err; } wifi_error skw_wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, wifi_passpoint_network *networks, wifi_passpoint_event_handler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_lci(wifi_request_id id, wifi_interface_handle iface, wifi_lci_information *lci) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface, wifi_lcr_information *lcr) { ALOGD("%s", __func__); return WIFI_SUCCESS; } #if 0 wifi_error skw_wifi_start_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface, u16 ether_type, u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec) { ALOGD("%s", __func__); return WIFI_SUCCESS; } #endif wifi_error skw_wifi_stop_sending_offloaded_packet(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_wake_reason_stats(wifi_interface_handle iface, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_driver_memory_dump(wifi_interface_handle iface, wifi_driver_memory_dump_callbacks callbacks) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_start_pkt_fate_monitoring(wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_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) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_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) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /* NAN functions */ wifi_error skw_wifi_nan_enable_request(transaction_id id, wifi_interface_handle iface, NanEnableRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_disable_request(transaction_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_publish_request(transaction_id id, wifi_interface_handle iface, NanPublishRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_publish_cancel_request(transaction_id id, wifi_interface_handle iface, NanPublishCancelRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_subscribe_request(transaction_id id, wifi_interface_handle iface, NanSubscribeRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_subscribe_cancel_request(transaction_id id, wifi_interface_handle iface, NanSubscribeCancelRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_transmit_followup_request(transaction_id id, wifi_interface_handle iface, NanTransmitFollowupRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_stats_request(transaction_id id, wifi_interface_handle iface, NanStatsRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_config_request(transaction_id id, wifi_interface_handle iface, NanConfigRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_tca_request(transaction_id id, wifi_interface_handle iface, NanTCARequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_beacon_sdf_payload_request(transaction_id id, wifi_interface_handle iface, NanBeaconSdfPayloadRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_register_handler(wifi_interface_handle iface, NanCallbackHandler handlers) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_get_version(wifi_handle handle, NanVersion* version) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_get_capabilities(transaction_id id, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_data_interface_create(transaction_id id, wifi_interface_handle iface, char *iface_name) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_data_interface_delete(transaction_id id, wifi_interface_handle iface, char *iface_name) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_data_request_initiator( transaction_id id, wifi_interface_handle iface, NanDataPathInitiatorRequest *msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_data_indication_response( transaction_id id, wifi_interface_handle iface, NanDataPathIndicationResponse *msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_nan_data_end(transaction_id id, wifi_interface_handle iface, NanDataPathEndRequest *msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_select_tx_power_scenario(wifi_interface_handle iface, wifi_power_scenario scenario) { ALOGD("%s", __func__); return WIFI_ERROR_NOT_SUPPORTED; } wifi_error skw_wifi_reset_tx_power_scenario(wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_ERROR_NOT_SUPPORTED; } /** * Returns the chipset's hardware filtering capabilities: * @param version pointer to version of the packet filter interpreter *                supported, filled in upon return. 0 indicates no support. * @param max_len pointer to maximum size of the filter bytecode, filled in *                upon return. */ wifi_error skw_wifi_get_packet_filter_capabilities(wifi_interface_handle handle, u32 *version, u32 *max_len) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**     * Programs the packet filter. * @param program pointer to the program byte-code. * @param len length of the program byte-code.     */ wifi_error skw_wifi_set_packet_filter(wifi_interface_handle handle, const u8 *program, u32 len) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_read_packet_filter(wifi_interface_handle handle, u32 src_offset, u8 *host_dst, u32 length) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_get_roaming_capabilities(wifi_interface_handle handle, wifi_roaming_capabilities *caps) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_enable_firmware_roaming(wifi_interface_handle handle, fw_roaming_state_t state) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_configure_roaming(wifi_interface_handle handle, wifi_roaming_config *roaming_config) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_set_radio_mode_change_handler(wifi_request_id id, wifi_interface_handle iface, wifi_radio_mode_change_handler eh) { ALOGD("%s", __func__); return WIFI_SUCCESS; } #if __ANDROID_API__ > __ANDROID_API_Q__ wifi_error skw_wifi_set_latency_mode(wifi_interface_handle iface, wifi_latency_mode mode) { ALOGD("%s", __func__); return WIFI_ERROR_NOT_SUPPORTED; } wifi_error skw_wifi_set_thermal_mitigation_mode(wifi_handle handle, wifi_thermal_mode mode, u32 completion_window) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_map_dscp_access_category(wifi_handle handle, u32 start, u32 end, u32 access_category) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_reset_dscp_mapping(wifi_handle handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } wifi_error skw_wifi_virtual_interface_create(wifi_handle handle, const char* ifname, wifi_interface_type iface_type) { ALOGD("%s: ifname: %s, type: 0x%x", __func__, ifname, iface_type); return WIFI_SUCCESS; } wifi_error skw_wifi_virtual_interface_delete(wifi_handle handle, const char* ifname) { ALOGD("%s: ifname: %s", __func__, ifname); return WIFI_SUCCESS; } wifi_error skw_wifi_set_subsystem_restart_handler(wifi_handle handle, wifi_subsystem_restart_handler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Allow vendor HAL to choose interface name when creating * an interface. This can be implemented by chips with their * own interface naming policy. * If not implemented, the default naming will be used. */ wifi_error skw_wifi_get_supported_iface_name(wifi_handle handle, u32 iface_type, char *name, size_t len) { return WIFI_ERROR_NOT_AVAILABLE; } /** * Perform early initialization steps that are needed when WIFI * is disabled. * If the function returns failure, it means the vendor HAL is unusable * (for example, if chip hardware is not installed) and no further * functions should be called. */ wifi_error skw_wifi_early_initialize(void) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Get supported feature set which are chip-global, that is * not dependent on any created interface. */ wifi_error skw_wifi_get_chip_feature_set(wifi_handle handle, feature_set *set) { ALOGD("%s: 0x%x", __func__, *set); #if 0 *set |= WIFI_FEATURE_INFRA; *set |= WIFI_FEATURE_INFRA_5G; *set |= WIFI_FEATURE_P2P; *set |= WIFI_FEATURE_SOFT_AP; #endif return WIFI_SUCCESS; } /** * Invoked to indicate that the provided iface is the primary STA iface when there are more * than 1 STA iface concurrently active. */ wifi_error skw_wifi_multi_sta_set_primary_connection(wifi_handle handle, wifi_interface_handle iface) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * When there are 2 simultaneous STA connections, this use case hint * indicates what STA + STA use-case is being enabled by the framework. */ wifi_error skw_wifi_multi_sta_set_use_case(wifi_handle handle, wifi_multi_sta_use_case use_case) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Invoked to indicate that the following list of wifi_coex_unsafe_channel should be avoided * with the specified restrictions. * @param unsafeChannels list of current |wifi_coex_unsafe_channel| to avoid. * @param restrictions bitmask of |wifi_coex_restriction| indicating wifi interfaces to * restrict from the current unsafe channels. */ wifi_error skw_wifi_set_coex_unsafe_channels(wifi_handle handle, u32 num_channels, wifi_coex_unsafe_channel *unsafeChannels, u32 restrictions) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Invoked to set voip optimization mode for the provided STA iface */ wifi_error skw_wifi_set_voip_mode(wifi_interface_handle iface, wifi_voip_mode mode) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_register_handler * Request to register TWT callback before sending any TWT request * @param wifi_interface_handle: * @param TwtCallbackHandler: callback function pointers * @return Synchronous wifi_error */ wifi_error skw_wifi_twt_register_handler(wifi_interface_handle iface, TwtCallbackHandler handler) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_get_capability * Request TWT capability * @param wifi_interface_handle: * @return Synchronous wifi_error and TwtCapabilitySet */ wifi_error skw_wifi_twt_get_capability(wifi_interface_handle iface, TwtCapabilitySet* twt_cap_set) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_setup_request * Request to send TWT setup frame * @param wifi_interface_handle: * @param TwtSetupRequest: detailed parameters of setup request * @return Synchronous wifi_error * @return Asynchronous EventTwtSetupResponse CB return TwtSetupResponse */ wifi_error skw_wifi_twt_setup_request(wifi_interface_handle iface, TwtSetupRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_teardown_request * Request to send TWT teardown frame * @param wifi_interface_handle: * @param TwtTeardownRequest: detailed parameters of teardown request * @return Synchronous wifi_error * @return Asynchronous EventTwtTeardownCompletion CB return TwtTeardownCompletion * TwtTeardownCompletion may also be received due to other events * like CSA, BTCX, TWT scheduler, MultiConnection, peer-initiated teardown, etc. */ wifi_error skw_wifi_twt_teardown_request(wifi_interface_handle iface, TwtTeardownRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_info_frame_request * Request to send TWT info frame * @param wifi_interface_handle: * @param TwtInfoFrameRequest: detailed parameters in info frame * @return Synchronous wifi_error * @return Asynchronous EventTwtInfoFrameReceived CB return TwtInfoFrameReceived * Driver may also receive Peer-initiated TwtInfoFrame */ wifi_error skw_wifi_twt_info_frame_request(wifi_interface_handle iface, TwtInfoFrameRequest* msg) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_get_stats * Request to get TWT stats * @param wifi_interface_handle: * @param config_id: configuration ID of TWT request * @return Synchronous wifi_error and TwtStats */ wifi_error skw_wifi_twt_get_stats(wifi_interface_handle iface, u8 config_id, TwtStats* stats) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief twt_clear_stats * Request to clear TWT stats * @param wifi_interface_handle: * @param config_id: configuration ID of TWT request * @return Synchronous wifi_error */ wifi_error skw_wifi_twt_clear_stats(wifi_interface_handle iface, u8 config_id) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Invoked to set DTIM configuration when the host is in the suspend mode * @param wifi_interface_handle: * @param multiplier: when STA in the power saving mode, the wake up interval will be set to * 1) multiplier * DTIM period if multiplier > 0. * 2) the device default value if multiplier <=0 * Some implementations may apply an additional cap to wake up interval in the case of 1). */ wifi_error skw_wifi_set_dtim_config(wifi_interface_handle handle, u32 multiplier) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /**@brief wifi_get_usable_channels * Request list of usable channels for the requested bands and modes. Usable * implies channel is allowed as per regulatory for the current country code * and not restricted due to other hard limitations (e.g. DFS, Coex) In * certain modes (e.g. STA+SAP) there could be other hard restrictions * since MCC operation many not be supported by SAP. This API also allows * driver to return list of usable channels for each mode uniquely to * distinguish cases where only a limited set of modes are allowed on * a given channel e.g. srd channels may be supported for P2P but not * for SAP or P2P-Client may be allowed on an indoor channel but P2P-GO * may not be allowed. This API is not interface specific and will be * used to query capabilities of driver in terms of what modes (STA, SAP, * P2P_CLI, P2P_GO, NAN, TDLS) can be supported on each of the channels. * @param handle global wifi_handle * @param band_mask BIT MASK of WLAN_MAC* as represented by |wlan_mac_band| * @param iface_mode_mask BIT MASK of BIT(WIFI_INTERFACE_*) represented by * |wifi_interface_mode|. Bitmask respresents all the modes that the * caller is interested in (e.g. STA, SAP, WFD-CLI, WFD-GO, TDLS, NAN). * Note: Bitmask does not represent concurrency matrix. If the caller * is interested in CLI, GO modes, the iface_mode_mask would be set * to WIFI_INTERFACE_P2P_CLIENT|WIFI_INTERFACE_P2P_GO. * @param filter_mask BIT MASK of WIFI_USABLE_CHANNEL_FILTER_* represented by * |wifi_usable_channel_filter|. Indicates if the channel list should * be filtered based on additional criteria. If filter_mask is not * specified, driver should return list of usable channels purely * based on regulatory constraints. * @param max_size maximum number of |wifi_usable_channel| * @param size actual number of |wifi_usable_channel| entries returned by driver * @param channels list of usable channels represented by |wifi_usable_channel| */ wifi_error skw_wifi_get_usable_channels(wifi_handle handle, u32 band_mask, u32 iface_mode_mask, u32 filter_mask, u32 max_size, u32* size, wifi_usable_channel* channels) { ALOGD("%s", __func__); return WIFI_SUCCESS; } /** * Trigger wifi subsystem restart to reload firmware */ wifi_error skw_wifi_trigger_subsystem_restart(wifi_handle handle) { ALOGD("%s", __func__); return WIFI_SUCCESS; } #endif static nl_sock *skw_create_socket(int port) { struct nl_sock * sock = NULL; uint32_t pid = getpid() & 0x3FFFFF; sock = nl_socket_alloc(); if (sock == NULL) { ALOGE("%s: socked alloc failed", __func__); return NULL; } nl_socket_set_local_port(sock, pid + (port << 22)); if (nl_connect(sock, NETLINK_GENERIC)) { ALOGE("%s: connect failed", __func__); nl_socket_free(sock); return NULL; } if (nl_socket_set_buffer_size(sock, SOCK_BUFF_SIZE, 0) < 0) ALOGE("cmd_sock: set RX buffer failed, %d", strerror(errno)); return sock; } class GetMulticastId : public WifiCommand { private: char *group; int mId; public: GetMulticastId(struct nl_sock *sk, int family, int flags, int nl80211_cmd) : WifiCommand(sk, family, flags, nl80211_cmd) { group = NULL; mId = -1; } virtual wifi_error build(wifi_interface_handle handle, void *param) { group = (char *)param; put_string(CTRL_ATTR_FAMILY_NAME, "nl80211"); return WIFI_SUCCESS; } virtual wifi_error parser(struct nlattr *attr[NL80211_ATTR_MAX]) { int i; struct nlattr *mcgrp; if (!attr[CTRL_ATTR_MCAST_GROUPS]) return WIFI_ERROR_UNKNOWN; skw_nla_for_each_nested(mcgrp, attr[CTRL_ATTR_MCAST_GROUPS], i) { struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (struct nlattr *)nla_data(mcgrp), nla_len(mcgrp), NULL); if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID] || strncmp((const char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]), group, nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0) continue; mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); break; }; return WIFI_SUCCESS; } int id() { return mId; } }; static int skw_get_multicast_id(struct nl_sock *sk, const char *group) { GetMulticastId cmd(sk, genl_ctrl_resolve(sk, "nlctrl"), 0, CTRL_CMD_GETFAMILY); if (cmd.build(NULL, (void *)group) == WIFI_SUCCESS) cmd.send(); return cmd.id(); } static int skw_add_membership(struct nl_sock *sk, const char *group) { int id = skw_get_multicast_id(sk, group); if (id < 0) { ALOGE("Could not find group %s", group); return id; } int ret = nl_socket_add_membership(sk, id); if (ret < 0) ALOGE("Could not add membership to group %s", group); return ret; } static int evtHandler(struct nl_msg *msg, void *arg) { ALOGD("%s", __func__); return NL_SKIP; } static wifi_error skw_wifi_event_init(hal_info *hal) { int err; hal->nl_event = skw_create_socket(WIFI_HAL_SOCK_EVENT_PORT); if (hal->nl_event == NULL) { ALOGE("%s: create event socket failed", __func__); return WIFI_ERROR_UNKNOWN; } //nl_socket_modify_cb(hal->nl_event, NL_CB_SEQ_CHECK, no_seq_check, &err); nl_socket_modify_cb(hal->nl_event, NL_CB_VALID, NL_CB_CUSTOM, evtHandler, &err); skw_add_membership(hal->nl_event, "scan"); skw_add_membership(hal->nl_event, "mlme"); skw_add_membership(hal->nl_event, "vendor"); skw_add_membership(hal->nl_event, "regulatory"); return WIFI_SUCCESS; } static void skw_wifi_event_deinit(hal_info *hal) { if (hal->nl_event) nl_socket_free(hal->nl_event); } static wifi_error skw_wifi_hal_init(hal_info *hal) { hal->nl_hal = skw_create_socket(WIFI_HAL_SOCK_DEFAULT_PORT); if (hal->nl_hal == NULL) { ALOGE("%s: create command socket failed", __func__); return WIFI_ERROR_UNKNOWN; } hal->family_nl80211 = genl_ctrl_resolve(hal->nl_hal, "nl80211"); if (hal->family_nl80211 < 0) { nl_socket_free(hal->nl_hal); ALOGE("%s: resolve nl80211 id failed", __func__); return WIFI_ERROR_UNKNOWN; } return WIFI_SUCCESS; } static void skw_wifi_hal_deinit(hal_info *hal) { if (hal->nl_hal) nl_socket_free(hal->nl_hal); } static wifi_error skw_wifi_initialize(wifi_handle *handle) { wifi_error err; hal_info *hal = NULL; ALOGD("%s", __func__); hal = (hal_info *)malloc(sizeof(hal_info)); if (hal == NULL) { ALOGE("%s: alloc hal_info failed", __func__); return WIFI_ERROR_OUT_OF_MEMORY; } memset(hal, 0, sizeof(*hal)); if (socketpair(AF_UNIX, SOCK_STREAM, 0, hal->exit_socks) == -1) { ALOGE("socketpair failed"); free(hal); return WIFI_ERROR_UNKNOWN; } err = skw_wifi_hal_init(hal); if (err != WIFI_SUCCESS) { free(hal); return err; } err = skw_wifi_event_init(hal); if (err != WIFI_SUCCESS) { skw_wifi_hal_deinit(hal); free(hal); return err; } *handle = (wifi_handle)hal; return WIFI_SUCCESS; } static void skw_wifi_deinitialize(wifi_handle handle) { hal_info *hal = (hal_info *)handle; if (hal->cleaned_up_handler) (*(hal->cleaned_up_handler))(handle); skw_wifi_hal_deinit(hal); skw_wifi_event_deinit(hal); if (hal->exit_socks[0]) close(hal->exit_socks[0]); if (hal->exit_socks[1]) close(hal->exit_socks[1]); free(hal); } void skw_wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler clean_handler) { hal_info *hal = (hal_info *)handle; ALOGD("%s", __func__); hal->cleaned_up_handler = clean_handler; hal->exit = true; TEMP_FAILURE_RETRY(write(hal->exit_socks[0], "exit", 4)); } static int skw_socket_handler(hal_info *hal, int events, struct nl_sock *sk) { int ret; struct nl_cb *cb = nl_socket_get_cb(sk); ret = nl_recvmsgs(sk, cb); nl_cb_put(cb); return ret; } static void skw_wifi_event_loop(wifi_handle handle) { pollfd fd[2]; hal_info *hal = (hal_info *)handle; ALOGD("%s", __func__); memset(&fd[0], 0, sizeof(fd)); fd[0].fd = nl_socket_get_fd(hal->nl_event); fd[0].events = POLLIN; fd[1].fd = hal->exit_socks[1]; fd[1].events = POLLIN; do { fd[0].revents = 0; fd[1].revents = 0; if (poll(fd, 2, -1) > 0) { if (fd[0].revents & POLLIN) { skw_socket_handler(hal, fd[0].revents, hal->nl_event); } } } while (!hal->exit); skw_wifi_deinitialize(handle); } #define POLL_DRIVER_DURATION_US (100000) #define POLL_DRIVER_MAX_TIME_MS (10000) static wifi_error skw_wifi_wait_for_driver_ready(void) { int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US; ALOGD("%s", __func__); do { if ((access("/sys/class/net/wlan0", F_OK)) == 0) return WIFI_SUCCESS; usleep(POLL_DRIVER_DURATION_US); } while(--count > 0); ALOGE("Time out waiting on Driver ready ... "); return WIFI_ERROR_TIMED_OUT; } wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) { if (!fn) { ALOGE("invalid parameter fn"); return WIFI_ERROR_UNINITIALIZED; } fn->wifi_initialize = skw_wifi_initialize; fn->wifi_wait_for_driver_ready = skw_wifi_wait_for_driver_ready; fn->wifi_cleanup = skw_wifi_cleanup; fn->wifi_event_loop = skw_wifi_event_loop; fn->wifi_get_error_info = skw_wifi_get_error_info; fn->wifi_get_supported_feature_set = skw_wifi_get_supported_feature_set; fn->wifi_get_concurrency_matrix = skw_wifi_get_concurrency_matrix; fn->wifi_set_scanning_mac_oui = skw_wifi_set_scanning_mac_oui; fn->wifi_get_supported_channels = skw_wifi_get_supported_channels; fn->wifi_is_epr_supported = skw_wifi_is_epr_supported; fn->wifi_get_ifaces = skw_wifi_get_ifaces; fn->wifi_get_iface_name = skw_wifi_get_iface_name; fn->wifi_set_iface_event_handler = skw_wifi_set_iface_event_handler; fn->wifi_reset_iface_event_handler = skw_wifi_reset_iface_event_handler; fn->wifi_start_gscan = skw_wifi_start_gscan; fn->wifi_stop_gscan = skw_wifi_stop_gscan; fn->wifi_get_cached_gscan_results = skw_wifi_get_cached_gscan_results; fn->wifi_set_bssid_hotlist = skw_wifi_set_bssid_hotlist; fn->wifi_reset_bssid_hotlist = skw_wifi_reset_bssid_hotlist; fn->wifi_set_significant_change_handler = skw_wifi_set_significant_change_handler; fn->wifi_reset_significant_change_handler = skw_wifi_reset_significant_change_handler; fn->wifi_get_gscan_capabilities = skw_wifi_get_gscan_capabilities; fn->wifi_set_link_stats = skw_wifi_set_link_stats; fn->wifi_get_link_stats = skw_wifi_get_link_stats; fn->wifi_clear_link_stats = skw_wifi_clear_link_stats; fn->wifi_get_valid_channels = skw_wifi_get_valid_channels; fn->wifi_rtt_range_request = skw_wifi_rtt_range_request; fn->wifi_rtt_range_cancel = skw_wifi_rtt_range_cancel; fn->wifi_get_rtt_capabilities = skw_wifi_get_rtt_capabilities; fn->wifi_rtt_get_responder_info = skw_wifi_rtt_get_responder_info; fn->wifi_enable_responder = skw_wifi_enable_responder; fn->wifi_disable_responder = skw_wifi_disable_responder; fn->wifi_set_nodfs_flag = skw_wifi_set_nodfs_flag; fn->wifi_start_logging = skw_wifi_start_logging; fn->wifi_set_epno_list = skw_wifi_set_epno_list; fn->wifi_reset_epno_list = skw_wifi_reset_epno_list; fn->wifi_set_country_code = skw_wifi_set_country_code; fn->wifi_get_firmware_memory_dump = skw_wifi_get_firmware_memory_dump; fn->wifi_set_log_handler = skw_wifi_set_log_handler; fn->wifi_reset_log_handler = skw_wifi_reset_log_handler; fn->wifi_set_alert_handler = skw_wifi_set_alert_handler; fn->wifi_reset_alert_handler = skw_wifi_reset_alert_handler; fn->wifi_get_firmware_version = skw_wifi_get_firmware_version; fn->wifi_get_ring_buffers_status = skw_wifi_get_ring_buffers_status; fn->wifi_get_logger_supported_feature_set = skw_wifi_get_logger_supported_feature_set; fn->wifi_get_ring_data = skw_wifi_get_ring_data; fn->wifi_enable_tdls = skw_wifi_enable_tdls; fn->wifi_disable_tdls = skw_wifi_disable_tdls; fn->wifi_get_tdls_status = skw_wifi_get_tdls_status; fn->wifi_get_tdls_capabilities = skw_wifi_get_tdls_capabilities; fn->wifi_get_driver_version = skw_wifi_get_driver_version; fn->wifi_set_passpoint_list = skw_wifi_set_passpoint_list; fn->wifi_reset_passpoint_list = skw_wifi_reset_passpoint_list; fn->wifi_set_lci = skw_wifi_set_lci; fn->wifi_set_lcr = skw_wifi_set_lcr; // fn->wifi_start_sending_offloaded_packet = skw_wifi_start_sending_offloaded_packet; fn->wifi_stop_sending_offloaded_packet = skw_wifi_stop_sending_offloaded_packet; fn->wifi_start_rssi_monitoring = skw_wifi_start_rssi_monitoring; fn->wifi_stop_rssi_monitoring = skw_wifi_stop_rssi_monitoring; fn->wifi_get_wake_reason_stats = skw_wifi_get_wake_reason_stats; fn->wifi_configure_nd_offload = skw_wifi_configure_nd_offload; fn->wifi_get_driver_memory_dump = skw_wifi_get_driver_memory_dump; fn->wifi_start_pkt_fate_monitoring = skw_wifi_start_pkt_fate_monitoring; fn->wifi_get_tx_pkt_fates = skw_wifi_get_tx_pkt_fates; fn->wifi_get_rx_pkt_fates = skw_wifi_get_rx_pkt_fates; fn->wifi_nan_enable_request = skw_wifi_nan_enable_request; fn->wifi_nan_disable_request = skw_wifi_nan_disable_request; fn->wifi_nan_publish_request = skw_wifi_nan_publish_request; fn->wifi_nan_publish_cancel_request = skw_wifi_nan_publish_cancel_request; fn->wifi_nan_subscribe_request = skw_wifi_nan_subscribe_request; fn->wifi_nan_subscribe_cancel_request = skw_wifi_nan_subscribe_cancel_request; fn->wifi_nan_transmit_followup_request = skw_wifi_nan_transmit_followup_request; fn->wifi_nan_stats_request = skw_wifi_nan_stats_request; fn->wifi_nan_config_request = skw_wifi_nan_config_request; fn->wifi_nan_tca_request = skw_wifi_nan_tca_request; fn->wifi_nan_beacon_sdf_payload_request = skw_wifi_nan_beacon_sdf_payload_request; fn->wifi_nan_register_handler = skw_wifi_nan_register_handler; fn->wifi_nan_get_version = skw_wifi_nan_get_version; fn->wifi_nan_get_capabilities = skw_wifi_nan_get_capabilities; fn->wifi_nan_data_interface_create = skw_wifi_nan_data_interface_create; fn->wifi_nan_data_interface_delete = skw_wifi_nan_data_interface_delete; fn->wifi_nan_data_request_initiator = skw_wifi_nan_data_request_initiator; fn->wifi_nan_data_indication_response = skw_wifi_nan_data_indication_response; fn->wifi_nan_data_end = skw_wifi_nan_data_end; fn->wifi_select_tx_power_scenario = skw_wifi_select_tx_power_scenario; fn->wifi_reset_tx_power_scenario = skw_wifi_reset_tx_power_scenario; fn->wifi_get_packet_filter_capabilities = skw_wifi_get_packet_filter_capabilities; fn->wifi_set_packet_filter = skw_wifi_set_packet_filter; fn->wifi_read_packet_filter = skw_wifi_read_packet_filter; fn->wifi_get_roaming_capabilities = skw_wifi_get_roaming_capabilities; fn->wifi_enable_firmware_roaming = skw_wifi_enable_firmware_roaming; fn->wifi_configure_roaming = skw_wifi_configure_roaming; fn->wifi_set_radio_mode_change_handler = skw_wifi_set_radio_mode_change_handler; #if __ANDROID_API__ > __ANDROID_API_Q__ fn->wifi_set_latency_mode = skw_wifi_set_latency_mode; fn->wifi_set_thermal_mitigation_mode = skw_wifi_set_thermal_mitigation_mode; fn->wifi_map_dscp_access_category = skw_wifi_map_dscp_access_category; fn->wifi_reset_dscp_mapping = skw_wifi_reset_dscp_mapping; fn->wifi_virtual_interface_create = skw_wifi_virtual_interface_create; fn->wifi_virtual_interface_delete = skw_wifi_virtual_interface_delete; fn->wifi_set_subsystem_restart_handler = skw_wifi_set_subsystem_restart_handler; fn->wifi_get_supported_iface_name = skw_wifi_get_supported_iface_name; fn->wifi_early_initialize = skw_wifi_early_initialize; fn->wifi_get_chip_feature_set = skw_wifi_get_chip_feature_set; fn->wifi_multi_sta_set_primary_connection = skw_wifi_multi_sta_set_primary_connection; fn->wifi_multi_sta_set_use_case = skw_wifi_multi_sta_set_use_case; fn->wifi_set_coex_unsafe_channels = skw_wifi_set_coex_unsafe_channels; fn->wifi_set_voip_mode = skw_wifi_set_voip_mode; fn->wifi_twt_register_handler = skw_wifi_twt_register_handler; fn->wifi_twt_get_capability = skw_wifi_twt_get_capability; fn->wifi_twt_setup_request = skw_wifi_twt_setup_request; fn->wifi_twt_teardown_request = skw_wifi_twt_teardown_request; fn->wifi_twt_info_frame_request = skw_wifi_twt_info_frame_request; fn->wifi_twt_get_stats = skw_wifi_twt_get_stats; fn->wifi_twt_clear_stats = skw_wifi_twt_clear_stats; fn->wifi_set_dtim_config = skw_wifi_set_dtim_config; fn->wifi_get_usable_channels = skw_wifi_get_usable_channels; fn->wifi_trigger_subsystem_restart = skw_wifi_trigger_subsystem_restart; #endif return WIFI_SUCCESS; }