-
#include <linux/module.h>
#include <linux/netdevice.h>
#include <net/netlink.h>
#include <linux/if_arp.h>
#include <asm/uaccess.h>
#include <linux/wireless.h>
+#if defined(WL_WIRELESS_EXT)
#include <wl_iw.h>
+#endif
#include <wldev_common.h>
#include <wlioctl.h>
#include <bcmutils.h>
#ifdef WL_CFG80211
#include <wl_cfg80211.h>
#endif
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif
#ifndef WL_CFG80211
#define htod32(i) i
#define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM"
#ifdef WL_EXT_IAPSTA
+#include <net/rtnetlink.h>
#define CMD_IAPSTA_INIT "IAPSTA_INIT"
#define CMD_IAPSTA_CONFIG "IAPSTA_CONFIG"
#define CMD_IAPSTA_ENABLE "IAPSTA_ENABLE"
#define CMD_ISAM_CONFIG "ISAM_CONFIG"
#define CMD_ISAM_ENABLE "ISAM_ENABLE"
#define CMD_ISAM_DISABLE "ISAM_DISABLE"
+#define CMD_ISAM_STATUS "ISAM_STATUS"
#ifdef PROP_TXSTATUS
#ifdef PROP_TXSTATUS_VSDB
#include <dhd_wlfc.h>
#define CMD_DHCPC_ENABLE "DHCPC_ENABLE"
#define CMD_DHCPC_DUMP "DHCPC_DUMP"
#endif
+#define CMD_AUTOCHANNEL "AUTOCHANNEL"
#define CMD_WL "WL"
int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
}
#ifdef WL_EXT_IAPSTA
-static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len);
+typedef enum IF_STATE {
+ IF_STATE_INIT = 1,
+ IF_STATE_DISALBE,
+ IF_STATE_ENABLE
+} if_state_t;
+
+typedef enum APSTAMODE {
+ ISTAONLY_MODE = 1,
+ IAPONLY_MODE,
+ IAPSTA_MODE,
+ IDUALAP_MODE,
+ ISTAAPAP_MODE,
+ IMESHONLY_MODE,
+ IMESHSTA_MODE,
+ IMESHAP_MODE,
+ IMESHAPSTA_MODE,
+ IMESHAPAP_MODE,
+ IGOSTA_MODE
+} apstamode_t;
+
+typedef enum IFMODE {
+ ISTA_MODE = 1,
+ IAP_MODE,
+ IMESH_MODE
+} ifmode_t;
+
+typedef enum BGNMODE {
+ IEEE80211B = 1,
+ IEEE80211G,
+ IEEE80211BG,
+ IEEE80211BGN,
+ IEEE80211BGNAC
+} bgnmode_t;
+
+typedef enum AUTHMODE {
+ AUTH_OPEN,
+ AUTH_SHARED,
+ AUTH_WPAPSK,
+ AUTH_WPA2PSK,
+ AUTH_WPAWPA2PSK,
+ AUTH_SAE
+} authmode_t;
+
+typedef enum ENCMODE {
+ ENC_NONE,
+ ENC_WEP,
+ ENC_TKIP,
+ ENC_AES,
+ ENC_TKIPAES
+} encmode_t;
+
+enum wl_if_list {
+ IF_PIF,
+ IF_VIF,
+ IF_VIF2,
+ MAX_IF_NUM
+};
+
+typedef enum WL_PRIO {
+ PRIO_AP,
+ PRIO_MESH,
+ PRIO_STA
+}wl_prio_t;
+
+typedef struct wl_if_info {
+ struct net_device *dev;
+ if_state_t ifstate;
+ ifmode_t ifmode;
+ char prefix;
+ wl_prio_t prio;
+ int ifidx;
+ uint8 bssidx;
+ char ifname[IFNAMSIZ+1];
+ char ssid[DOT11_MAX_SSID_LEN];
+ struct ether_addr bssid;
+ bgnmode_t bgnmode;
+ int hidden;
+ int maxassoc;
+ uint16 channel;
+ authmode_t amode;
+ encmode_t emode;
+ char key[100];
+} wl_if_info_t;
+
+#define CSA_FW_BIT (1<<0)
+#define CSA_DRV_BIT (1<<1)
+
+typedef struct wl_apsta_params {
+ struct wl_if_info if_info[MAX_IF_NUM];
+ int ioctl_ver;
+ bool init;
+ bool rsdb;
+ bool vsdb;
+ uint csa;
+ apstamode_t apstamode;
+ bool netif_change;
+ wait_queue_head_t netif_change_event;
+} wl_apsta_params_t;
+
+static int wl_ext_enable_iface(struct net_device *dev, char *ifname);
int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
- void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
+ void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx,
+ struct mutex* buf_sync)
{
int ret;
return ret;
}
-
-int wl_ext_iovar_getbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
- void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
-{
- int ret;
-
- ret = wldev_iovar_getbuf_bsscfg(dev, iovar_name, param, paramlen,
- buf, buflen, bsscfg_idx, buf_sync);
- if (ret < 0)
- ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret));
-
- return ret;
-}
#endif
/* Return a legacy chanspec given a new chanspec
return chanspec;
}
+#if defined(WL_EXT_IAPSTA) || defined(WL_CFG80211) || defined(WL_ESCAN)
+static chanspec_t
+wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+ chanspec_t chspec;
+
+ /* get the channel number */
+ chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+ /* convert the band */
+ if (LCHSPEC_IS2G(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BAND_2G;
+ } else {
+ chspec |= WL_CHANSPEC_BAND_5G;
+ }
+
+ /* convert the bw and sideband */
+ if (LCHSPEC_IS20(legacy_chspec)) {
+ chspec |= WL_CHANSPEC_BW_20;
+ } else {
+ chspec |= WL_CHANSPEC_BW_40;
+ if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+ chspec |= WL_CHANSPEC_CTL_SB_L;
+ } else {
+ chspec |= WL_CHANSPEC_CTL_SB_U;
+ }
+ }
+
+ if (wf_chspec_malformed(chspec)) {
+ ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+ chspec));
+ return INVCHANSPEC;
+ }
+
+ return chspec;
+}
+
+static chanspec_t
+wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
+{
+ chanspec = dtohchanspec(chanspec);
+ if (ioctl_ver == 1) {
+ chanspec = wl_ext_chspec_from_legacy(chanspec);
+ }
+
+ return chanspec;
+}
+#endif
+
static int
wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
{
}
static int
-wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chspec)
+wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
+ uint16 channel, chanspec_t *ret_chspec)
{
s32 _chan = channel;
chanspec_t chspec = 0;
u32 bw_cap;
} param = {0, 0};
uint band;
- int ioctl_ver = 0;
if (_chan <= CH_MAX_2G_CHANNEL)
band = IEEE80211_BAND_2GHZ;
else
band = IEEE80211_BAND_5GHZ;
- wl_ext_get_ioctl_ver(dev, &ioctl_ver);
if (band == IEEE80211_BAND_5GHZ) {
param.band = WLC_BAND_5G;
wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
printf("%s: channel %d\n", __FUNCTION__, _chan);
} else if (err) {
- ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err));
+ ANDROID_ERROR(("%s: failed to set chanspec error %d\n",
+ __FUNCTION__, err));
} else
- printf("%s: channel %d, 0x%x\n", __FUNCTION__, channel, chspec);
+ printf("%s: %s channel %d, 0x%x\n", __FUNCTION__,
+ dev->name, channel, chspec);
} else {
- ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", __FUNCTION__));
+ ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+ __FUNCTION__));
err = BCME_ERROR;
}
} else {
channel_info_t ci;
int bytes_written = 0;
chanspec_t fw_chspec;
+ int ioctl_ver = 0;
ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command));
sscanf(command, "%*s %d", &channel);
if (channel > 0) {
- ret = wl_ext_set_chanspec(dev, channel, &fw_chspec);
+ wl_ext_get_ioctl_ver(dev, &ioctl_ver);
+ ret = wl_ext_set_chanspec(dev, ioctl_ver, channel, &fw_chspec);
} else {
- if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
+ if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci,
+ sizeof(channel_info_t), FALSE))) {
ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel));
ANDROID_TRACE(("target_channel %d\n", ci.target_channel));
ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel));
- bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel);
+ bytes_written = snprintf(command, sizeof(channel_info_t)+2,
+ "channel %d", ci.hw_channel);
ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
ret = bytes_written;
}
memset(valid_chan_list, 0, sizeof(valid_chan_list));
list = (wl_uint32_list_t *)(void *) valid_chan_list;
list->count = htod32(WL_NUMCHANNELS);
- ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0);
+ ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), 0);
if (ret<0) {
ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
} else {
bytes_written = snprintf(command, total_len, "channels");
for (i = 0; i < dtoh32(list->count); i++) {
- bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i]));
+ bytes_written += snprintf(command+bytes_written, total_len, " %d",
+ dtoh32(list->element[i]));
printf("%d ", dtoh32(list->element[i]));
}
printf("\n");
if (roam_trigger[0]) {
roam_trigger[1] = WLC_BAND_ALL;
- ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 1);
+ ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 1);
if (ret)
- ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
} else {
roam_trigger[1] = WLC_BAND_2G;
- ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+ ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 0);
if (!ret)
trigger[0] = roam_trigger[0];
else
- ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
roam_trigger[1] = WLC_BAND_5G;
- ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+ ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+ sizeof(roam_trigger), 0);
if (!ret)
trigger[1] = roam_trigger[0];
else
- ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+ ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+ roam_trigger[0], ret));
ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1]));
bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]);
} else {
if (id < 0)
id = 0;
- ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL);
+ ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
+ sizeof(buf), NULL);
if (ret) {
goto exit;
} else {
}
printf("\n");
}
- bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", dtoh32(mkeep_alive_pktp->period_msec));
+ bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ",
+ dtoh32(mkeep_alive_pktp->period_msec));
bytes_written += snprintf(command+bytes_written, total_len, "0x");
for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
- bytes_written += snprintf(command+bytes_written, total_len, "%x", mkeep_alive_pktp->data[i]);
+ bytes_written += snprintf(command+bytes_written, total_len, "%x",
+ mkeep_alive_pktp->data[i]);
}
ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
ret = bytes_written;
return 0;
}
+static void
+wl_ext_get_amode(struct wl_if_info *cur_if, char *amode)
+{
+ struct net_device *dev = cur_if->dev;
+ int auth=-1, wpa_auth=-1;
+
+ wl_ext_iovar_getint(dev, "auth", &auth);
+ wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (auth == 0 && wpa_auth == 0) {
+ strcpy(amode, "open");
+ } else if (auth == 0 && wpa_auth == 128) {
+ strcpy(amode, "sae");
+ }
+ } else if (auth == 0 && wpa_auth == 0) {
+ strcpy(amode, "open");
+ } else if (auth == 1 && wpa_auth == 0) {
+ strcpy(amode, "shared");
+ } else if (auth == 0 && wpa_auth == 4) {
+ strcpy(amode, "wpapsk");
+ } else if (auth == 0 && wpa_auth == 128) {
+ strcpy(amode, "wpa2psk");
+ } else if (auth == 0 && wpa_auth == 132) {
+ strcpy(amode, "wpawpa2psk");
+ }
+}
+
+static void
+wl_ext_get_emode(struct wl_if_info *cur_if, char *emode)
+{
+ struct net_device *dev = cur_if->dev;
+ int wsec=0;
+
+ wl_ext_iovar_getint(dev, "wsec", &wsec);
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (wsec == 0) {
+ strcpy(emode, "none");
+ } else {
+ strcpy(emode, "sae");
+ }
+ } else if (wsec == 0) {
+ strcpy(emode, "none");
+ } else if (wsec == 1) {
+ strcpy(emode, "wep");
+ } else if (wsec == 2 || wsec == 10) {
+ strcpy(emode, "tkip");
+ } else if (wsec == 4 || wsec == 12) {
+ strcpy(emode, "aes");
+ } else if (wsec == 6 || wsec == 14) {
+ strcpy(emode, "tkipaes");
+ }
+}
+
static int
-wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params)
+wl_ext_set_amode(struct wl_if_info *cur_if)
{
struct net_device *dev = cur_if->dev;
authmode_t amode = cur_if->amode;
int auth=0, wpa_auth=0;
- if (amode == AUTH_OPEN) {
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (amode == AUTH_SAE) {
+ auth = 0;
+ wpa_auth = 128;
+ ANDROID_INFO(("%s: Authentication: SAE\n", __FUNCTION__));
+ } else {
+ auth = 0;
+ wpa_auth = 0;
+ ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
+ }
+ } else if (amode == AUTH_OPEN) {
auth = 0;
wpa_auth = 0;
- ANDROID_TRACE(("%s: Authentication: Open System\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
} else if (amode == AUTH_SHARED) {
auth = 1;
wpa_auth = 0;
- ANDROID_TRACE(("%s: Authentication: Shared Key\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: Shared Key\n", __FUNCTION__));
} else if (amode == AUTH_WPAPSK) {
auth = 0;
wpa_auth = 4;
- ANDROID_TRACE(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
} else if (amode == AUTH_WPA2PSK) {
auth = 0;
wpa_auth = 128;
- ANDROID_TRACE(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
} else if (amode == AUTH_WPAWPA2PSK) {
auth = 0;
wpa_auth = 132;
- ANDROID_TRACE(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
}
if (cur_if->ifmode == IMESH_MODE) {
s32 val = WL_BSSTYPE_MESH;
encmode_t emode = cur_if->emode;
char *key = cur_if->key;
s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct dhd_pub *dhd = dhd_get_pub(dev);
memset(&wsec_key, 0, sizeof(wsec_key));
memset(&psk, 0, sizeof(psk));
- if (emode == ENC_NONE) {
+
+ if (cur_if->ifmode == IMESH_MODE) {
+ if (amode == AUTH_SAE) {
+ wsec = 4;
+ ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+ } else {
+ wsec = 0;
+ ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
+ }
+ } else if (emode == ENC_NONE) {
wsec = 0;
- ANDROID_TRACE(("%s: Encryption: No securiy\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
} else if (emode == ENC_WEP) {
wsec = 1;
wl_ext_parse_wep(key, &wsec_key);
- ANDROID_TRACE(("%s: Encryption: WEP\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
+ ANDROID_INFO(("%s: Encryption: WEP\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
} else if (emode == ENC_TKIP) {
wsec = 2;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: TKIP\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
- } else if (emode == ENC_AES) {
+ ANDROID_INFO(("%s: Encryption: TKIP\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ } else if (emode == ENC_AES || amode == AUTH_SAE) {
wsec = 4;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: AES\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
} else if (emode == ENC_TKIPAES) {
wsec = 6;
psk.key_len = strlen(key);
psk.flags = WSEC_PASSPHRASE;
memcpy(psk.key, key, strlen(key));
- ANDROID_TRACE(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
- ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ ANDROID_INFO(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+ }
+ if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
+ apsta_params->apstamode == IAPSTA_MODE) {
+ wsec |= 0x8; // terence 20180628: fix me, this is a workaround
}
wl_ext_iovar_setint(dev, "wsec", wsec);
if (cur_if->ifmode == IMESH_MODE) {
- if (amode == AUTH_WPA2PSK && emode == ENC_AES) {
+ if (amode == AUTH_SAE) {
+ ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, key));
wl_ext_iovar_setint(dev, "mesh_auth_proto", 1);
wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
wl_ext_iovar_setbuf(dev, "sae_password", key, strlen(key),
return 0;
}
+static uint16
+wl_ext_get_chan(struct net_device *dev)
+{
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ int ret = 0;
+ uint16 chan = 0, ctl_chan;
+ struct ether_addr bssid;
+ u32 chanspec = 0;
+
+ ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
+ if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
+ if (wldev_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
+ chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
+ ctl_chan = wf_chspec_ctlchan(chanspec);
+ chan = (u16)(ctl_chan & 0x00FF);
+ ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__,
+ chan, chanspec));
+ return chan;
+ }
+ }
+
+ return 0;
+}
+
+static chanspec_t
+wl_ext_get_chanspec(struct wl_apsta_params *apsta_params,
+ struct net_device *dev, uint16 channel)
+{
+ s32 _chan = channel;
+ chanspec_t chspec = 0;
+ chanspec_t fw_chspec = 0;
+ u32 bw = WL_CHANSPEC_BW_20;
+ s32 err = BCME_OK;
+ s32 bw_cap = 0;
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct {
+ u32 band;
+ u32 bw_cap;
+ } param = {0, 0};
+ uint band;
+
+ if (_chan <= CH_MAX_2G_CHANNEL)
+ band = IEEE80211_BAND_2GHZ;
+ else
+ band = IEEE80211_BAND_5GHZ;
+
+ if (band == IEEE80211_BAND_5GHZ) {
+ param.band = WLC_BAND_5G;
+ err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ ANDROID_ERROR(("bw_cap failed, %d\n", err));
+ return err;
+ } else {
+ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ if (bw_cap != WLC_N_BW_20ALL)
+ bw = WL_CHANSPEC_BW_40;
+ }
+ } else {
+ if (WL_BW_CAP_80MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
+ }
+ }
+ else if (band == IEEE80211_BAND_2GHZ)
+ bw = WL_CHANSPEC_BW_20;
+
+set_channel:
+ chspec = wf_channel2chspec(_chan, bw);
+ if (wf_chspec_valid(chspec)) {
+ fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec);
+ if (fw_chspec == INVCHANSPEC) {
+ ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+ __FUNCTION__));
+ fw_chspec = 0;
+ }
+ } else {
+ if (bw == WL_CHANSPEC_BW_80)
+ bw = WL_CHANSPEC_BW_40;
+ else if (bw == WL_CHANSPEC_BW_40)
+ bw = WL_CHANSPEC_BW_20;
+ else
+ bw = 0;
+ if (bw)
+ goto set_channel;
+ ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec));
+ err = BCME_ERROR;
+ }
+
+ return fw_chspec;
+}
+
static void
wl_ext_ch_to_chanspec(int ch, struct wl_join_params *join_params,
size_t *join_params_size)
}
}
-static chanspec_t
-wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
-{
- chanspec_t chspec;
-
- /* get the channel number */
- chspec = LCHSPEC_CHANNEL(legacy_chspec);
-
- /* convert the band */
- if (LCHSPEC_IS2G(legacy_chspec)) {
- chspec |= WL_CHANSPEC_BAND_2G;
- } else {
- chspec |= WL_CHANSPEC_BAND_5G;
- }
-
- /* convert the bw and sideband */
- if (LCHSPEC_IS20(legacy_chspec)) {
- chspec |= WL_CHANSPEC_BW_20;
- } else {
- chspec |= WL_CHANSPEC_BW_40;
- if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
- chspec |= WL_CHANSPEC_CTL_SB_L;
- } else {
- chspec |= WL_CHANSPEC_CTL_SB_U;
- }
- }
-
- if (wf_chspec_malformed(chspec)) {
- ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
- chspec));
- return INVCHANSPEC;
- }
-
- return chspec;
-}
-
-static chanspec_t
-wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
-{
- chanspec = dtohchanspec(chanspec);
- if (ioctl_ver == 1) {
- chanspec = wl_ext_chspec_from_legacy(chanspec);
- }
-
- return chanspec;
-}
-
static s32
wl_ext_connect(struct wl_if_info *cur_if)
{
err = -ENOMEM;
goto exit;
}
- ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), strlen(cur_if->ssid));
+ ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID),
+ strlen(cur_if->ssid));
memcpy(&ext_join_params->ssid.SSID, cur_if->ssid, ext_join_params->ssid.SSID_len);
ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
/* increate dwell time to receive probe response or detect Beacon
ext_join_params->ssid.SSID_len));
}
- err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params, join_params_size,
- iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
+ err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params,
+ join_params_size, iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cur_if->channel,
}
+static void
+wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
+ bool need_rtnl_unlock)
+{
+ if (need_rtnl_unlock)
+ rtnl_unlock();
+ wait_event_interruptible_timeout(apsta_params->netif_change_event,
+ apsta_params->netif_change, msecs_to_jiffies(1500));
+ if (need_rtnl_unlock)
+ rtnl_lock();
+}
+
static void
wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params)
{
struct dhd_pub *dhd;
+ apstamode_t apstamode = apsta_params->apstamode;
wl_interface_create_t iface;
struct wl_if_info *cur_if;
wlc_ssid_t ssid = { 0, {0} };
wl_country_t cspec = {{0}, 0, {0}};
wl_p2p_if_t ifreq;
s32 val = 0;
- int i, dfs = 1;
+ int i, dfs = 1, pm = 0;
dhd = dhd_get_pub(dev);
- if (!strlen(apsta_params->if_info[IF_VIF].ifname))
- strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
- if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
- strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
-
for (i=0; i<MAX_IF_NUM; i++) {
cur_if = &apsta_params->if_info[i];
+ if (i == 1 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan1");
+ if (i == 2 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan2");
if (cur_if->ifmode == ISTA_MODE) {
cur_if->channel = 0;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_sta", i);
+ cur_if->prio = PRIO_STA;
+ cur_if->prefix = 'S';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
} else if (cur_if->ifmode == IAP_MODE) {
cur_if->channel = 1;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_ap", i);
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'A';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
dfs = 0;
} else if (cur_if->ifmode == IMESH_MODE) {
cur_if->channel = 1;
cur_if->maxassoc = -1;
cur_if->ifstate = IF_STATE_INIT;
- snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_mesh", i);
+ cur_if->prio = PRIO_MESH;
+ cur_if->prefix = 'M';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
dfs = 0;
}
}
- if (dfs == 0) {
+
+ if (!dfs && !apsta_params->vsdb) {
dhd_conf_get_country(dhd, &cspec);
- if (!dhd_conf_map_country_list(dhd, &cspec, 1)) {
+ if (!dhd_conf_map_country_list(dhd, &cspec)) {
dhd_conf_set_country(dhd, &cspec);
dhd_bus_country_set(dev, &cspec, TRUE);
}
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "dfs_chan_disable", 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ }
+
+ if (FW_SUPPORTED(dhd, rsdb)) {
+ if (apstamode == IDUALAP_MODE)
+ apsta_params->rsdb = TRUE;
+ else if (apstamode == ISTAAPAP_MODE)
+ apsta_params->rsdb = FALSE;
+ if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE ||
+ apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE ||
+ apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE ||
+ apstamode == IMESHAPAP_MODE) {
+ wl_config_t rsdb_mode_cfg = {0, 0};
+ if (apsta_params->rsdb)
+ rsdb_mode_cfg.config = 1;
+ printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
+ sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ }
+ } else {
+ apsta_params->rsdb = FALSE;
}
- if (apsta_params->apstamode == ISTAONLY_MODE) {
+ if (apstamode == ISTAONLY_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
- } else if (apsta_params->apstamode == IAPONLY_MODE) {
+ } else if (apstamode == IAPONLY_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
#endif
#endif /* PROP_TXSTATUS_VSDB */
}
- else if (apsta_params->apstamode == IAPSTA_MODE) {
+ else if (apstamode == IAPSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ apsta_params->netif_change = FALSE;
if (FW_SUPPORTED(dhd, rsdb)) {
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface,
+ sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL);
} else {
- wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf,
- WLC_IOCTL_SMLEN, 1, NULL);
+ wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
+ iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
}
- apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IDUALAP_MODE) {
+ else if (apstamode == IDUALAP_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
/* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
#ifdef ARP_OFFLOAD_SUPPORT
dhd_arp_offload_enable(dhd, FALSE);
#endif /* ARP_OFFLOAD_SUPPORT */
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 0);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
val = 1;
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHONLY_MODE) {
+ else if (apstamode == ISTAAPAP_MODE) {
+ u8 rand_bytes[2] = {0, };
+ get_random_bytes(&rand_bytes, sizeof(rand_bytes));
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbss", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
- // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
- }
- else if (apsta_params->apstamode == IMESHSTA_MODE) {
- wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
- wl_ext_iovar_setint(dev, "mpc", 0);
- wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
- iface.flags = WL_INTERFACE_CREATE_STA;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
+ iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+ memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ iface.mac_addr.octet[0] |= 0x02;
+ iface.mac_addr.octet[5] += 0x01;
+ memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
- }
- else if (apsta_params->apstamode == IMESHAP_MODE) {
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ bzero(&iface, sizeof(wl_interface_create_t));
+ iface.ver = WL_INTERFACE_CREATE_VER;
+ iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+ memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+ iface.mac_addr.octet[0] |= 0x02;
+ iface.mac_addr.octet[5] += 0x02;
+ memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+ apsta_params->netif_change = FALSE;
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ }
+ else if (apstamode == IMESHONLY_MODE) {
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
+ }
+ else if (apstamode == IMESHSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
+ wl_ext_iovar_setint(dev, "apsta", 1);
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+ bzero(&iface, sizeof(wl_interface_create_t));
+ iface.ver = WL_INTERFACE_CREATE_VER;
+ iface.flags = WL_INTERFACE_CREATE_STA;
+ apsta_params->netif_change = FALSE;
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
+ }
+ else if (apstamode == IMESHAP_MODE) {
+ wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+ wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHAPSTA_MODE) {
+ else if (apstamode == IMESHAPSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_STA;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IMESHAPAP_MODE) {
+ else if (apstamode == IMESHAPAP_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "mpc", 0);
+ wl_ext_iovar_setint(dev, "mbcn", 1);
wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+ wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
// don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
bzero(&iface, sizeof(wl_interface_create_t));
iface.ver = WL_INTERFACE_CREATE_VER;
iface.flags = WL_INTERFACE_CREATE_AP;
- wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
- iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
- else if (apsta_params->apstamode == IGOSTA_MODE) {
+ else if (apstamode == IGOSTA_MODE) {
wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
wl_ext_iovar_setint(dev, "apsta", 1);
wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
bzero(&ifreq, sizeof(wl_p2p_if_t));
ifreq.type = htod32(WL_P2P_IF_GO);
+ apsta_params->netif_change = FALSE;
wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
- apsta_params->netif_change = FALSE;
- wait_event_interruptible_timeout(apsta_params->netif_change_event,
- apsta_params->netif_change, msecs_to_jiffies(1500));
+ wl_ext_wait_netif_change(apsta_params, TRUE);
}
wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
apsta_params->init = TRUE;
- printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+
+ printf("%s: apstamode=%d\n", __FUNCTION__, apstamode);
}
static int
apsta_params->apstamode = IAPSTA_MODE;
} else if (!strcmp(pick_tmp2, "ap-ap")) {
apsta_params->apstamode = IDUALAP_MODE;
+ } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
+ apsta_params->apstamode = ISTAAPAP_MODE;
} else if (!strcmp(pick_tmp2, "mesh")) {
apsta_params->apstamode = IMESHONLY_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-sta")) {
+ } else if (!strcmp(pick_tmp2, "mesh-sta") ||
+ !strcmp(pick_tmp2, "sta-mesh")) {
apsta_params->apstamode = IMESHSTA_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap") ||
+ !strcmp(pick_tmp2, "ap-mesh")) {
apsta_params->apstamode = IMESHAP_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap-sta")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap-sta") ||
+ !strcmp(pick_tmp2, "sta-ap-mesh") ||
+ !strcmp(pick_tmp2, "sta-mesh-ap")) {
apsta_params->apstamode = IMESHAPSTA_MODE;
- } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
+ } else if (!strcmp(pick_tmp2, "mesh-ap-ap") ||
+ !strcmp(pick_tmp2, "ap-ap-mesh")) {
apsta_params->apstamode = IMESHAPAP_MODE;
} else if (!strcmp(pick_tmp2, "apsta")) {
apsta_params->apstamode = IAPSTA_MODE;
apsta_params->if_info[i].ifmode = ISTA_MODE;
else if (!strcmp(pch, "ap"))
apsta_params->if_info[i].ifmode = IAP_MODE;
- else if (!strcmp(pch, "mesh"))
+ else if (!strcmp(pch, "mesh")) {
+ if (dhd->conf->fw_type != FW_TYPE_MESH) {
+ ANDROID_ERROR(("%s: wrong fw type\n", __FUNCTION__));
+ return -1;
+ }
apsta_params->if_info[i].ifmode = IMESH_MODE;
+ }
pch = bcmstrtok(&pick_tmp2, " -", 0);
}
}
+ }
+ else if (!strcmp(param, "rsdb")) {
+ pch = bcmstrtok(&pick_tmp, " ", 0);
+ if (pch) {
+ if (!strcmp(pch, "y")) {
+ apsta_params->rsdb = TRUE;
+ } else if (!strcmp(pch, "n")) {
+ apsta_params->rsdb = FALSE;
+ } else {
+ ANDROID_ERROR(("%s: rsdb [y|n]\n", __FUNCTION__));
+ return -1;
+ }
+ }
} else if (!strcmp(param, "vsdb")) {
pch = bcmstrtok(&pick_tmp, " ", 0);
if (pch) {
return -1;
}
}
+ } else if (!strcmp(param, "csa")) {
+ pch = bcmstrtok(&pick_tmp, " ", 0);
+ if (pch) {
+ apsta_params->csa = (int)simple_strtol(pch, NULL, 0);
+ }
} else if (!strcmp(param, "ifname")) {
pch = NULL;
pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
{
char *pch, *pick_tmp;
char name[20], data[100];
- int i, j;
+ int i, j, len;
char *ifname_head = NULL;
typedef struct config_map_t {
char *head;
char *tail;
} config_map_t;
-
+
config_map_t config_map [] = {
{" ifname ", NULL, NULL},
{" ssid ", NULL, NULL},
pick_tmp = command;
// reset head and tail
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
row->head = NULL;
row->tail = pick_tmp + strlen(pick_tmp);
}
// pick head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
pch = strstr(pick_tmp, row->name);
if (pch) {
}
// sort by head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
row_prev = &config_map[i];
- for (j = i+1; j < sizeof(config_map)/sizeof(config_map[0]); j++) {
+ for (j = i+1; j < sizeof(config_map)/sizeof(config_map[0]); j++) {
row = &config_map[j];
if (row->head < row_prev->head) {
strcpy(name, row_prev->name);
}
// pick tail
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
row_prev = &config_map[i];
row = &config_map[i+1];
if (row_prev->head) {
}
// remove name from head
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
if (row->head) {
if (!strcmp(row->name, " ifname ")) {
}
}
- for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+ for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
row = &config_map[i];
if (row->head) {
memset(data, 0, sizeof(data));
- if (row->tail) {
+ if (row->tail && row->tail > row->head) {
strncpy(data, row->head, row->tail-row->head);
} else {
strcpy(data, row->head);
if (!strcmp(row->name, " ifname ")) {
break;
} else if (!strcmp(row->name, " ssid ")) {
- strcpy(cur_if->ssid, pick_tmp);
+ len = strlen(pick_tmp);
+ memset(cur_if->ssid, 0, sizeof(cur_if->ssid));
+ if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+ strncpy(cur_if->ssid, &pick_tmp[1], len-2);
+ else
+ strcpy(cur_if->ssid, pick_tmp);
} else if (!strcmp(row->name, " bssid ")) {
pch = bcmstrtok(&pick_tmp, ": ", 0);
for (j=0; j<6 && pch; j++) {
cur_if->amode = AUTH_WPA2PSK;
else if (!strcmp(pick_tmp, "wpawpa2psk"))
cur_if->amode = AUTH_WPAWPA2PSK;
+ else if (!strcmp(pick_tmp, "sae"))
+ cur_if->amode = AUTH_SAE;
else {
ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n",
__FUNCTION__));
return -1;
}
} else if (!strcmp(row->name, " key ")) {
- strcpy(cur_if->key, pick_tmp);
+ len = strlen(pick_tmp);
+ memset(cur_if->key, 0, sizeof(cur_if->key));
+ if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+ strncpy(cur_if->key, &pick_tmp[1], len-2);
+ else
+ strcpy(cur_if->key, pick_tmp);
}
}
}
static int
wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
{
- int ret=0;
+ int ret=0, i;
char *pch, *pch2, *pick_tmp, *pick_next=NULL, *param;
struct wl_apsta_params *apsta_params = &g_apsta_params;
char ifname[IFNAMSIZ+1];
- struct wl_if_info *cur_if = &apsta_params->if_info[IF_PIF];
+ struct wl_if_info *cur_if = NULL;
if (!apsta_params->init) {
ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
return -1;
}
- if (!strcmp(apsta_params->if_info[IF_PIF].dev->name, ifname)) {
- cur_if = &apsta_params->if_info[IF_PIF];
- } else if (!strcmp(apsta_params->if_info[IF_VIF].ifname, ifname)) {
- cur_if = &apsta_params->if_info[IF_VIF];
- } else if (!strcmp(apsta_params->if_info[IF_VIF2].ifname, ifname)) {
- cur_if = &apsta_params->if_info[IF_VIF2];
- } else {
- ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", __FUNCTION__,
- ifname, apsta_params->apstamode));
+ for (i=0; i<MAX_IF_NUM; i++) {
+ if (apsta_params->if_info[i].dev &&
+ !strcmp(apsta_params->if_info[i].dev->name, ifname)) {
+ cur_if = &apsta_params->if_info[i];
+ break;
+ }
+ }
+ if (!cur_if) {
+ ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n",
+ __FUNCTION__, ifname, apsta_params->apstamode));
return -1;
}
ret = wl_ext_parse_config(cur_if, pick_tmp, &pick_next);
return 0;
}
+static int
+wl_ext_isam_status(struct net_device *dev)
+{
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ int i;
+ bool now_if;
+ struct wl_if_info *tmp_if;
+ uint16 chan = 0;
+ wlc_ssid_t ssid = { 0, {0} };
+ char amode[16], emode[16];
+
+ if (apsta_params->init == FALSE) {
+ return 0;
+ }
+
+ printf("****************************\n");
+ printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+ for (i=0; i<MAX_IF_NUM; i++) {
+ now_if = FALSE;
+ memset(&ssid, 0, sizeof(ssid));
+ memset(amode, 0, sizeof(amode));
+ memset(emode, 0, sizeof(emode));
+ tmp_if = &apsta_params->if_info[i];
+ if (dev == tmp_if->dev)
+ now_if = TRUE;
+ if (tmp_if->dev) {
+ chan = wl_ext_get_chan(tmp_if->dev);
+ if (chan) {
+ wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+ wl_ext_get_amode(tmp_if, amode);
+ wl_ext_get_emode(tmp_if, emode);
+ }
+ if (chan) {
+ printf("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n",
+ tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+ now_if?"*":" ", chan, amode, emode, ssid.SSID);
+ } else {
+ printf("%s[%c-%c%s]:\n",
+ tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+ now_if?"*":" ");
+ }
+ }
+ }
+ printf("****************************\n");
+
+ return 0;
+}
+
+static int
+wl_ext_if_down(struct wl_if_info *cur_if)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ scb_val_t scbval;
+ struct {
+ s32 cfg;
+ s32 val;
+ } bss_setbuf;
+ apstamode_t apstamode = g_apsta_params.apstamode;
+
+ printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+ } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ // deauthenticate all STA first
+ memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN);
+ wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
+ }
+
+ if (apstamode == IAPONLY_MODE || apstamode == IMESHONLY_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_DOWN, NULL, 0, 1);
+ } else {
+ bss_setbuf.cfg = 0xffffffff;
+ bss_setbuf.val = htod32(0);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+ iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ }
+
+ return 0;
+}
+
+static int
+wl_ext_if_up(struct wl_if_info *cur_if)
+{
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+ struct {
+ s32 cfg;
+ s32 val;
+ } bss_setbuf;
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ apstamode_t apstamode = apsta_params->apstamode;
+ chanspec_t fw_chspec;
+
+ if (cur_if->ifmode != IAP_MODE) {
+ ANDROID_ERROR(("%s: Wrong ifmode on %s[%c]\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix));
+ return 0;
+ }
+
+ if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ return 0;
+ }
+
+ printf("%s: %s[%c] Turning on\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+ wl_ext_isam_status(cur_if->dev);
+
+ wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+ &fw_chspec);
+
+ if (apstamode == IAPONLY_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_UP, NULL, 0, 1);
+ } else {
+ bss_setbuf.cfg = 0xffffffff;
+ bss_setbuf.val = htod32(1);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+ sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ }
+
+ OSL_SLEEP(500);
+
+ return 0;
+}
+
static int
wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
{
wlc_ssid_t ssid = { 0, {0} };
scb_val_t scbval;
struct {
- s32 tmp;
s32 cfg;
s32 val;
} bss_setbuf;
return -1;
}
+ printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix);
+
if (cur_if->ifmode == ISTA_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
} else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_iovar_setint(dev, "mpc", 1);
} else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) &&
cur_if->ifmode == IAP_MODE) {
- // if_info[IF_VIF] is AP mode
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
#endif
#endif /* PROP_TXSTATUS_VSDB */
- } else if (apstamode == IDUALAP_MODE) {
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ }
+ else if (apstamode == IDUALAP_MODE) {
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
} else if (apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
- apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
- bss_setbuf.tmp = 0xffffffff;
- bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+ apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE ||
+ apstamode == ISTAAPAP_MODE) {
+ bss_setbuf.cfg = 0xffffffff;
bss_setbuf.val = htod32(0);
wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
iovar_buf, WLC_IOCTL_SMLEN, NULL);
cur_if->ifstate = IF_STATE_DISALBE;
- printf("%s: ifname=%s, mode=%d\n", __FUNCTION__, ifname, cur_if->ifmode);
+ printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix);
return 0;
}
-static bool
-wl_ext_iapsta_diff_band(uint16 channel1, uint16 channel2)
-{
- ANDROID_TRACE(("%s: cur_chan=%d, channel=%d\n", __FUNCTION__, channel1, channel2));
- if ((channel1 <= CH_MAX_2G_CHANNEL && channel2 > CH_MAX_2G_CHANNEL) ||
- (channel1 > CH_MAX_2G_CHANNEL && channel2 <= CH_MAX_2G_CHANNEL)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
static uint16
-wl_ext_iapsta_is_vsdb(struct net_device *dev,
- struct wl_if_info *cur_if, struct wl_if_info *another_if)
+wl_ext_get_vsdb_chan(struct net_device *dev,
+ struct wl_if_info *cur_if, struct wl_if_info *target_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- int ret = 0, cur_chan = 0;
- uint16 another_chan = 0, ctl_chan;
+ uint16 target_chan = 0, cur_chan = cur_if->channel;
struct dhd_pub *dhd;
- struct ether_addr bssid;
- u32 chanspec = 0;
dhd = dhd_get_pub(dev);
-
- ret = wldev_ioctl(another_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
- if (wldev_iovar_getint(another_if->dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
- ANDROID_TRACE(("%s: chanspec=0x%x\n", __FUNCTION__, chanspec));
- chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
- ctl_chan = wf_chspec_ctlchan(chanspec);
- another_chan = (u16)(ctl_chan & 0x00FF);
- cur_chan = cur_if->channel;
- if (wl_ext_iapsta_diff_band(another_chan, cur_chan)) {
- // different band
- if (!FW_SUPPORTED(dhd, rsdb))
- return another_chan;
- } else {
- // same band
- if (another_chan != cur_chan)
- return another_chan;
- }
+
+ target_chan = wl_ext_get_chan(target_if->dev);
+ if (target_chan) {
+ ANDROID_INFO(("%s: cur_chan=%d, target_chan=%d\n", __FUNCTION__,
+ cur_chan, target_chan));
+ if ((cur_chan <= CH_MAX_2G_CHANNEL && target_chan > CH_MAX_2G_CHANNEL) ||
+ (cur_chan > CH_MAX_2G_CHANNEL && target_chan <= CH_MAX_2G_CHANNEL)) {
+ // different band
+ if (!FW_SUPPORTED(dhd, rsdb) || !apsta_params->rsdb)
+ return target_chan;
+ } else {
+ // same band
+ if (target_chan != cur_chan)
+ return target_chan;
}
}
return 0;
}
-static void
-wl_ext_iapsta_change_channel(struct wl_if_info *cur_if, uint16 chan)
+static int
+wl_ext_triger_csa(struct wl_if_info *cur_if)
{
- if (chan) {
- char cmd[50] = "";
- printf("%s: deauthenticate all STA and move to chan=%d on %s\n",
- __FUNCTION__, chan, cur_if->ifname);
- snprintf(cmd, 50, "%s %s", "isam_disable ifname", cur_if->ifname);
- wl_ext_iapsta_disable(cur_if->dev, cmd, strlen(cmd));
- cur_if->channel = chan;
- snprintf(cmd, 50, "%s %s", "isam_enable ifname", cur_if->ifname);
- wl_ext_iapsta_enable(cur_if->dev, cmd, strlen(cmd));
+ struct wl_apsta_params *apsta_params = &g_apsta_params;
+ s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+ if (apsta_params->csa & CSA_DRV_BIT &&
+ (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) {
+ if (!cur_if->channel) {
+ printf("%s: %s[%c] skip channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ } else if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ wl_ext_if_down(cur_if);
+ } else {
+ wl_chan_switch_t csa_arg;
+ memset(&csa_arg, 0, sizeof(csa_arg));
+ csa_arg.mode = 1;
+ csa_arg.count = 3;
+ csa_arg.chspec = wl_ext_get_chanspec(apsta_params, cur_if->dev,
+ cur_if->channel);
+ if (csa_arg.chspec) {
+ printf("%s: Trigger CSA to channel %d(0x%x)\n", __FUNCTION__,
+ cur_if->channel, csa_arg.chspec);
+ wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg),
+ iovar_buf, sizeof(iovar_buf), NULL);
+ OSL_SLEEP(500);
+ wl_ext_isam_status(cur_if->dev);
+ } else {
+ printf("%s: fail to get chanspec\n", __FUNCTION__);
+ }
+ }
}
+
+ return 0;
}
-static void
-wl_ext_iapsta_change_cur_iface_channel(struct net_device *dev,
+static uint16
+wl_ext_move_cur_channel(struct net_device *dev,
struct wl_if_info *cur_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *another_if, *final_if = NULL;
- uint16 new_chan = 0;
+ struct wl_if_info *tmp_if, *target_if = NULL;
+ uint16 tmp_chan, target_chan = 0;
+ wl_prio_t max_prio;
int i;
- if (cur_if->ifmode == IAP_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == ISTA_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan) {
- final_if = another_if;
- break;
- }
- }
- }
- } else if (cur_if->ifmode == IMESH_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == ISTA_MODE || another_if->ifmode == IAP_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan) {
- final_if = another_if;
- break;
- }
+ if (apsta_params->vsdb) {
+ target_chan = cur_if->channel;
+ goto exit;
+ }
+
+ // find the max prio
+ max_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+ tmp_if->prio > max_prio) {
+ tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+ if (tmp_chan) {
+ target_if = tmp_if;
+ target_chan = tmp_chan;
+ max_prio = tmp_if->prio;
}
}
}
- if (new_chan && !apsta_params->vsdb) {
- cur_if->channel = new_chan;
- printf("%s: %s ifmode=%d, %s ifmode=%d, channel=%d\n", __FUNCTION__,
- cur_if->ifname, cur_if->ifmode, final_if->ifname, final_if->ifmode,
- cur_if->channel);
+
+ if (target_chan) {
+ printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->channel, target_if->ifname, target_chan);
+ cur_if->channel = target_chan;
+ }
+exit:
+ if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) &&
+ (cur_if->channel >= 52 && cur_if->channel <= 148)) {
+ printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, cur_if->channel);
+ cur_if->channel = 0;
}
+ return cur_if->channel;
}
static void
-wl_ext_iapsta_change_other_iface_channel(struct net_device *dev,
+wl_ext_move_other_channel(struct net_device *dev,
struct wl_if_info *cur_if)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *another_if;
- uint16 new_chan = 0;
+ struct wl_if_info *tmp_if, *target_if=NULL;
+ uint16 tmp_chan, target_chan = 0;
+ wl_prio_t max_prio = 0, cur_prio;
int i;
- if (cur_if->ifmode == ISTA_MODE) {
- for (i=MAX_IF_NUM-1; i>=0; i--) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == IAP_MODE || another_if->ifmode == IMESH_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan && !apsta_params->vsdb) {
- wl_ext_iapsta_change_channel(another_if, cur_if->channel);
- }
+ if (apsta_params->vsdb || !cur_if->channel) {
+ return;
+ }
+
+ // find the max prio, but lower than cur_if
+ cur_prio = cur_if->prio;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+ tmp_if->prio >= max_prio && tmp_if->prio <= cur_prio) {
+ tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+ if (tmp_chan) {
+ target_if = tmp_if;
+ target_chan = tmp_chan;
+ max_prio = tmp_if->prio;
}
}
- } else if (cur_if->ifmode == IAP_MODE) {
- for (i=0; i<MAX_IF_NUM; i++) {
- another_if = &apsta_params->if_info[i];
- if (another_if->ifmode == IMESH_MODE) {
- new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
- if (new_chan && !apsta_params->vsdb) {
- wl_ext_iapsta_change_channel(another_if, cur_if->channel);
- }
+ }
+
+ if (target_if) {
+ printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+ target_if->ifname, target_chan, cur_if->ifname, cur_if->channel);
+ target_if->channel = cur_if->channel;
+ if (apsta_params->csa == 0) {
+ wl_ext_if_down(target_if);
+ wl_ext_move_other_channel(dev, target_if);
+ if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) {
+ wl_ext_enable_iface(target_if->dev, target_if->ifname);
+ } else if (target_if->ifmode == IAP_MODE) {
+ wl_ext_if_up(target_if);
}
+ } else {
+ wl_ext_triger_csa(target_if);
}
}
}
static int
-wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
+wl_ext_enable_iface(struct net_device *dev, char *ifname)
{
- int ret = 0, i;
- char *pick_tmp, *param;
+ int i;
s8 iovar_buf[WLC_IOCTL_SMLEN];
wlc_ssid_t ssid = { 0, {0} };
chanspec_t fw_chspec;
struct wl_apsta_params *apsta_params = &g_apsta_params;
apstamode_t apstamode = apsta_params->apstamode;
struct wl_if_info *cur_if = NULL;
- char cmd[128];
struct dhd_pub *dhd;
- struct ether_addr bssid;
uint16 cur_chan;
dhd = dhd_get_pub(dev);
return -1;
}
- wl_ext_iapsta_change_cur_iface_channel(dev, cur_if);
+ printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix);
- if ((apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
- apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) &&
- cur_if == &apsta_params->if_info[IF_PIF] &&
- cur_if->ifstate == IF_STATE_INIT &&
- FW_SUPPORTED(dhd, rsdb)) {
- wl_config_t rsdb_mode_cfg = {1, 0};
- // mesh-ap must set rsdb_mode=1 in same channel or AP mode not easy to be found
- printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
- wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
- sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
- }
+ wl_ext_isam_status(cur_if->dev);
- ret = wldev_ioctl(cur_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
- if (ret != BCME_NOTASSOCIATED && memcmp(ðer_null, &bssid, ETHER_ADDR_LEN)) {
- ANDROID_INFO(("%s: Associated! ret %d\n", __FUNCTION__, ret));
+ wl_ext_move_cur_channel(dev, cur_if);
+ if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) {
return 0;
}
- ssid.SSID_len = strlen(cur_if->ssid);
- memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
- ANDROID_TRACE(("%s: apstamode=%d, bssidx=%d\n", __FUNCTION__, apstamode, cur_if->bssidx));
+ cur_chan = wl_ext_get_chan(cur_if->dev);
+ if (cur_chan) {
+ ANDROID_INFO(("%s: Associated!\n", __FUNCTION__));
+ if (cur_chan != cur_if->channel) {
+ wl_ext_triger_csa(cur_if);
+ }
+ return 0;
+ }
- wl_ext_iapsta_change_other_iface_channel(dev, cur_if);
+ wl_ext_move_other_channel(dev, cur_if);
- if (cur_if == &apsta_params->if_info[IF_VIF] || cur_if == &apsta_params->if_info[IF_VIF2]) {
+ if (cur_if->ifidx > 0) {
wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr,
ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
// set ssid for AP
+ ssid.SSID_len = strlen(cur_if->ssid);
+ memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_iovar_setint(dev, "mpc", 0);
if (apstamode == IAPONLY_MODE) {
if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
wl_ext_set_bgnmode(cur_if);
- cur_chan = cur_if->channel;
- if (!cur_chan) {
- cur_chan = 1;
+ if (!cur_if->channel) {
#ifdef WL_CFG80211
+ char *pick_tmp, *param;
+ char cmd[128];
+ uint16 cur_chan;
+ cur_chan = 1;
snprintf(cmd, 128, "get_best_channels");
wl_cfg80211_get_best_channels(dev, cmd, strlen(cmd));
pick_tmp = cmd;
}
param = bcmstrtok(&pick_tmp, " ", 0);
}
+ cur_if->channel = cur_chan;
+#else
+ cur_if->channel = 1;
#endif
}
- wl_ext_set_chanspec(cur_if->dev, cur_chan, &fw_chspec);
+ wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+ &fw_chspec);
}
- wl_ext_set_amode(cur_if, apsta_params);
+ wl_ext_set_amode(cur_if);
wl_ext_set_emode(cur_if, apsta_params);
if (cur_if->ifmode == IAP_MODE) {
wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc);
// terence: fix me, hidden does not work in dualAP mode
if (cur_if->hidden > 0) {
- wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1);
- printf("%s: Broadcast SSID: %s\n", __FUNCTION__, cur_if->hidden ? "OFF":"ON");
+ wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden,
+ sizeof(cur_if->hidden), 1);
+ printf("%s: Broadcast SSID: %s\n", __FUNCTION__,
+ cur_if->hidden ? "OFF":"ON");
}
}
} else {
bss_setbuf.cfg = htod32(cur_if->bssidx);
bss_setbuf.val = htod32(1);
- wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
- iovar_buf, WLC_IOCTL_SMLEN, NULL);
+ wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+ sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
}
#ifdef ARP_OFFLOAD_SUPPORT
/* IF SoftAP is enabled, disable arpoe */
}
else if (apstamode == IDUALAP_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+ } else if (apstamode == ISTAAPAP_MODE) {
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_connect(cur_if);
+ } else if (cur_if->ifmode == IAP_MODE) {
+ wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+ } else {
+ printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode);
+ }
} else if (apstamode == IMESHONLY_MODE ||
apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
} else if (cur_if->ifmode == IMESH_MODE) {
// need to up before setting ssid
- wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
memset(&join_params, 0, sizeof(join_params));
join_params.ssid.SSID_len = strlen(cur_if->ssid);
- memcpy((void *)join_params.ssid.SSID, cur_if->ssid, ssid.SSID_len);
+ memcpy((void *)join_params.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid));
join_params.params.chanspec_list[0] = fw_chspec;
join_params.params.chanspec_num = 1;
join_params_size = sizeof(join_params);
}
}
- printf("%s: ifname=%s, mode=%d, SSID: \"%s\"\n", __FUNCTION__,
- ifname, cur_if->ifmode, cur_if->ssid);
+ OSL_SLEEP(500);
+ printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__,
+ ifname, cur_if->prefix, cur_if->ssid);
+ wl_ext_isam_status(cur_if->dev);
cur_if->ifstate = IF_STATE_ENABLE;
pch = bcmstrtok(&pick_tmp, " ", 0);
if (pch) {
strcpy(ifname, pch);
- ret = wl_ext_iapsta_enable_iface(dev, ifname);
+ ret = wl_ext_enable_iface(dev, ifname);
if (ret)
return ret;
- else
- OSL_SLEEP(1000);
} else {
ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
return -1;
wl_ext_iapsta_alive_preinit(struct net_device *dev)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct wl_if_info *cur_if;
+ int i;
if (apsta_params->init == TRUE) {
ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__));
ANDROID_TRACE(("%s: Enter\n", __FUNCTION__));
- strcpy(apsta_params->if_info[IF_PIF].ssid, "tttp");
- apsta_params->if_info[IF_PIF].maxassoc = -1;
- apsta_params->if_info[IF_PIF].channel = 1;
-
- if (!strlen(apsta_params->if_info[IF_VIF].ifname))
- strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
- strcpy(apsta_params->if_info[IF_VIF].ssid, "tttv");
- apsta_params->if_info[IF_VIF].maxassoc = -1;
- apsta_params->if_info[IF_VIF].channel = 1;
-
- if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
- strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
- strcpy(apsta_params->if_info[IF_VIF2].ssid, "tttv2");
- apsta_params->if_info[IF_VIF2].maxassoc = -1;
- apsta_params->if_info[IF_VIF2].channel = 161;
+ for (i=0; i<MAX_IF_NUM; i++) {
+ cur_if = &apsta_params->if_info[i];
+ if (i == 1 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan1");
+ if (i == 2 && !strlen(cur_if->ifname))
+ strcpy(cur_if->ifname, "wlan2");
+ if (cur_if->ifmode == ISTA_MODE) {
+ cur_if->channel = 0;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_STA;
+ cur_if->prefix = 'S';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
+ } else if (cur_if->ifmode == IAP_MODE) {
+ cur_if->channel = 1;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_AP;
+ cur_if->prefix = 'A';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
+ } else if (cur_if->ifmode == IMESH_MODE) {
+ cur_if->channel = 1;
+ cur_if->maxassoc = -1;
+ cur_if->ifstate = IF_STATE_INIT;
+ cur_if->prio = PRIO_MESH;
+ cur_if->prefix = 'M';
+ snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
+ }
+ }
apsta_params->init = TRUE;
return op_mode;
}
+#if defined(WL_WIRELESS_EXT)
static bool
wl_ext_conn_status_str(uint32 event_type,
uint32 status, uint32 reason, char* stringBuf, uint buflen)
return FALSE;
}
+#endif /* WL_WIRELESS_EXT */
int
wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
struct wl_if_info *cur_if = NULL;
- char extra[IW_CUSTOM_MAX + 1];
int i;
#if defined(WL_WIRELESS_EXT)
+ char extra[IW_CUSTOM_MAX + 1];
union iwreq_data wrqu;
- int cmd = 0;
#endif
uint32 event_type = ntoh32(e->event_type);
uint32 status = ntoh32(e->status);
}
for (i=0; i<MAX_IF_NUM; i++) {
- if (apsta_params->if_info[i].bssidx == e->ifidx) {
+ if (apsta_params->if_info[i].ifidx == e->ifidx) {
cur_if = &apsta_params->if_info[i];
break;
}
return -1;
}
- memset(extra, 0, sizeof(extra));
-#if defined(WL_WIRELESS_EXT)
- memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
- wrqu.addr.sa_family = ARPHRD_ETHER;
-#endif
-
if (cur_if->ifmode == ISTA_MODE) {
- switch (event_type) {
- case WLC_E_LINK:
- if (!(flags & WLC_EVENT_MSG_LINK)) {
- printf("%s: %s Link Down with BSSID="MACSTR"\n", __FUNCTION__,
- cur_if->ifname, MAC2STR((u8 *)&e->addr));
- } else {
- printf("%s: %s Link UP with BSSID="MACSTR"\n", __FUNCTION__,
- cur_if->ifname, MAC2STR((u8 *)&e->addr));
- }
- break;
- default:
- /* Cannot translate event */
- break;
+ if (event_type == WLC_E_LINK) {
+ if (!(flags & WLC_EVENT_MSG_LINK)) {
+ printf("%s: %s[%c] Link Down with %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ } else {
+ printf("%s: %s[%c] Link UP with %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ }
}
- } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
- if (((event_type == WLC_E_ASSOC_IND) || (event_type == WLC_E_REASSOC_IND)) &&
- reason == DOT11_SC_SUCCESS) {
- printf("%s: %s connected device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
+ }
+ else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+ if ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_INITIAL_ASSOC)) {
+ printf("%s: %s[%c] Link up\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix);
+ } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+ (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+ reason == WLC_E_REASON_DEAUTH)) {
+ printf("%s: %s[%c] Link down\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix);
+ }
+ else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
+ reason == DOT11_SC_SUCCESS) {
+ printf("%s: %s[%c] connected device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
} else if (event_type == WLC_E_DISASSOC_IND) {
- printf("%s: %s disassociated device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
- } else if ((event_type == WLC_E_DEAUTH_IND) ||
- ((event_type == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) {
- printf("%s: %s deauthenticated device "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, MAC2STRDBG(e->addr.octet));
- } else {
- ANDROID_TRACE(("%s: %s event %d "MACDBG"\n", __FUNCTION__,
- cur_if->ifname, event_type, MAC2STRDBG(e->addr.octet)));
+ printf("%s: %s[%c] disassociated device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
+ } else if (event_type == WLC_E_DEAUTH_IND ||
+ (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
+ printf("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__,
+ cur_if->ifname, cur_if->prefix, &e->addr);
}
}
- if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
#if defined(WL_WIRELESS_EXT)
- cmd = IWEVCUSTOM;
+ memset(extra, 0, sizeof(extra));
+ memset(&wrqu, 0, sizeof(wrqu));
+ memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+ wrqu.addr.sa_family = ARPHRD_ETHER;
+ if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
wrqu.data.length = strlen(extra);
- wireless_send_event(cur_if->dev, cmd, &wrqu, extra);
+ wireless_send_event(cur_if->dev, IWEVCUSTOM, &wrqu, extra);
+ ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n",
+ __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+ reason, flags));
+ } else
#endif /* WL_WIRELESS_EXT */
- ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d sent up\n", __FUNCTION__,
- cur_if->ifname, event_type, status, reason));
- } else {
- ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d\n", __FUNCTION__,
- cur_if->ifname, event_type, status, reason));
+ {
+ ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n",
+ __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+ reason, flags));
}
return 0;
}
-void
-wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel)
+u32
+wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
- struct wl_if_info *cur_if = NULL;
+ struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
int i;
for (i=0; i<MAX_IF_NUM; i++) {
- if (apsta_params->if_info[i].dev == dev) {
- cur_if = &apsta_params->if_info[i];
- cur_if->channel = channel;
- wl_ext_iapsta_change_other_iface_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ tmp_if = &apsta_params->if_info[i];
+ if (tmp_if->dev && tmp_if->dev == dev) {
+ cur_if = tmp_if;
+ break;
}
}
+ if (cur_if) {
+ wl_ext_isam_status(cur_if->dev);
+ cur_if->channel = channel;
+ channel = wl_ext_move_cur_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ if (channel)
+ wl_ext_move_other_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+ }
+
+ return channel;
}
int
-wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_name(struct net_device *net, int ifidx)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct dhd_pub *dhd;
+ struct wl_if_info *cur_if = NULL;
- ANDROID_TRACE(("%s: bssidx=%d, %s\n", __FUNCTION__, bssidx, net->name));
- if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
- strcpy(apsta_params->if_info[IF_VIF].ifname, net->name);
- } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
- strcpy(apsta_params->if_info[IF_VIF2].ifname, net->name);
+ dhd = dhd_get_pub(net);
+
+ ANDROID_TRACE(("%s: ifidx=%d, %s\n", __FUNCTION__, ifidx, net->name));
+ if (ifidx < MAX_IF_NUM) {
+ cur_if = &apsta_params->if_info[ifidx];
+ }
+ if (ifidx == 0) {
+ if (dhd->conf->fw_type == FW_TYPE_MESH) {
+ apsta_params->rsdb = TRUE;
+ apsta_params->csa = CSA_FW_BIT | CSA_DRV_BIT;
+ }
+ strcpy(cur_if->ifname, net->name);
+ } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+ strcpy(cur_if->ifname, net->name);
+ apsta_params->netif_change = TRUE;
+ wake_up_interruptible(&apsta_params->netif_change_event);
}
return 0;
}
int
-wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
{
struct wl_apsta_params *apsta_params = &g_apsta_params;
+ struct dhd_pub *dhd;
+ struct wl_if_info *cur_if = NULL, *primary_if;
- printf("%s: bssidx=%d\n", __FUNCTION__, bssidx);
- if (bssidx == 0) {
+ dhd = dhd_get_pub(net);
+
+ printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx);
+ if (ifidx < MAX_IF_NUM) {
+ cur_if = &apsta_params->if_info[ifidx];
+ }
+ if (ifidx == 0) {
memset(apsta_params, 0, sizeof(struct wl_apsta_params));
apsta_params->vsdb = FALSE;
- apsta_params->if_info[IF_PIF].dev = net;
- apsta_params->if_info[IF_PIF].bssidx = bssidx;
- strcpy(apsta_params->if_info[IF_PIF].ifname, net->name);
+ cur_if->dev = net;
+ cur_if->ifidx = ifidx;
+ cur_if->bssidx = bssidx;
+ strcpy(cur_if->ifname, net->name);
init_waitqueue_head(&apsta_params->netif_change_event);
- } else if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
- apsta_params->if_info[IF_VIF].dev = net;
- apsta_params->if_info[IF_VIF].bssidx = bssidx;
- if (strlen(apsta_params->if_info[IF_VIF].ifname)) {
+ } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+ primary_if = &apsta_params->if_info[IF_PIF];
+ cur_if->dev = net;
+ cur_if->ifidx = ifidx;
+ cur_if->bssidx = bssidx;
+ if (strlen(cur_if->ifname)) {
memset(net->name, 0, sizeof(IFNAMSIZ));
- strcpy(net->name, apsta_params->if_info[IF_VIF].ifname);
+ strcpy(net->name, cur_if->ifname);
net->name[IFNAMSIZ-1] = '\0';
}
- if (apsta_params->if_info[IF_PIF].dev) {
- memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
+ if (apsta_params->apstamode != ISTAAPAP_MODE) {
+ memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
net->dev_addr[0] |= 0x02;
+ if (ifidx >= 2) {
+ net->dev_addr[4] ^= 0x80;
+ net->dev_addr[4] += ifidx;
+ net->dev_addr[5] += (ifidx-1);
+ }
}
- apsta_params->netif_change = TRUE;
- wake_up_interruptible(&apsta_params->netif_change_event);
- } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
- apsta_params->if_info[IF_VIF2].dev = net;
- apsta_params->if_info[IF_VIF2].bssidx = bssidx;
- if (strlen(apsta_params->if_info[IF_VIF2].ifname)) {
- memset(net->name, 0, sizeof(IFNAMSIZ));
- strcpy(net->name, apsta_params->if_info[IF_VIF2].ifname);
- net->name[IFNAMSIZ-1] = '\0';
- }
- if (apsta_params->if_info[IF_PIF].dev) {
- memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
- net->dev_addr[0] |= 0x02;
- net->dev_addr[4] ^= 0x80;
- net->dev_addr[4] += bssidx;
- net->dev_addr[5] += bssidx;
+ if (cur_if->ifmode == ISTA_MODE) {
+ wl_ext_iovar_setint(net, "roam_off", dhd->conf->roam_off);
+ wl_ext_iovar_setint(net, "bcn_timeout", dhd->conf->bcn_timeout);
+ } else if (cur_if->ifmode == IMESH_MODE) {
+ int pm = 0;
+ wl_ext_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), 1);
}
- apsta_params->netif_change = TRUE;
- wake_up_interruptible(&apsta_params->netif_change_event);
}
return 0;
int
wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len)
{
-
int ret = 0;
int bytes_written = 0;
uint32 ip_addr;
return ret;
}
-int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
- int *bytes_written)
+int wl_android_ext_priv_cmd(struct net_device *net, char *command,
+ int total_len, int *bytes_written)
{
int ret = 0;
else if (strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) {
*bytes_written = wl_ext_iapsta_disable(net, command, total_len);
}
+ else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) {
+ *bytes_written = wl_ext_isam_status(net);
+ }
#endif
#ifdef IDHCP
else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) {
else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) {
*bytes_written = wl_ext_dhcpc_dump(net, command, total_len);
}
+#endif
+#ifdef WL_CFG80211
+ else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+ *bytes_written = wl_cfg80211_autochannel(net, command, total_len);
+ }
+#endif
+#ifdef WL_ESCAN
+ else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+ *bytes_written = wl_escan_autochannel(net, command, total_len);
+ }
#endif
else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) {
*bytes_written = wl_ext_iovar(net, command, total_len);
return ret;
}
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+int
+wl_ext_get_distance(struct net_device *net, u32 band)
+{
+ u32 bw = WL_CHANSPEC_BW_20;
+ s32 bw_cap = 0, distance = 0;
+ struct {
+ u32 band;
+ u32 bw_cap;
+ } param = {0, 0};
+ char buf[WLC_IOCTL_SMLEN]="\0";
+ s32 err = BCME_OK;
+
+ param.band = band;
+ err = wldev_iovar_getbuf(net, "bw_cap", ¶m, sizeof(param), buf,
+ sizeof(buf), NULL);
+ if (err) {
+ if (err != BCME_UNSUPPORTED) {
+ ANDROID_ERROR(("bw_cap failed, %d\n", err));
+ return err;
+ } else {
+ err = wl_ext_iovar_getint(net, "mimo_bw_cap", &bw_cap);
+ if (err) {
+ ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+ }
+ if (bw_cap != WLC_N_BW_20ALL)
+ bw = WL_CHANSPEC_BW_40;
+ }
+ } else {
+ if (WL_BW_CAP_80MHZ(buf[0]))
+ bw = WL_CHANSPEC_BW_80;
+ else if (WL_BW_CAP_40MHZ(buf[0]))
+ bw = WL_CHANSPEC_BW_40;
+ else
+ bw = WL_CHANSPEC_BW_20;
+ }
+
+ if (bw == WL_CHANSPEC_BW_20)
+ distance = 2;
+ else if (bw == WL_CHANSPEC_BW_40)
+ distance = 4;
+ else if (bw == WL_CHANSPEC_BW_80)
+ distance = 8;
+ else
+ distance = 16;
+ ANDROID_INFO(("%s: bw=0x%x, distance=%d\n", __FUNCTION__, bw, distance));
+
+ return distance;
+}
+
+int
+wl_ext_get_best_channel(struct net_device *net,
+#if defined(BSSCACHE)
+ wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#else
+ struct wl_scan_results *bss_list,
+#endif
+ int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+)
+{
+ struct wl_bss_info *bi = NULL; /* must be initialized */
+ s32 i, j;
+#if defined(BSSCACHE)
+ wl_bss_cache_t *node;
+#endif
+ int b_band[CH_MAX_2G_CHANNEL]={0}, a_band1[4]={0}, a_band4[5]={0};
+ s32 cen_ch, distance, distance_2g, distance_5g, ch, min_ap=999;
+ u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+ wl_uint32_list_t *list;
+ int ret;
+ chanspec_t chanspec;
+
+ memset(b_band, -1, sizeof(b_band));
+ memset(a_band1, -1, sizeof(a_band1));
+ memset(a_band4, -1, sizeof(a_band4));
+
+ memset(valid_chan_list, 0, sizeof(valid_chan_list));
+ list = (wl_uint32_list_t *)(void *) valid_chan_list;
+ list->count = htod32(WL_NUMCHANNELS);
+ ret = wldev_ioctl(net, WLC_GET_VALID_CHANNELS, valid_chan_list,
+ sizeof(valid_chan_list), 0);
+ if (ret<0) {
+ ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
+ return 0;
+ } else {
+ for (i = 0; i < dtoh32(list->count); i++) {
+ ch = dtoh32(list->element[i]);
+ if (ch < CH_MAX_2G_CHANNEL)
+ b_band[ch-1] = 0;
+ else if (ch <= 48)
+ a_band1[(ch-36)/4] = 0;
+ else if (ch >= 149 && ch <= 161)
+ a_band4[(ch-149)/4] = 0;
+ }
+ }
+
+ distance_2g = wl_ext_get_distance(net, WLC_BAND_2G);
+ distance_5g = wl_ext_get_distance(net, WLC_BAND_5G);
+
+#if defined(BSSCACHE)
+ node = bss_cache_ctrl->m_cache_head;
+ for (i=0; node && i<256; i++)
+#else
+ for (i=0; i < bss_list->count; i++)
+#endif
+ {
+#if defined(BSSCACHE)
+ bi = node->results.bss_info;
+#else
+ bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
+#endif
+ chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
+ cen_ch = CHSPEC_CHANNEL(bi->chanspec);
+ distance = 0;
+ if (CHSPEC_IS20(chanspec))
+ distance += 2;
+ else if (CHSPEC_IS40(chanspec))
+ distance += 4;
+ else if (CHSPEC_IS80(chanspec))
+ distance += 8;
+ else
+ distance += 16;
+
+ if (CHSPEC_IS2G(chanspec)) {
+ distance += distance_2g;
+ for (j=0; j<ARRAYSIZE(b_band); j++) {
+ if (b_band[j] >= 0 && abs(cen_ch-(1+j)) <= distance)
+ b_band[j] += 1;
+ }
+ } else {
+ distance += distance_5g;
+ if (cen_ch <= 48) {
+ for (j=0; j<ARRAYSIZE(a_band1); j++) {
+ if (a_band1[j] >= 0 && abs(cen_ch-(36+j*4)) <= distance)
+ a_band1[j] += 1;
+ }
+ } else if (cen_ch >= 149) {
+ for (j=0; j<ARRAYSIZE(a_band4); j++) {
+ if (a_band4[j] >= 0 && abs(cen_ch-(149+j*4)) <= distance)
+ a_band4[j] += 1;
+ }
+ }
+ }
+#if defined(BSSCACHE)
+ node = node->next;
+#endif
+ }
+
+ *best_2g_ch = 0;
+ min_ap = 999;
+ for (i=0; i<CH_MAX_2G_CHANNEL; i++) {
+ if(b_band[i] < min_ap && b_band[i] >= 0) {
+ min_ap = b_band[i];
+ *best_2g_ch = i+1;
+ }
+ }
+ *best_5g_ch = 0;
+ min_ap = 999;
+ for (i=0; i<ARRAYSIZE(a_band1); i++) {
+ if(a_band1[i] < min_ap && a_band1[i] >= 0) {
+ min_ap = a_band1[i];
+ *best_5g_ch = i*4 + 36;
+ }
+ }
+ for (i=0; i<ARRAYSIZE(a_band4); i++) {
+ if(a_band4[i] < min_ap && a_band4[i] >= 0) {
+ min_ap = a_band4[i];
+ *best_5g_ch = i*4 + 149;
+ }
+ }
+
+ if (android_msg_level&ANDROID_INFO_LEVEL) {
+ printf("%s: b_band: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(b_band); j++)
+ printf("%d, ", b_band[j]);
+ printf("\n");
+ printf("%s: a_band1: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(a_band1); j++)
+ printf("%d, ", a_band1[j]);
+ printf("\n");
+ printf("%s: a_band4: ", __FUNCTION__);
+ for (j=0; j<ARRAYSIZE(a_band4); j++)
+ printf("%d, ", a_band4[j]);
+ printf("\n");
+ printf("%s: best_2g_ch=%d, best_5g_ch=%d\n", __FUNCTION__,
+ *best_2g_ch, *best_5g_ch);
+ }
+
+ return 0;
+}
+#endif
+
#if defined(RSSIAVG)
void
wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
}
void
-wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+ u8 *bssid)
{
wl_rssi_cache_t *node, *prev, **rssi_head;
int i = -1, tmp = 0;
}
int
-wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
+wl_update_connected_rssi_cache(struct net_device *net,
+ wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
{
wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
int j, k=0;
int rssi, error=0;
struct ether_addr bssid;
struct timeval now, timeout;
+ scb_val_t scbval;
if (!g_wifi_on)
return 0;
if (error) {
ANDROID_ERROR(("Could not get bssid (%d)\n", error));
}
- error = wldev_get_rssi(net, &rssi);
+ error = wldev_get_rssi(net, &scbval);
if (error) {
ANDROID_ERROR(("Could not get rssi (%d)\n", error));
return error;
}
+ rssi = scbval.val;
do_gettimeofday(&now);
timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
}
void
-wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list)
+wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+ wl_scan_results_t *ss_list)
{
wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
wl_bss_info_t *bi = NULL;
}
void
-wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
+ u8 *bssid)
{
wl_bss_cache_t *node, *prev, **bss_head;
int i = -1, tmp = 0;
rssi = dtoh16(node->results.bss_info->RSSI);
#endif
ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
- __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID));
+ __FUNCTION__, k, &node->results.bss_info->BSSID, rssi,
+ node->results.bss_info->SSID));
k++;
node = node->next;
}
#endif
for (;node;) {
#if defined(RSSIAVG)
- rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
+ rssi_node = wl_get_avg_rssi(rssi_cache_ctrl,
+ &node->results.bss_info->BSSID);
#else
rssi_node = dtoh16(node->results.bss_info->RSSI);
#endif