#include #include #include #include #include #include "sprdwl.h" #include "wl_core.h" #define SOFTAP_INI_PATH "/data/misc/wifi/softap.ini" static bool is_valid_channel(struct wiphy *wiphy, int chn) { int i; struct ieee80211_supported_band *bands; if (chn < 15) { if (chn < 1) return false; return true; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) bands = wiphy->bands[NL80211_BAND_5GHZ]; #else bands = wiphy->bands[IEEE80211_BAND_5GHZ]; #endif for (i = 0; i < bands->n_channels; i++) if (chn == bands->channels[i].hw_value) return true; return false; } static int sprdwl_get_softap_chan(u8 *path) { int ret; int chn; struct file *fp = NULL; #ifdef setfs mm_segment_t fs; #endif char buf[64] = {0}; if (path == NULL) return -EINVAL; fp = filp_open(path, O_RDONLY, 0); if (IS_ERR(fp)) { wl_err("Open file: %s failed(%ld)\n", path, PTR_ERR(fp)); return -EINVAL; } #ifdef setfs fs = get_fs(); set_fs(get_ds()); #endif ret = kernel_read(fp, buf, sizeof(buf), &fp->f_pos); filp_close(fp, NULL); #ifdef setfs set_fs(fs); #endif if (ret <= 0) { wl_err("read file failed, ret = %d\n", ret); return -EINVAL; } ret = sscanf(buf, "channel=%d\n", &chn); if (ret != 1) { wl_err("Keywords channel not found in %s\n", path); return -EINVAL; } return chn; } void sprdwl_hook_reset_channel(struct wiphy *wiphy, struct cfg80211_ap_settings *settings) { u8 *ie, *ds_param_ch; int channel = 1; struct ieee80211_mgmt *mgmt; struct ieee80211_ht_operation *oper; /* Read channel from file /data/misc/wifi/softap.ini */ channel = sprdwl_get_softap_chan(SOFTAP_INI_PATH); if (channel < 0) return; if (!is_valid_channel(wiphy, channel)) { wl_err("%s channel(%d) invalid\n", __func__, channel); return; } mgmt = (struct ieee80211_mgmt *)settings->beacon.head; ie = (u8 *)cfg80211_find_ie(WLAN_EID_DS_PARAMS, &mgmt->u.beacon.variable[0], settings->beacon.head_len); if (ie == NULL) { wl_err("IE WLAN_EID_DS_PARAMS not found in beacon\n"); return; } ds_param_ch = ie + 2; ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_OPERATION, settings->beacon.tail, settings->beacon.tail_len); if (ie == NULL) { wl_err("IE WLAN_EID_HT_OPERATION not found in beacon\n"); return; } ie += 2; oper = (struct ieee80211_ht_operation *)ie; wl_info("%s done, reset channel %d -> %d\n", __func__, oper->primary_chan, channel); *ds_param_ch = oper->primary_chan = channel; }