From: Rongjun Chen Date: Mon, 25 Dec 2017 05:24:00 +0000 (+0800) Subject: wifi: update bcm 1.57 wifi driver to fix ap6255 country code issue X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=91a2c11741597ad535bd522a5151ebb8076da262;p=GitHub%2FLineageOS%2FG12%2Fandroid_hardware_amlogic_kernel-modules_dhd-driver.git wifi: update bcm 1.57 wifi driver to fix ap6255 country code issue PD# 157312 update wifi driver Change-Id: I6a98921411f990dce92a2de5a6eb0d37da33fd4f --- diff --git a/bcmdhd.1.579.77.41.1.cn/Kconfig b/bcmdhd.1.579.77.41.1.cn/Kconfig old mode 100644 new mode 100755 diff --git a/bcmdhd.1.579.77.41.1.cn/Makefile b/bcmdhd.1.579.77.41.1.cn/Makefile old mode 100644 new mode 100755 index 5788bb3..0e7e33d --- a/bcmdhd.1.579.77.41.1.cn/Makefile +++ b/bcmdhd.1.579.77.41.1.cn/Makefile @@ -20,8 +20,7 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER -DSDTEST \ -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY \ -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS \ -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD \ - -DTSQ_MULTIPLIER -DMFP \ - -DBCMSDIOH_TXGLOM_EXT -DWL_EXT_IAPSTA \ + -DTSQ_MULTIPLIER -DMFP -DWL_EXT_IAPSTA \ -DENABLE_INSMOD_NO_FW_LOAD \ -I$(src) -I$(src)/include @@ -34,20 +33,9 @@ DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o \ ifneq ($(CONFIG_BCMDHD_SDIO),) DHDCFLAGS += \ -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \ - -DBDC -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM \ + -DBDC -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT \ -DCUSTOM_SDIO_F2_BLKSIZE=256 -ifeq ($(CONFIG_VTS_SUPPORT),y) -DHDCFLAGS += \ - -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \ - -DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ - -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHDTCPACK_SUPPRESS -DDHD_WAKE_STATUS \ - -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DDHD_USE_STATIC_MEMDUMP - -DHDOFILES += dhd_debug_linux.o dhd_debug.o bcmxtlv.o \ - dhd_rtt.o bcm_app_utils.o -endif - DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \ dhd_sdio.o dhd_cdc.o dhd_wlfc.o @@ -74,12 +62,28 @@ ifneq ($(CONFIG_BCMDHD_PCIE),) DHDCFLAGS += \ -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1 DHDCFLAGS += -DDHD_PCIE_BAR1_WIN_BASE_FIX=0x200000 +ifneq ($(CONFIG_PCI_MSI),) DHDCFLAGS += -DDHD_USE_MSI +endif +ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) +DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF +endif DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o \ dhd_msgbuf.o endif +ifeq ($(CONFIG_VTS_SUPPORT),y) +DHDCFLAGS += \ + -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG \ + -DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DKEEP_ALIVE -DPKT_FILTER_SUPPORT \ + -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHDTCPACK_SUPPRESS -DDHD_WAKE_STATUS \ + -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP + +DHDOFILES += dhd_debug_linux.o dhd_debug.o bcmxtlv.o \ + dhd_rtt.o bcm_app_utils.o +endif + obj-$(CONFIG_BCMDHD) += dhd.o dhd-objs += $(DHDOFILES) @@ -96,7 +100,8 @@ endif ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y) #obj-m += dhd_static_buf.o -DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF -DCONFIG_DHD_USE_STATIC_BUF +DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF +DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -DCONFIG_DHD_USE_STATIC_BUF endif ifneq ($(CONFIG_WIRELESS_EXT),) diff --git a/bcmdhd.1.579.77.41.1.cn/bcmsdh_sdmmc.c b/bcmdhd.1.579.77.41.1.cn/bcmsdh_sdmmc.c index d98411f..0921a6c 100644 --- a/bcmdhd.1.579.77.41.1.cn/bcmsdh_sdmmc.c +++ b/bcmdhd.1.579.77.41.1.cn/bcmsdh_sdmmc.c @@ -57,18 +57,6 @@ mmc_host_clk_release(struct mmc_host *host) #include #else #include -static inline void mmc_host_clk_hold(struct mmc_host *host) -{ -} - -static inline void mmc_host_clk_release(struct mmc_host *host) -{ -} - -static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) -{ - return host->ios.clock; -} #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0)) */ #include #include diff --git a/bcmdhd.1.579.77.41.1.cn/dhd.h b/bcmdhd.1.579.77.41.1.cn/dhd.h index 0c46434..bccc5bf 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd.h +++ b/bcmdhd.1.579.77.41.1.cn/dhd.h @@ -443,12 +443,8 @@ enum dhd_rsdb_scan_features { /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN -#ifdef CUSTOM_SDIO_F2_BLKSIZE -#define DHD_SDALIGN CUSTOM_SDIO_F2_BLKSIZE -#else #define DHD_SDALIGN 32 #endif -#endif /** * DMA-able buffer parameters @@ -1494,7 +1490,7 @@ extern void dhd_os_dhdiovar_lock(dhd_pub_t *pub); extern void dhd_os_dhdiovar_unlock(dhd_pub_t *pub); extern int dhd_os_proto_block(dhd_pub_t * pub); extern int dhd_os_proto_unblock(dhd_pub_t * pub); -extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition); +extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool resched); extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); extern unsigned int dhd_os_get_ioctl_resp_timeout(void); extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_config.c b/bcmdhd.1.579.77.41.1.cn/dhd_config.c index 700573f..5fddc37 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_config.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_config.c @@ -59,6 +59,7 @@ uint config_msg_level = CONFIG_ERROR_LEVEL; #define CONFIG_BCM43341B0 "config_43341b0.txt" #define CONFIG_BCM43241B4 "config_43241b4.txt" #define CONFIG_BCM4339A0 "config_4339a0.txt" +#define CONFIG_BCM43454C0 "config_43454c0.txt" #define CONFIG_BCM43455C0 "config_43455c0.txt" #define CONFIG_BCM43456C5 "config_43456c5.txt" #define CONFIG_BCM4354A1 "config_4354a1.txt" @@ -80,7 +81,7 @@ uint config_msg_level = CONFIG_ERROR_LEVEL; #define FW_BCM43438A0 "fw_bcm43438a0" #define FW_BCM43438A1 "fw_bcm43438a1" #define FW_BCM43436B0 "fw_bcm43436b0" -#define FW_BCM43012B0 "fw_bcm43012b0" +#define FW_BCM43013B0 "fw_bcm43013b0" #define FW_BCM43341B1 "fw_bcm43341b0_ag" #define FW_BCM43241B4 "fw_bcm43241b4_ag" #define FW_BCM4339A0 "fw_bcm4339a0_ag" @@ -92,10 +93,11 @@ uint config_msg_level = CONFIG_ERROR_LEVEL; #define FW_BCM4359B1 "fw_bcm4359b1_ag" #define FW_BCM4359C0 "fw_bcm4359c0_ag" -#define CLM_BCM43012B0 "clm_bcm43012b0" +#define CLM_BCM43013B0 "clm_bcm43013b0" #endif #ifdef BCMPCIE #define FW_BCM4356A2 "fw_bcm4356a2_pcie_ag" +#define FW_BCM4359C0 "fw_bcm4359c0_pcie_ag" #endif #define htod32(i) i @@ -389,6 +391,21 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, char *nv_path) } #endif +void +dhd_conf_free_country_list(conf_country_list_t *country_list) +{ + int i; + + CONFIG_TRACE(("%s called\n", __FUNCTION__)); + for (i=0; icount; i++) { + if (country_list->cspec[i]) { + CONFIG_TRACE(("%s Free cspec %p\n", __FUNCTION__, country_list->cspec[i])); + kfree(country_list->cspec[i]); + } + } + country_list->count = 0; +} + void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) { @@ -417,7 +434,10 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) /* find out the last '/' */ i = strlen(fw_path); while (i > 0) { - if (fw_path[i] == '/') break; + if (fw_path[i] == '/') { + i++; + break; + } i--; } #ifdef BAND_AG @@ -447,92 +467,93 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path) case BCM4330_CHIP_ID: if (ag_type == FW_TYPE_G) { if (chiprev == BCM4330B2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4330B2); + strcpy(&fw_path[i], FW_BCM4330B2); } else { if (chiprev == BCM4330B2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4330B2_AG); + strcpy(&fw_path[i], FW_BCM4330B2_AG); } break; case BCM43362_CHIP_ID: if (chiprev == BCM43362A0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43362A0); + strcpy(&fw_path[i], FW_BCM43362A0); else - strcpy(&fw_path[i+1], FW_BCM43362A2); + strcpy(&fw_path[i], FW_BCM43362A2); break; case BCM43430_CHIP_ID: if (chiprev == BCM43430A0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43438A0); + strcpy(&fw_path[i], FW_BCM43438A0); else if (chiprev == BCM43430A1_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43438A1); + strcpy(&fw_path[i], FW_BCM43438A1); else if (chiprev == BCM43430A2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43436B0); + strcpy(&fw_path[i], FW_BCM43436B0); break; case BCM43012_CHIP_ID: - if (chiprev == BCM43012B0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43012B0); + if (chiprev == BCM43013B0_CHIP_REV) + strcpy(&fw_path[i], FW_BCM43013B0); break; case BCM4334_CHIP_ID: if (chiprev == BCM4334B1_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4334B1); + strcpy(&fw_path[i], FW_BCM4334B1); break; case BCM43340_CHIP_ID: case BCM43341_CHIP_ID: if (chiprev == BCM43341B0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43341B1); + strcpy(&fw_path[i], FW_BCM43341B1); break; case BCM4324_CHIP_ID: if (chiprev == BCM43241B4_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43241B4); + strcpy(&fw_path[i], FW_BCM43241B4); break; case BCM4335_CHIP_ID: if (chiprev == BCM4335A0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4339A0); + strcpy(&fw_path[i], FW_BCM4339A0); break; case BCM4339_CHIP_ID: if (chiprev == BCM4339A0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4339A0); - break; - case BCM43454_CHIP_ID: - if (chiprev == BCM43455C0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43455C0); + strcpy(&fw_path[i], FW_BCM4339A0); break; case BCM4345_CHIP_ID: + case BCM43454_CHIP_ID: if (chiprev == BCM43455C0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43455C0); - else if (chiprev == BCM43455C5_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM43456C5); + strcpy(&fw_path[i], FW_BCM43455C0); + else if (chiprev == BCM43456C5_CHIP_REV) + strcpy(&fw_path[i], FW_BCM43456C5); break; case BCM4354_CHIP_ID: if (chiprev == BCM4354A1_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4354A1); + strcpy(&fw_path[i], FW_BCM4354A1); else if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4356A2); + strcpy(&fw_path[i], FW_BCM4356A2); break; case BCM4356_CHIP_ID: case BCM4371_CHIP_ID: if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4356A2); + strcpy(&fw_path[i], FW_BCM4356A2); break; case BCM43569_CHIP_ID: if (chiprev == BCM4358A3_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4358A3); + strcpy(&fw_path[i], FW_BCM4358A3); break; case BCM4359_CHIP_ID: if (chiprev == BCM4359B1_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4359B1); + strcpy(&fw_path[i], FW_BCM4359B1); else if (chiprev == BCM4359C0_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4359C0); + strcpy(&fw_path[i], FW_BCM4359C0); break; #endif #ifdef BCMPCIE case BCM4354_CHIP_ID: case BCM4356_CHIP_ID: if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&fw_path[i+1], FW_BCM4356A2); + strcpy(&fw_path[i], FW_BCM4356A2); + break; + case BCM4359_CHIP_ID: + if (chiprev == BCM4359C0_CHIP_REV) + strcpy(&fw_path[i], FW_BCM4359C0); break; #endif default: - strcpy(&fw_path[i+1], "fw_bcmdhd"); + strcpy(&fw_path[i], "fw_bcmdhd"); } strcat(fw_path, fw_tail); @@ -557,7 +578,10 @@ dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path) /* find out the last '/' */ i = strlen(clm_path); while (i > 0) { - if (clm_path[i] == '/') break; + if (clm_path[i] == '/') { + i++; + break; + } i--; } @@ -566,12 +590,12 @@ dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path) switch (chip) { #ifdef BCMSDIO case BCM43012_CHIP_ID: - if (chiprev == BCM43012B0_CHIP_REV) - strcpy(&clm_path[i+1], CLM_BCM43012B0); + if (chiprev == BCM43013B0_CHIP_REV) + strcpy(&clm_path[i], CLM_BCM43013B0); break; #endif default: - strcpy(&clm_path[i+1], "clm_bcmdhd"); + strcpy(&clm_path[i], "clm_bcmdhd"); } strcat(clm_path, fw_tail); @@ -612,11 +636,14 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path) /* find out the last '/' */ i = strlen(nv_path); while (i > 0) { - if (nv_path[i] == '/') break; + if (nv_path[i] == '/') { + i++; + break; + } i--; } - strcpy(&nv_path[i+1], dhd->conf->nv_by_chip.m_chip_nv_path_head[matched].name); + strcpy(&nv_path[i], dhd->conf->nv_by_chip.m_chip_nv_path_head[matched].name); CONFIG_TRACE(("%s: nvram_path=%s\n", __FUNCTION__, nv_path)); } @@ -635,10 +662,13 @@ dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path /* find out the last '/' */ i = strlen(dst_path); while (i > 0) { - if (dst_path[i] == '/') break; + if (dst_path[i] == '/') { + i++; + break; + } i--; } - strcpy(&dst_path[i+1], dst_name); + strcpy(&dst_path[i], dst_name); CONFIG_TRACE(("%s: dst_path=%s\n", __FUNCTION__, dst_path)); } @@ -661,7 +691,10 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) /* find out the last '/' */ i = strlen(conf_path); while (i > 0) { - if (conf_path[i] == '/') break; + if (conf_path[i] == '/') { + i++; + break; + } i--; } @@ -669,77 +702,84 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path) #ifdef BCMSDIO case BCM4330_CHIP_ID: if (chiprev == BCM4330B2_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4330B2); + strcpy(&conf_path[i], CONFIG_BCM4330B2); break; case BCM43362_CHIP_ID: if (chiprev == BCM43362A0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43362A0); + strcpy(&conf_path[i], CONFIG_BCM43362A0); else - strcpy(&conf_path[i+1], CONFIG_BCM43362A2); + strcpy(&conf_path[i], CONFIG_BCM43362A2); break; case BCM43430_CHIP_ID: if (chiprev == BCM43430A0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43438A0); + strcpy(&conf_path[i], CONFIG_BCM43438A0); else if (chiprev == BCM43430A1_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43438A1); + strcpy(&conf_path[i], CONFIG_BCM43438A1); else if (chiprev == BCM43430A2_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43436B0); + strcpy(&conf_path[i], CONFIG_BCM43436B0); break; case BCM4334_CHIP_ID: if (chiprev == BCM4334B1_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4334B1); + strcpy(&conf_path[i], CONFIG_BCM4334B1); break; case BCM43340_CHIP_ID: case BCM43341_CHIP_ID: if (chiprev == BCM43341B0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43341B0); + strcpy(&conf_path[i], CONFIG_BCM43341B0); break; case BCM4324_CHIP_ID: if (chiprev == BCM43241B4_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43241B4); + strcpy(&conf_path[i], CONFIG_BCM43241B4); break; case BCM4335_CHIP_ID: if (chiprev == BCM4335A0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4339A0); + strcpy(&conf_path[i], CONFIG_BCM4339A0); break; - case BCM4345_CHIP_ID: case BCM43454_CHIP_ID: if (chiprev == BCM43455C0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43455C0); - else if (chiprev == BCM43455C5_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM43456C5); + strcpy(&conf_path[i], CONFIG_BCM43454C0); + break; + case BCM4345_CHIP_ID: + if (chiprev == BCM43455C0_CHIP_REV) + strcpy(&conf_path[i], CONFIG_BCM43455C0); + else if (chiprev == BCM43456C5_CHIP_REV) + strcpy(&conf_path[i], CONFIG_BCM43456C5); break; case BCM4339_CHIP_ID: if (chiprev == BCM4339A0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4339A0); + strcpy(&conf_path[i], CONFIG_BCM4339A0); break; case BCM4354_CHIP_ID: if (chiprev == BCM4354A1_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4354A1); + strcpy(&conf_path[i], CONFIG_BCM4354A1); else if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4356A2); + strcpy(&conf_path[i], CONFIG_BCM4356A2); break; case BCM4356_CHIP_ID: case BCM4371_CHIP_ID: if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4356A2); + strcpy(&conf_path[i], CONFIG_BCM4356A2); break; case BCM43569_CHIP_ID: if (chiprev == BCM4358A3_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4358A3); + strcpy(&conf_path[i], CONFIG_BCM4358A3); break; case BCM4359_CHIP_ID: if (chiprev == BCM4359B1_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4359B1); + strcpy(&conf_path[i], CONFIG_BCM4359B1); else if (chiprev == BCM4359C0_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4359C0); + strcpy(&conf_path[i], CONFIG_BCM4359C0); break; #endif #ifdef BCMPCIE case BCM4354_CHIP_ID: case BCM4356_CHIP_ID: if (chiprev == BCM4356A2_CHIP_REV) - strcpy(&conf_path[i+1], CONFIG_BCM4356A2); + strcpy(&conf_path[i], CONFIG_BCM4356A2); + break; + case BCM4359_CHIP_ID: + if (chiprev == BCM4359C0_CHIP_REV) + strcpy(&conf_path[i], CONFIG_BCM4359C0); break; #endif } @@ -838,19 +878,6 @@ dhd_conf_get_band(dhd_pub_t *dhd) return band; } -int -dhd_conf_set_country(dhd_pub_t *dhd) -{ - int bcmerror = -1; - - memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t)); - printf("%s: set country %s, revision %d\n", __FUNCTION__, - dhd->conf->cspec.ccode, dhd->conf->cspec.rev); - dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)&dhd->conf->cspec, sizeof(wl_country_t), FALSE); - - return bcmerror; -} - int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec) { @@ -860,23 +887,28 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec) bcm_mkiovar("country", NULL, 0, (char*)cspec, sizeof(wl_country_t)); if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cspec, sizeof(wl_country_t), FALSE, 0)) < 0) CONFIG_ERROR(("%s: country code getting failed %d\n", __FUNCTION__, bcmerror)); - else - printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev); return bcmerror; } int -dhd_conf_get_country_from_config(dhd_pub_t *dhd, wl_country_t *cspec) +dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs) { int bcmerror = -1, i; struct dhd_conf *conf = dhd->conf; + conf_country_list_t *country_list; + + if ((nodfs > 0 || dhd->op_mode & DHD_FLAG_HOSTAP_MODE) && + conf->country_list_nodfs.count > 0) { + country_list = &conf->country_list_nodfs; + } else { + country_list = &conf->country_list; + } - for (i = 0; i < conf->country_list.count; i++) { - if (!strncmp(cspec->country_abbrev, conf->country_list.cspec[i].country_abbrev, 2)) { - memcpy(cspec->ccode, - conf->country_list.cspec[i].ccode, WLC_CNTRY_BUF_SZ); - cspec->rev = conf->country_list.cspec[i].rev; + for (i = 0; i < country_list->count; i++) { + if (!strncmp(cspec->country_abbrev, country_list->cspec[i]->country_abbrev, 2)) { + memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ); + cspec->rev = country_list->cspec[i]->rev; printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev); return 0; } @@ -885,6 +917,21 @@ dhd_conf_get_country_from_config(dhd_pub_t *dhd, wl_country_t *cspec) return bcmerror; } +int +dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec) +{ + int bcmerror = -1; + + memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t)); + + printf("%s: set country %s, revision %d\n", __FUNCTION__, cspec->ccode, cspec->rev); + dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)cspec, sizeof(wl_country_t), FALSE); + dhd_conf_get_country(dhd, cspec); + printf("Country code: %s (%s/%d)\n", cspec->country_abbrev, cspec->ccode, cspec->rev); + + return bcmerror; +} + int dhd_conf_fix_country(dhd_pub_t *dhd) { @@ -892,6 +939,7 @@ dhd_conf_fix_country(dhd_pub_t *dhd) uint band; wl_uint32_list_t *list; u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; + wl_country_t cspec; if (!(dhd && dhd->conf)) { return bcmerror; @@ -910,11 +958,13 @@ dhd_conf_fix_country(dhd_pub_t *dhd) dtoh32(list->count)<11)) { CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n", __FUNCTION__, bcmerror, dtoh32(list->count))); - if ((bcmerror = dhd_conf_set_country(dhd)) < 0) { - strcpy(dhd->conf->cspec.country_abbrev, "US"); - dhd->conf->cspec.rev = 0; - strcpy(dhd->conf->cspec.ccode, "US"); - dhd_conf_set_country(dhd); + dhd_conf_map_country_list(dhd, &dhd->conf->cspec, 0); + if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) { + strcpy(cspec.country_abbrev, "US"); + cspec.rev = 0; + strcpy(cspec.ccode, "US"); + dhd_conf_map_country_list(dhd, &cspec, 0); + dhd_conf_set_country(dhd, &cspec); } } @@ -1131,12 +1181,32 @@ dhd_conf_set_wme(dhd_pub_t *dhd, int mode) return; } +void +dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode) +{ + int i; + struct dhd_conf *conf = dhd->conf; + bool set = true; + + for (i=0; imchan[i].bw >= 0); + set &= ((conf->mchan[i].p2p_mode == -1) | (conf->mchan[i].p2p_mode == p2p_mode)); + set &= ((conf->mchan[i].miracast_mode == -1) | (conf->mchan[i].miracast_mode == miracast_mode)); + if (set) { + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", conf->mchan[i].bw, 0, FALSE); + } + } + + return; +} + #ifdef PKT_FILTER_SUPPORT void dhd_conf_add_pkt_filter(dhd_pub_t *dhd) { int i, j; - char str[12]; + char str[16]; #define MACS "%02x%02x%02x%02x%02x%02x" /* @@ -1157,17 +1227,17 @@ dhd_conf_add_pkt_filter(dhd_pub_t *dhd) } dhd->pktfilter_count += i; - for(i=0; iconf->magic_pkt_filter_add.count; i++) { - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], " 0x"); - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF"); + if (dhd->conf->magic_pkt_filter_add) { + strcat(dhd->conf->magic_pkt_filter_add, " 0x"); + strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF"); for (j=0; j<16; j++) - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF"); - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], " 0x"); - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF"); + strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF"); + strcat(dhd->conf->magic_pkt_filter_add, " 0x"); + strcat(dhd->conf->magic_pkt_filter_add, "FFFFFFFFFFFF"); sprintf(str, MACS, MAC2STRDBG(dhd->mac.octet)); for (j=0; j<16; j++) - strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], str); - dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->magic_pkt_filter_add.filter[i]; + strncat(dhd->conf->magic_pkt_filter_add, str, 12); + dhd->pktfilter[dhd->pktfilter_count] = dhd->conf->magic_pkt_filter_add; dhd->pktfilter_count += 1; } } @@ -1730,6 +1800,7 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) char *pch, *pick_tmp; struct dhd_conf *conf = dhd->conf; char *data = full_param+len_param; + wl_country_t *cspec; /* Process country_list: * country_list=[country1]:[ccode1]/[regrev1], @@ -1743,23 +1814,125 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param) pch = bcmstrtok(&pick_tmp, ":", 0); if (!pch) break; - strcpy(conf->country_list.cspec[i].country_abbrev, pch); + cspec = NULL; + if (!(cspec = kmalloc(sizeof(wl_country_t), GFP_KERNEL))) { + CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + break; + } + conf->country_list.count++; + memset(cspec, 0, sizeof(wl_country_t)); + conf->country_list.cspec[i] = cspec; + + strcpy(cspec->country_abbrev, pch); pch = bcmstrtok(&pick_tmp, "/", 0); if (!pch) break; - memcpy(conf->country_list.cspec[i].ccode, pch, 2); + memcpy(cspec->ccode, pch, 2); pch = bcmstrtok(&pick_tmp, ", ", 0); if (!pch) break; - conf->country_list.cspec[i].rev = (int32)simple_strtol(pch, NULL, 10); - conf->country_list.count ++; + cspec->rev = (int32)simple_strtol(pch, NULL, 10); CONFIG_TRACE(("%s: country_list abbrev=%s, ccode=%s, regrev=%d\n", __FUNCTION__, - conf->country_list.cspec[i].country_abbrev, - conf->country_list.cspec[i].ccode, - conf->country_list.cspec[i].rev)); + cspec->country_abbrev, cspec->ccode, cspec->rev)); } printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count); } + else if (!strncmp("country_list_nodfs=", full_param, len_param)) { + pick_tmp = data; + for (i=0; icountry_list_nodfs.count++; + memset(cspec, 0, sizeof(wl_country_t)); + conf->country_list_nodfs.cspec[i] = cspec; + + strcpy(cspec->country_abbrev, pch); + pch = bcmstrtok(&pick_tmp, "/", 0); + if (!pch) + break; + memcpy(cspec->ccode, pch, 2); + pch = bcmstrtok(&pick_tmp, ", ", 0); + if (!pch) + break; + cspec->rev = (int32)simple_strtol(pch, NULL, 10); + CONFIG_TRACE(("%s: country_list_nodfs abbrev=%s, ccode=%s, regrev=%d\n", __FUNCTION__, + cspec->country_abbrev, cspec->ccode, cspec->rev)); + } + printf("%s: %d nodfs country in list\n", __FUNCTION__, conf->country_list_nodfs.count); + } + else + return false; + + return true; +} + +bool +dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param) +{ + int i; + char *pch, *pick_tmp, *pick_tmp2; + struct dhd_conf *conf = dhd->conf; + char *data = full_param+len_param; + + /* Process mchan_bw and btc_params_mgmt: + * mchan_bw=[val]/[any/go/gc]/[any/source/sink] + * Ex: mchan_bw=80/go/source, 30/gc/sink + */ + if (!strncmp("mchan_bw=", full_param, len_param)) { + pick_tmp = data; + for (i=0; imchan[i].bw = (int)simple_strtol(pch, NULL, 0); + if (conf->mchan[i].bw < 0 || conf->mchan[i].bw > 100) { + CONFIG_ERROR(("%s: wrong bw %d\n", __FUNCTION__, conf->mchan[i].bw)); + conf->mchan[i].bw = 0; + break; + } + } + pch = bcmstrtok(&pick_tmp2, "/", 0); + if (!pch) { + break; + } else { + if (bcmstrstr(pch, "any")) { + conf->mchan[i].p2p_mode = -1; + } else if (bcmstrstr(pch, "go")) { + conf->mchan[i].p2p_mode = WL_P2P_IF_GO; + } else if (bcmstrstr(pch, "gc")) { + conf->mchan[i].p2p_mode = WL_P2P_IF_CLIENT; + } + } + pch = bcmstrtok(&pick_tmp2, "/", 0); + if (!pch) { + break; + } else { + if (bcmstrstr(pch, "any")) { + conf->mchan[i].miracast_mode = -1; + } else if (bcmstrstr(pch, "source")) { + conf->mchan[i].miracast_mode = MIRACAST_SOURCE; + } else if (bcmstrstr(pch, "sink")) { + conf->mchan[i].miracast_mode = MIRACAST_SINK; + } + } + } + for (i=0; imchan[i].bw >= 0) + printf("%s: mchan_bw=%d/%d/%d\n", __FUNCTION__, + conf->mchan[i].bw, conf->mchan[i].p2p_mode, conf->mchan[i].miracast_mode); + } + } else return false; @@ -1815,16 +1988,13 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param) printf("\n"); } else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) { - pick_tmp = data; - pch = bcmstrtok(&pick_tmp, ",.-", 0); - i=0; - while (pch != NULL && imagic_pkt_filter_add.filter[i][0], pch); - printf("%s: magic_pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->magic_pkt_filter_add.filter[i][0]); - pch = bcmstrtok(&pick_tmp, ",.-", 0); - i++; + if (!(conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL))) { + CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + } else { + memset(conf->magic_pkt_filter_add, 0, MAGIC_PKT_FILTER_LEN); + strcpy(conf->magic_pkt_filter_add, data); + printf("%s: magic_pkt_filter_add = %s\n", __FUNCTION__, conf->magic_pkt_filter_add); } - conf->magic_pkt_filter_add.count = i; } else return false; @@ -2007,13 +2177,6 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->bus_rxglom = TRUE; printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom); } - else if (!strncmp("dhd_poll=", full_param, len_param)) { - if (!strncmp(data, "0", 1)) - conf->dhd_poll = 0; - else - conf->dhd_poll = 1; - printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll); - } else if (!strncmp("deferred_tx_len=", full_param, len_param)) { conf->deferred_tx_len = (int)simple_strtol(data, NULL, 10); printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len); @@ -2048,6 +2211,27 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param) } #endif +#ifdef BCMPCIE +bool +dhd_conf_read_pcie_params(dhd_pub_t *dhd, char *full_param, uint len_param) +{ + struct dhd_conf *conf = dhd->conf; + char *data = full_param+len_param; + + if (!strncmp("bus:deepsleep_disable=", full_param, len_param)) { + if (!strncmp(data, "0", 1)) + conf->bus_deepsleep_disable = 0; + else + conf->bus_deepsleep_disable = 1; + printf("%s: bus:deepsleep_disable = %d\n", __FUNCTION__, conf->bus_deepsleep_disable); + } + else + return false; + + return true; +} +#endif + bool dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) { @@ -2088,6 +2272,15 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param) conf->ap_in_suspend = (int)simple_strtol(data, NULL, 10); printf("%s: ap_in_suspend = %d\n", __FUNCTION__, conf->ap_in_suspend); } +#ifdef SUSPEND_EVENT + else if (!strncmp("suspend_eventmask_enable=", full_param, len_param)) { + if (!strncmp(data, "1", 1)) + conf->suspend_eventmask_enable = TRUE; + else + conf->suspend_eventmask_enable = FALSE; + printf("%s: suspend_eventmask_enable = %d\n", __FUNCTION__, conf->suspend_eventmask_enable); + } +#endif else return false; @@ -2103,7 +2296,18 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) char *pch, *pick_tmp; int i; - if (!strncmp("band=", full_param, len_param)) { + if (!strncmp("dhd_poll=", full_param, len_param)) { + if (!strncmp(data, "0", 1)) + conf->dhd_poll = 0; + else + conf->dhd_poll = 1; + printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll); + } + else if (!strncmp("dhd_watchdog_ms=", full_param, len_param)) { + dhd_watchdog_ms = (int)simple_strtol(data, NULL, 10); + printf("%s: dhd_watchdog_ms = %d\n", __FUNCTION__, dhd_watchdog_ms); + } + else if (!strncmp("band=", full_param, len_param)) { /* Process band: * band=a for 5GHz only and band=b for 2.4GHz only */ @@ -2242,6 +2446,14 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param) conf->tsq = (int)simple_strtol(data, NULL, 10); printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq); } + else if (!strncmp("ctrl_resched=", full_param, len_param)) { + conf->ctrl_resched = (int)simple_strtol(data, NULL, 10); + printf("%s: ctrl_resched = %d\n", __FUNCTION__, conf->ctrl_resched); + } + else if (!strncmp("dhd_ioctl_timeout_msec=", full_param, len_param)) { + conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10); + printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec); + } else return false; @@ -2324,6 +2536,8 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) continue; else if (dhd_conf_read_country_list(dhd, pick, len_param)) continue; + else if (dhd_conf_read_mchan_params(dhd, pick, len_param)) + continue; #ifdef PKT_FILTER_SUPPORT else if (dhd_conf_read_pkt_filter(dhd, pick, len_param)) continue; @@ -2340,6 +2554,10 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path) else if (dhd_conf_read_sdio_params(dhd, pick, len_param)) continue; #endif /* BCMSDIO */ +#ifdef BCMPCIE + else if (dhd_conf_read_pcie_params(dhd, pick, len_param)) + continue; +#endif /* BCMPCIE */ else if (dhd_conf_read_pm_params(dhd, pick, len_param)) continue; else if (dhd_conf_read_others(dhd, pick, len_param)) @@ -2435,6 +2653,7 @@ int dhd_conf_preinit(dhd_pub_t *dhd) { struct dhd_conf *conf = dhd->conf; + int i; CONFIG_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -2443,6 +2662,10 @@ dhd_conf_preinit(dhd_pub_t *dhd) dhd_conf_free_mac_list(&conf->nv_by_mac); dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip); #endif + dhd_conf_free_country_list(&conf->country_list); + dhd_conf_free_country_list(&dhd->conf->country_list_nodfs); + if (conf->magic_pkt_filter_add) + kfree(conf->magic_pkt_filter_add); memset(&conf->country_list, 0, sizeof(conf_country_list_t)); conf->band = -1; conf->mimo_bw_cap = -1; @@ -2499,7 +2722,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) #ifdef PKT_FILTER_SUPPORT memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t)); memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t)); - memset(&conf->magic_pkt_filter_add, 0, sizeof(conf_pkt_filter_del_t)); #endif conf->srl = -1; conf->lrl = -1; @@ -2508,6 +2730,7 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txbf = -1; conf->lpc = -1; conf->disable_proptx = -1; + conf->dhd_poll = -1; #ifdef BCMSDIO conf->bus_txglom = -1; conf->use_rxchain = 0; @@ -2515,7 +2738,6 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txglom_ext = FALSE; conf->tx_max_offset = 0; conf->txglomsize = SDPCM_DEFGLOM_SIZE; - conf->dhd_poll = -1; conf->txctl_tmo_fix = 5; conf->tx_in_rx = TRUE; conf->txglom_mode = SDPCM_TXGLOM_MDESC; @@ -2524,6 +2746,9 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->txinrx_thres = -1; conf->sd_f2_blocksize = 0; conf->oob_enabled_later = FALSE; +#endif +#ifdef BCMPCIE + conf->bus_deepsleep_disable = 1; #endif conf->ampdu_ba_wsize = 0; conf->ampdu_hostreorder = -1; @@ -2537,6 +2762,11 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->num_different_channels = -1; conf->xmit_in_suspend = TRUE; conf->ap_in_suspend = 0; +#ifdef SUSPEND_EVENT + conf->suspend_eventmask_enable = FALSE; + memset(&conf->suspend_eventmask, 0, sizeof(conf->suspend_eventmask)); + memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask)); +#endif #ifdef IDHCP conf->dhcpc_enable = -1; conf->dhcpd_enable = -1; @@ -2553,19 +2783,27 @@ dhd_conf_preinit(dhd_pub_t *dhd) conf->rsdb_mode = -2; conf->vhtmode = -1; conf->autocountry = -1; + conf->ctrl_resched = 2; + conf->dhd_ioctl_timeout_msec = 0; #ifdef IAPSTA_PREINIT memset(conf->iapsta_init, 0, sizeof(conf->iapsta_init)); memset(conf->iapsta_config, 0, sizeof(conf->iapsta_config)); memset(conf->iapsta_enable, 0, sizeof(conf->iapsta_enable)); #endif + for (i=0; imchan[i], -1, sizeof(mchan_params_t)); + } #ifdef CUSTOMER_HW_AMLOGIC dhd_slpauto = FALSE; + conf->txglom_mode = SDPCM_TXGLOM_CPY; #endif if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID || conf->chip == BCM4371_CHIP_ID || conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) { #ifdef DHDTCPACK_SUPPRESS +#ifdef BCMSDIO conf->tcpack_sup_mode = TCPACK_SUP_REPLACE; +#endif #endif dhd_rxbound = 128; dhd_txbound = 64; @@ -2620,6 +2858,10 @@ dhd_conf_reset(dhd_pub_t *dhd) dhd_conf_free_mac_list(&dhd->conf->nv_by_mac); dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); #endif + dhd_conf_free_country_list(&dhd->conf->country_list); + dhd_conf_free_country_list(&dhd->conf->country_list_nodfs); + if (dhd->conf->magic_pkt_filter_add) + kfree(dhd->conf->magic_pkt_filter_add); memset(dhd->conf, 0, sizeof(dhd_conf_t)); return 0; } @@ -2663,6 +2905,10 @@ dhd_conf_detach(dhd_pub_t *dhd) dhd_conf_free_mac_list(&dhd->conf->nv_by_mac); dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip); #endif + dhd_conf_free_country_list(&dhd->conf->country_list); + dhd_conf_free_country_list(&dhd->conf->country_list_nodfs); + if (dhd->conf->magic_pkt_filter_add) + kfree(dhd->conf->magic_pkt_filter_add); MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t)); } dhd->conf = NULL; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_config.h b/bcmdhd.1.579.77.41.1.cn/dhd_config.h index 5fdd538..ca295f1 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_config.h +++ b/bcmdhd.1.579.77.41.1.cn/dhd_config.h @@ -23,7 +23,7 @@ extern uint dhd_slpauto; #define BCM43430A0_CHIP_REV 0 #define BCM43430A1_CHIP_REV 1 #define BCM43430A2_CHIP_REV 2 -#define BCM43012B0_CHIP_REV 1 +#define BCM43013B0_CHIP_REV 1 #define BCM4330B2_CHIP_REV 4 #define BCM4334B1_CHIP_REV 3 #define BCM43341B0_CHIP_REV 2 @@ -31,13 +31,13 @@ extern uint dhd_slpauto; #define BCM4335A0_CHIP_REV 2 #define BCM4339A0_CHIP_REV 1 #define BCM43455C0_CHIP_REV 6 -#define BCM43455C5_CHIP_REV 9 +#define BCM43456C5_CHIP_REV 9 #define BCM4354A1_CHIP_REV 1 #define BCM4359B1_CHIP_REV 5 -#define BCM4359C0_CHIP_REV 9 #endif #define BCM4356A2_CHIP_REV 2 #define BCM4358A3_CHIP_REV 3 +#define BCM4359C0_CHIP_REV 9 typedef struct wl_mac_range { uint32 oui; @@ -82,6 +82,7 @@ typedef struct wmes_param { #ifdef PKT_FILTER_SUPPORT #define DHD_CONF_FILTER_MAX 8 #define PKT_FILTER_LEN 300 +#define MAGIC_PKT_FILTER_LEN 450 typedef struct conf_pkt_filter_add { uint32 count; char filter[DHD_CONF_FILTER_MAX][PKT_FILTER_LEN]; @@ -96,9 +97,19 @@ typedef struct conf_pkt_filter_del { #define CONFIG_COUNTRY_LIST_SIZE 100 typedef struct conf_country_list { uint32 count; - wl_country_t cspec[CONFIG_COUNTRY_LIST_SIZE]; + wl_country_t *cspec[CONFIG_COUNTRY_LIST_SIZE]; } conf_country_list_t; +/* mchan_params */ +#define MCHAN_MAX_NUM 4 +#define MIRACAST_SOURCE 1 +#define MIRACAST_SINK 2 +typedef struct mchan_params { + int bw; + int p2p_mode; + int miracast_mode; +} mchan_params_t; + typedef struct dhd_conf { uint chip; uint chiprev; @@ -106,6 +117,7 @@ typedef struct dhd_conf { wl_mac_list_ctrl_t nv_by_mac; wl_chip_nv_path_list_ctrl_t nv_by_chip; conf_country_list_t country_list; + conf_country_list_t country_list_nodfs; int band; int mimo_bw_cap; int bw_cap_2g; @@ -114,7 +126,7 @@ typedef struct dhd_conf { wl_channel_list_t channels; uint roam_off; uint roam_off_suspend; - int roam_trigger[2]; + int roam_trigger[2]; int roam_scan_period[2]; int roam_delta[2]; int fullroamperiod; @@ -127,7 +139,7 @@ typedef struct dhd_conf { #ifdef PKT_FILTER_SUPPORT conf_pkt_filter_add_t pkt_filter_add; conf_pkt_filter_del_t pkt_filter_del; - conf_pkt_filter_add_t magic_pkt_filter_add; + char *magic_pkt_filter_add; #endif int srl; int lrl; @@ -136,6 +148,7 @@ typedef struct dhd_conf { int txbf; int lpc; int disable_proptx; + int dhd_poll; #ifdef BCMSDIO int bus_txglom; int use_rxchain; @@ -148,7 +161,6 @@ typedef struct dhd_conf { */ int tx_max_offset; uint txglomsize; - int dhd_poll; int txctl_tmo_fix; bool tx_in_rx; bool txglom_mode; @@ -162,6 +174,9 @@ typedef struct dhd_conf { int dhd_txminmax; // -1=DATABUFCNT(bus) uint sd_f2_blocksize; bool oob_enabled_later; +#endif +#ifdef BCMPCIE + int bus_deepsleep_disable; #endif int ampdu_ba_wsize; int ampdu_hostreorder; @@ -200,6 +215,9 @@ typedef struct dhd_conf { char iapsta_enable[50]; #endif int autocountry; + int ctrl_resched; + int dhd_ioctl_timeout_msec; + struct mchan_params mchan[MCHAN_MAX_NUM]; int tsq; } dhd_conf_t; @@ -224,14 +242,15 @@ int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, int def int dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx); int dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, int len, bool down); uint dhd_conf_get_band(dhd_pub_t *dhd); -int dhd_conf_set_country(dhd_pub_t *dhd); +int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec); int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec); -int dhd_conf_get_country_from_config(dhd_pub_t *dhd, wl_country_t *cspec); +int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs); int dhd_conf_fix_country(dhd_pub_t *dhd); bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel); int dhd_conf_set_roam(dhd_pub_t *dhd); void dhd_conf_set_bw_cap(dhd_pub_t *dhd); void dhd_conf_set_wme(dhd_pub_t *dhd, int mode); +void dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int go, int source); void dhd_conf_add_pkt_filter(dhd_pub_t *dhd); bool dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id); void dhd_conf_discard_pkt_filter(dhd_pub_t *dhd); diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c b/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c index 78537c8..1d2ce75 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_gpio.c @@ -15,6 +15,9 @@ #include #endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */ +#ifdef CONFIG_DHD_USE_STATIC_BUF +extern void *bcmdhd_mem_prealloc(int section, unsigned long size); +#endif /* CONFIG_DHD_USE_STATIC_BUF */ static int gpio_wl_reg_on = -1; // WL_REG_ON is input pin of WLAN module #ifdef CUSTOMER_OOB @@ -189,33 +192,21 @@ static int dhd_wlan_get_mac_addr(unsigned char *buf) return err; } -#ifdef CONFIG_DHD_USE_STATIC_BUF -extern void *bcmdhd_mem_prealloc(int section, unsigned long size); -void* bcm_wlan_prealloc(int section, unsigned long size) -{ - void *alloc_ptr = NULL; - alloc_ptr = bcmdhd_mem_prealloc(section, size); - if (alloc_ptr) { - printf("success alloc section %d, size %ld\n", section, size); - if (size != 0L) - bzero(alloc_ptr, size); - return alloc_ptr; - } - printf("can't alloc section %d\n", section); - return NULL; -} -#endif static struct cntry_locales_custom brcm_wlan_translate_custom_table[] = { /* Table should be filled out based on custom platform regulatory requirement */ +#ifdef EXAMPLE_TABLE {"", "XT", 49}, /* Universal if Country code is unknown or empty */ {"US", "US", 0}, +#endif /* EXMAPLE_TABLE */ }; #ifdef CUSTOM_FORCE_NODFS_FLAG struct cntry_locales_custom brcm_wlan_translate_nodfs_table[] = { +#ifdef EXAMPLE_TABLE {"", "XT", 50}, /* Universal if Country code is unknown or empty */ {"US", "US", 0}, +#endif /* EXMAPLE_TABLE */ }; #endif @@ -266,7 +257,7 @@ struct wifi_platform_data dhd_wlan_control = { .set_carddetect = dhd_wlan_set_carddetect, .get_mac_addr = dhd_wlan_get_mac_addr, #ifdef CONFIG_DHD_USE_STATIC_BUF - .mem_prealloc = bcm_wlan_prealloc, + .mem_prealloc = bcmdhd_mem_prealloc, #endif /* CONFIG_DHD_USE_STATIC_BUF */ .get_country_code = dhd_wlan_get_country_code, }; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_linux.c b/bcmdhd.1.579.77.41.1.cn/dhd_linux.c index 3bf901c..70944f5 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_linux.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_linux.c @@ -10995,7 +10995,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if (ret < 0) printf("%s: country code setting failed %d\n", __FUNCTION__, ret); } else { - dhd_conf_set_country(dhd); + dhd_conf_map_country_list(dhd, &dhd->conf->cspec, 0); + dhd_conf_set_country(dhd, &dhd->conf->cspec); dhd_conf_fix_country(dhd); } dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "autocountry", dhd->conf->autocountry, 0, FALSE); @@ -11678,6 +11679,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) // terence 20151210: set bus:txglom after dhd_txglom_enable since it's possible changed in dhd_conf_set_txglom_params dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bus:txglom", dhd->conf->bus_txglom, 0, FALSE); #endif /* defined(BCMSDIO) */ +#if defined(BCMPCIE) + dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bus:deepsleep_disable", dhd->conf->bus_deepsleep_disable, 0, FALSE); +#endif /* defined(BCMPCIE) */ #if defined(BCMSDIO) #ifdef PROP_TXSTATUS @@ -12861,14 +12865,14 @@ void dhd_detach(dhd_pub_t *dhdp) dhd->new_freq = NULL; cpufreq_unregister_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER); #endif + DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter)); #ifdef CONFIG_HAS_WAKELOCK dhd->wakelock_wd_counter = 0; wake_lock_destroy(&dhd->wl_wdwake); - // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry - wake_lock_destroy(&dhd->wl_wifi); + // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry + wake_lock_destroy(&dhd->wl_wifi); #endif /* CONFIG_HAS_WAKELOCK */ if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { - DHD_TRACE(("wd wakelock count:%d\n", dhd->wakelock_wd_counter)); DHD_OS_WAKE_LOCK_DESTROY(dhd); } @@ -13215,10 +13219,15 @@ dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec) } int -dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition) +dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool resched) { dhd_info_t * dhd = (dhd_info_t *)(pub->info); - int timeout; + int timeout, timeout_tmp = dhd_ioctl_timeout_msec; + + if (!resched && pub->conf->ctrl_resched>0 && pub->conf->dhd_ioctl_timeout_msec>0) { + timeout_tmp = dhd_ioctl_timeout_msec; + dhd_ioctl_timeout_msec = pub->conf->dhd_ioctl_timeout_msec; + } /* Convert timeout in millsecond to jiffies */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -13231,6 +13240,10 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition) timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout); + if (!resched && pub->conf->ctrl_resched>0 && pub->conf->dhd_ioctl_timeout_msec>0) { + dhd_ioctl_timeout_msec = timeout_tmp; + } + DHD_PERIM_LOCK(pub); return timeout; @@ -13631,19 +13644,23 @@ dhd_os_sdunlock_txq(dhd_pub_t *pub) void dhd_os_sdlock_rxq(dhd_pub_t *pub) { +#if 0 dhd_info_t *dhd; dhd = (dhd_info_t *)(pub->info); spin_lock_bh(&dhd->rxqlock); +#endif } void dhd_os_sdunlock_rxq(dhd_pub_t *pub) { +#if 0 dhd_info_t *dhd; dhd = (dhd_info_t *)(pub->info); spin_unlock_bh(&dhd->rxqlock); +#endif } static void @@ -14124,6 +14141,9 @@ dhd_dev_get_feature_set(struct net_device *dev) if (dhd_is_pno_supported(dhd)) { feature_set |= WIFI_FEATURE_PNO; #ifdef GSCAN_SUPPORT + /* terence 20171115: remove to get GTS PASS + * com.google.android.gts.wifi.WifiHostTest#testWifiScannerBatchTimestamp + */ // feature_set |= WIFI_FEATURE_GSCAN; // feature_set |= WIFI_FEATURE_HAL_EPNO; #endif /* GSCAN_SUPPORT */ @@ -15675,6 +15695,7 @@ void dhd_get_customized_country_code(struct net_device *dev, char *country_iso_c BCM_REFERENCE(dhd); } + void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notify) { dhd_info_t *dhd = DHD_DEV_INFO(dev); @@ -19135,6 +19156,7 @@ static void dhd_sysfs_exit(dhd_info_t *dhd) DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__)); return; } + if (&dhd->dhd_kobj != NULL) kobject_put(&dhd->dhd_kobj); } diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_msgbuf.c b/bcmdhd.1.579.77.41.1.cn/dhd_msgbuf.c index e602d24..455f125 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_msgbuf.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_msgbuf.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef DHD_TIMESYNC #include #endif /* DHD_TIMESYNC */ @@ -6013,6 +6014,7 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) int timeleft; unsigned long flags; int ret = 0; + static uint cnt = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -6021,7 +6023,7 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) goto out; } - timeleft = dhd_os_ioctl_resp_wait(dhd, (uint *)&prot->ioctl_received); + timeleft = dhd_os_ioctl_resp_wait(dhd, (uint *)&prot->ioctl_received, false); #ifdef DHD_RECOVER_TIMEOUT if (prot->ioctl_received == 0) { @@ -6053,6 +6055,25 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) } #endif /* DHD_RECOVER_TIMEOUT */ + if (dhd->conf->ctrl_resched > 0 && timeleft == 0 && (!dhd_query_bus_erros(dhd))) { + cnt++; + if (cnt <= dhd->conf->ctrl_resched) { + uint32 intstatus = 0, intmask = 0; + intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); + intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); + if (intstatus) { + DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, intstatus=0x%x, intmask=0x%x\n", + __FUNCTION__, cnt, intstatus, intmask)); + dhd->bus->ipend = TRUE; + dhd->bus->dpc_sched = TRUE; + dhd_sched_dpc(dhd); + timeleft = dhd_os_ioctl_resp_wait(dhd, &prot->ioctl_received, true); + } + } + } else { + cnt = 0; + } + if (timeleft == 0 && (!dhd_query_bus_erros(dhd))) { uint32 intstatus; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_pcie.c b/bcmdhd.1.579.77.41.1.cn/dhd_pcie.c index 77995b5..48e3d19 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_pcie.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_pcie.c @@ -497,7 +497,9 @@ uint32 dhdpcie_bus_intstatus(dhd_bus_t *bus) { uint32 intstatus = 0; +#ifndef DHD_READ_INTSTATUS_IN_DPC uint32 intmask = 0; +#endif /* DHD_READ_INTSTATUS_IN_DPC */ if ((bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) && bus->wait_for_d3_ack) { @@ -521,10 +523,12 @@ dhdpcie_bus_intstatus(dhd_bus_t *bus) /* this is a PCIE core register..not a config register... */ intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); +#ifndef DHD_READ_INTSTATUS_IN_DPC /* this is a PCIE core register..not a config register... */ intmask = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); intstatus &= intmask; +#endif /* DHD_READ_INTSTATUS_IN_DPC */ /* Is device removed. intstatus & intmask read 0xffffffff */ if (intstatus == (uint32)-1) { DHD_ERROR(("%s: Device is removed or Link is down.\n", __FUNCTION__)); @@ -600,6 +604,7 @@ dhdpcie_bus_isr(dhd_bus_t *bus) } } +#ifndef DHD_READ_INTSTATUS_IN_DPC intstatus = dhdpcie_bus_intstatus(bus); /* Check if the interrupt is ours or not */ @@ -627,6 +632,7 @@ dhdpcie_bus_isr(dhd_bus_t *bus) /* Count the interrupt call */ bus->intrcount++; +#endif /* DHD_READ_INTSTATUS_IN_DPC */ bus->ipend = TRUE; @@ -1008,6 +1014,8 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) /* Set the poll and/or interrupt flags */ bus->intr = (bool)dhd_intr; + if ((bus->poll = (bool)dhd_poll)) + bus->pollrate = 1; bus->wait_for_d3_ack = 1; #ifdef PCIE_OOB @@ -1530,6 +1538,14 @@ bool dhd_bus_watchdog(dhd_pub_t *dhd) } } +#ifdef DHD_READ_INTSTATUS_IN_DPC + if (bus->poll) { + bus->ipend = TRUE; + bus->dpc_sched = TRUE; + dhd_sched_dpc(bus->dhd); /* queue DPC now!! */ + } +#endif /* DHD_READ_INTSTATUS_IN_DPC */ + #if defined(PCIE_OOB) || defined(PCIE_INB_DW) /* If haven't communicated with device for a while, deassert the Device_Wake GPIO */ if (dhd_doorbell_timeout != 0 && dhd->busstate == DHD_BUS_DATA && @@ -1639,6 +1655,17 @@ dhd_set_path_params(struct dhd_bus *bus) } +void +dhd_set_bus_params(struct dhd_bus *bus) +{ + if (bus->dhd->conf->dhd_poll >= 0) { + bus->poll = bus->dhd->conf->dhd_poll; + if (!bus->pollrate) + bus->pollrate = 1; + printf("%s: set polling mode %d\n", __FUNCTION__, bus->dhd->conf->dhd_poll); + } +} + static int dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) { @@ -1680,6 +1707,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) DHD_OS_WAKE_LOCK(bus->dhd); dhd_set_path_params(bus); + dhd_set_bus_params(bus); ret = _dhdpcie_download_firmware(bus); @@ -6066,10 +6094,24 @@ dhd_bus_dpc(struct dhd_bus *bus) DHD_BUS_BUSY_SET_IN_DPC(bus->dhd); DHD_GENERAL_UNLOCK(bus->dhd, flags); +#ifdef DHD_READ_INTSTATUS_IN_DPC + if (bus->ipend) { + bus->ipend = FALSE; + bus->intstatus = dhdpcie_bus_intstatus(bus); + /* Check if the interrupt is ours or not */ + if (bus->intstatus == 0) { + goto INTR_ON; + } + bus->intrcount++; + } +#endif /* DHD_READ_INTSTATUS_IN_DPC */ resched = dhdpcie_bus_process_mailbox_intr(bus, bus->intstatus); if (!resched) { bus->intstatus = 0; +#ifdef DHD_READ_INTSTATUS_IN_DPC +INTR_ON: +#endif /* DHD_READ_INTSTATUS_IN_DPC */ bus->dpc_intr_enable_count++; dhdpcie_bus_intr_enable(bus); /* Enable back interrupt using Intmask!! */ } diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_pcie.h b/bcmdhd.1.579.77.41.1.cn/dhd_pcie.h index eb8de62..92b07c6 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_pcie.h +++ b/bcmdhd.1.579.77.41.1.cn/dhd_pcie.h @@ -259,6 +259,7 @@ typedef struct dhd_bus { struct pktq txq; /* Queue length used for flow-control */ bool intr; /* Use interrupts */ + bool poll; /* Use polling */ bool ipend; /* Device interrupt is pending */ bool intdis; /* Interrupts disabled by isr */ uint intrcount; /* Count of device interrupt callbacks */ diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_pcie_linux.c b/bcmdhd.1.579.77.41.1.cn/dhd_pcie_linux.c index 51664a7..5c9561a 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_pcie_linux.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_pcie_linux.c @@ -1029,10 +1029,22 @@ dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info) if (!bus->irq_registered) { snprintf(dhdpcie_info->pciname, sizeof(dhdpcie_info->pciname), "dhdpcie:%s", pci_name(pdev)); +#ifdef DHD_USE_MSI + printf("%s: MSI enabled\n", __FUNCTION__); + err = pci_enable_msi(pdev); + if (err < 0) { + DHD_ERROR(("%s: pci_enable_msi() failed, %d, fall back to INTx\n", __FUNCTION__, err)); + } +#else + printf("%s: MSI not enabled\n", __FUNCTION__); +#endif /* DHD_USE_MSI */ err = request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED, dhdpcie_info->pciname, bus); if (err) { DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__)); +#ifdef DHD_USE_MSI + pci_disable_msi(pdev); +#endif /* DHD_USE_MSI */ return -1; } else { bus->irq_registered = TRUE; @@ -1497,6 +1509,9 @@ dhdpcie_free_irq(dhd_bus_t *bus) if (bus->irq_registered) { free_irq(pdev->irq, bus); bus->irq_registered = FALSE; +#ifdef DHD_USE_MSI + pci_disable_msi(pdev); +#endif /* DHD_USE_MSI */ } else { DHD_ERROR(("%s: PCIe IRQ is not registered\n", __FUNCTION__)); } diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_pno.c b/bcmdhd.1.579.77.41.1.cn/dhd_pno.c index c553733..c20ed7b 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_pno.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_pno.c @@ -910,6 +910,7 @@ exit: bytes_written = (int32)(bp - buf); return bytes_written; } + static int _dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool only_last) { @@ -992,6 +993,7 @@ _dhd_pno_cfg(dhd_pub_t *dhd, uint16 *channel_list, int nchan) exit: return err; } + static int _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mode_t mode) { @@ -1084,6 +1086,7 @@ _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mod mutex_unlock(&_pno_state->pno_mutex); return err; } + static int _dhd_pno_add_bssid(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, int nbssid) { @@ -4007,6 +4010,7 @@ exit: kfree(buf); return err; } + int dhd_pno_deinit(dhd_pub_t *dhd) { int err = BCME_OK; diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c b/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c index 1dcdd28..fe2e874 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_sdio.c @@ -696,7 +696,7 @@ static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txs int prev_chain_total_len, bool last_chained_pkt, int *pad_pkt_len, void **new_pkt #if defined(BCMSDIOH_TXGLOM_EXT) - , int frist_frame + , int first_frame #endif ); static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt); @@ -1040,7 +1040,7 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) uint8 wr_val = 0, rd_val, cmp_val, bmask; int err = 0; int try_cnt = 0; - return 0; + KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"))); wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); @@ -2910,6 +2910,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) { int timeleft; uint rxlen = 0; + static uint cnt = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -2917,7 +2918,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) return -EIO; /* Wait until control frame is available */ - timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen); + timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, false); dhd_os_sdlock(bus->dhd); rxlen = bus->rxlen; @@ -2925,6 +2926,32 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) bus->rxlen = 0; dhd_os_sdunlock(bus->dhd); + if (bus->dhd->conf->ctrl_resched > 0 && !rxlen && timeleft == 0) { + cnt++; + if (cnt <= bus->dhd->conf->ctrl_resched) { + uint32 status, retry = 0; + R_SDREG(status, &bus->regs->intstatus, retry); + if ((status & I_HMB_HOST_INT) || PKT_AVAILABLE(bus, status)) { + DHD_ERROR(("%s: reschedule dhd_dpc, cnt=%d, status=0x%x\n", + __FUNCTION__, cnt, status)); + bus->ipend = TRUE; + bus->dpc_sched = TRUE; + dhd_sched_dpc(bus->dhd); + + /* Wait until control frame is available */ + timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, true); + + dhd_os_sdlock(bus->dhd); + rxlen = bus->rxlen; + bcopy(bus->rxctl, msg, MIN(msglen, rxlen)); + bus->rxlen = 0; + dhd_os_sdunlock(bus->dhd); + } + } + } else { + cnt = 0; + } + if (rxlen) { DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", __FUNCTION__, rxlen, msglen)); diff --git a/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c b/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c index 50573e4..33997cd 100644 --- a/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c +++ b/bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c @@ -73,7 +73,7 @@ enum dhd_prealloc_index { #define DHD_PREALLOC_OSL_BUF_SIZE (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) #define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024) #define DHD_PREALLOC_DHD_INFO_SIZE (30 * 1024) -#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (770 * 1024) +#define DHD_PREALLOC_MEMDUMP_RAM_SIZE (810 * 1024) #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE (73 * 1024) #define DHD_PREALLOC_WL_ESCAN_INFO_SIZE (66 * 1024) #ifdef CONFIG_64BIT diff --git a/bcmdhd.1.579.77.41.1.cn/include/epivers.h b/bcmdhd.1.579.77.41.1.cn/include/epivers.h index 4cf4c70..a2dc35e 100644 --- a/bcmdhd.1.579.77.41.1.cn/include/epivers.h +++ b/bcmdhd.1.579.77.41.1.cn/include/epivers.h @@ -46,6 +46,6 @@ #define EPI_VERSION_DEV 1.579.77.41 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "1.579.77.41.2 (r)" +#define EPI_VERSION_STR "1.579.77.41.3 (r)" #endif /* _epivers_h_ */ diff --git a/bcmdhd.1.579.77.41.1.cn/include/wlioctl.h b/bcmdhd.1.579.77.41.1.cn/include/wlioctl.h index 82c4b4f..1e6a3a2 100644 --- a/bcmdhd.1.579.77.41.1.cn/include/wlioctl.h +++ b/bcmdhd.1.579.77.41.1.cn/include/wlioctl.h @@ -11554,13 +11554,6 @@ typedef struct wl_interface_create { struct ether_addr mac_addr; /* Optional Mac address */ } wl_interface_create_t; -typedef struct wl_interface_create_v0 { - uint16 ver; /* version of this struct */ - struct ether_addr mac_addr; /* MAC address of the interface */ - char ifname[BCM_MSG_IFNAME_MAX]; /* name of interface */ - uint8 bsscfgidx; /* source bsscfg index */ -} wl_interface_info_t; - typedef struct wl_interface_create_v1 { uint16 ver; /**< version of this struct */ uint8 pad1[2]; /**< Padding bytes */ diff --git a/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c b/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c index 507edc1..6265338 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_android_ext.c @@ -1,150 +1,150 @@ - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define htod32(i) i -#define htod16(i) i -#define dtoh32(i) i -#define dtoh16(i) i -#define htodchanspec(i) i -#define dtohchanspec(i) i -#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) - -#define CMD_CHANNEL "CHANNEL" -#define CMD_CHANNELS "CHANNELS" -#define CMD_ROAM_TRIGGER "ROAM_TRIGGER" -#define CMD_KEEP_ALIVE "KEEP_ALIVE" -#define CMD_PM "PM" -#define CMD_MONITOR "MONITOR" -#define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM" - -#ifdef WL_EXT_IAPSTA -#define CMD_IAPSTA_INIT "IAPSTA_INIT" -#define CMD_IAPSTA_CONFIG "IAPSTA_CONFIG" -#define CMD_IAPSTA_ENABLE "IAPSTA_ENABLE" -#define CMD_IAPSTA_DISABLE "IAPSTA_DISABLE" -#ifdef PROP_TXSTATUS -#ifdef PROP_TXSTATUS_VSDB -#include + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define htod32(i) i +#define htod16(i) i +#define dtoh32(i) i +#define dtoh16(i) i +#define htodchanspec(i) i +#define dtohchanspec(i) i +#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) + +#define CMD_CHANNEL "CHANNEL" +#define CMD_CHANNELS "CHANNELS" +#define CMD_ROAM_TRIGGER "ROAM_TRIGGER" +#define CMD_KEEP_ALIVE "KEEP_ALIVE" +#define CMD_PM "PM" +#define CMD_MONITOR "MONITOR" +#define CMD_SET_SUSPEND_BCN_LI_DTIM "SET_SUSPEND_BCN_LI_DTIM" + +#ifdef WL_EXT_IAPSTA +#define CMD_IAPSTA_INIT "IAPSTA_INIT" +#define CMD_IAPSTA_CONFIG "IAPSTA_CONFIG" +#define CMD_IAPSTA_ENABLE "IAPSTA_ENABLE" +#define CMD_IAPSTA_DISABLE "IAPSTA_DISABLE" +#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB +#include extern int disable_proptx; -#endif /* PROP_TXSTATUS_VSDB */ -#endif -#endif -#ifdef IDHCP -#define CMD_DHCPC_ENABLE "DHCPC_ENABLE" -#define CMD_DHCPC_DUMP "DHCPC_DUMP" -#endif -#define CMD_WL "WL" - -#define IEEE80211_BAND_2GHZ 0 -#define IEEE80211_BAND_5GHZ 1 - -int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) -{ - int ret; - - ret = wldev_ioctl(dev, cmd, arg, len, set); - if (ret) - ANDROID_ERROR(("%s: cmd=%d ret=%d\n", __FUNCTION__, cmd, ret)); - return ret; -} - -int wl_ext_iovar_getint(struct net_device *dev, s8 *iovar, s32 *val) -{ - int ret; - - ret = wldev_iovar_getint(dev, iovar, val); - if (ret) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); - - return ret; -} - -int wl_ext_iovar_setint(struct net_device *dev, s8 *iovar, s32 val) -{ - int ret; - - ret = wldev_iovar_setint(dev, iovar, val); - if (ret) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); - - return ret; -} - -int wl_ext_iovar_getbuf(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_getbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); - if (ret != 0) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - -int wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) -{ - int ret; - - ret = wldev_iovar_setbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); - if (ret != 0) - ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); - - return ret; -} - -#ifdef WL_EXT_IAPSTA -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) -{ - int ret; - - ret = wldev_iovar_setbuf_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; -} - -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 +#endif /* PROP_TXSTATUS_VSDB */ +#endif +#endif +#ifdef IDHCP +#define CMD_DHCPC_ENABLE "DHCPC_ENABLE" +#define CMD_DHCPC_DUMP "DHCPC_DUMP" +#endif +#define CMD_WL "WL" + +#define IEEE80211_BAND_2GHZ 0 +#define IEEE80211_BAND_5GHZ 1 + +int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set) +{ + int ret; + + ret = wldev_ioctl(dev, cmd, arg, len, set); + if (ret) + ANDROID_ERROR(("%s: cmd=%d ret=%d\n", __FUNCTION__, cmd, ret)); + return ret; +} + +int wl_ext_iovar_getint(struct net_device *dev, s8 *iovar, s32 *val) +{ + int ret; + + ret = wldev_iovar_getint(dev, iovar, val); + if (ret) + ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); + + return ret; +} + +int wl_ext_iovar_setint(struct net_device *dev, s8 *iovar, s32 val) +{ + int ret; + + ret = wldev_iovar_setint(dev, iovar, val); + if (ret) + ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar, ret)); + + return ret; +} + +int wl_ext_iovar_getbuf(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_getbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); + if (ret != 0) + ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); + + return ret; +} + +int wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name, + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync) +{ + int ret; + + ret = wldev_iovar_setbuf(dev, iovar_name, param, paramlen, buf, buflen, buf_sync); + if (ret != 0) + ANDROID_ERROR(("%s: iovar=%s, ret=%d\n", __FUNCTION__, iovar_name, ret)); + + return ret; +} + +#ifdef WL_EXT_IAPSTA +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) +{ + int ret; + + ret = wldev_iovar_setbuf_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; +} + +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 * Returns INVCHANSPEC on error */ static chanspec_t -wl_ext_chspec_to_legacy(chanspec_t chspec) +wl_ext_chspec_to_legacy(chanspec_t chspec) { chanspec_t lchspec; if (wf_chspec_malformed(chspec)) { - ANDROID_ERROR(("wl_ext_chspec_to_legacy: input chanspec (0x%04X) malformed\n", + ANDROID_ERROR(("wl_ext_chspec_to_legacy: input chanspec (0x%04X) malformed\n", chspec)); return INVCHANSPEC; } @@ -173,25 +173,25 @@ wl_ext_chspec_to_legacy(chanspec_t chspec) } else { /* cannot express the bandwidth */ char chanbuf[CHANSPEC_STR_LEN]; - ANDROID_ERROR(( - "wl_ext_chspec_to_legacy: unable to convert chanspec %s (0x%04X) " + ANDROID_ERROR(( + "wl_ext_chspec_to_legacy: unable to convert chanspec %s (0x%04X) " "to pre-11ac format\n", wf_chspec_ntoa(chspec, chanbuf), chspec)); return INVCHANSPEC; } return lchspec; -} +} /* given a chanspec value, do the endian and chanspec version conversion to * a chanspec_t value * Returns INVCHANSPEC on error */ static chanspec_t -wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) +wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) { - if (ioctl_ver == 1) { - chanspec = wl_ext_chspec_to_legacy(chanspec); + if (ioctl_ver == 1) { + chanspec = wl_ext_chspec_to_legacy(chanspec); if (chanspec == INVCHANSPEC) { return chanspec; } @@ -199,99 +199,99 @@ wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec) chanspec = htodchanspec(chanspec); return chanspec; -} - -static int -wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) -{ - int ret = 0; - s32 val = 0; - - val = 1; - ret = wl_ext_ioctl(dev, WLC_GET_VERSION, &val, sizeof(val), 0); - if (ret) { - ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", ret)); - return ret; - } - val = dtoh32(val); - if (val != WLC_IOCTL_VERSION && val != 1) { - ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", - val, WLC_IOCTL_VERSION)); - return BCME_VERSION; - } - *ioctl_ver = val; - - return ret; -} - -static int -wl_ext_set_chanspec(struct net_device *dev, uint16 channel) -{ - s32 _chan = channel; +} + +static int +wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver) +{ + int ret = 0; + s32 val = 0; + + val = 1; + ret = wl_ext_ioctl(dev, WLC_GET_VERSION, &val, sizeof(val), 0); + if (ret) { + ANDROID_ERROR(("WLC_GET_VERSION failed, err=%d\n", ret)); + return ret; + } + val = dtoh32(val); + if (val != WLC_IOCTL_VERSION && val != 1) { + ANDROID_ERROR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n", + val, WLC_IOCTL_VERSION)); + return BCME_VERSION; + } + *ioctl_ver = val; + + return ret; +} + +static int +wl_ext_set_chanspec(struct net_device *dev, uint16 channel) +{ + s32 _chan = channel; chanspec_t chspec = 0; - chanspec_t fw_chspec = 0; - u32 bw = WL_CHANSPEC_BW_20; + 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]; + s32 bw_cap = 0; + s8 iovar_buf[WLC_IOCTL_SMLEN]; struct { u32 band; 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 = {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; err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), - iovar_buf, WLC_IOCTL_SMLEN, NULL); + iovar_buf, WLC_IOCTL_SMLEN, NULL); if (err) { if (err != BCME_UNSUPPORTED) { - ANDROID_ERROR(("bw_cap failed, %d\n", err)); + 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)); + 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])) + if (WL_BW_CAP_80MHZ(iovar_buf[0])) bw = WL_CHANSPEC_BW_80; - else if (WL_BW_CAP_40MHZ(iovar_buf[0])) + 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; - + } + } + 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(ioctl_ver, chspec); + fw_chspec = wl_ext_chspec_host_to_driver(ioctl_ver, chspec); if (fw_chspec != INVCHANSPEC) { - if ((err = wldev_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) { + if ((err = wldev_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) { if (bw == WL_CHANSPEC_BW_80) - goto change_bw; - wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1); - printf("%s: channel %d\n", __FUNCTION__, _chan); + goto change_bw; + 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)); - } else - printf("%s: channel %d, 0x%x\n", __FUNCTION__, channel, chspec); + ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err)); + } else + printf("%s: channel %d, 0x%x\n", __FUNCTION__, 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 { @@ -304,1875 +304,1973 @@ change_bw: bw = 0; if (bw) goto set_channel; - ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec)); + ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec)); err = BCME_ERROR; - } - - return err; -} - -int -wl_ext_channel(struct net_device *dev, char* command, int total_len) -{ - int ret; - int channel=0; - channel_info_t ci; - int bytes_written = 0; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - sscanf(command, "%*s %d", &channel); - - if (channel > 0) { - ret = wl_ext_set_chanspec(dev, channel); - } else { - 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); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - - return ret; -} - -int -wl_ext_channels(struct net_device *dev, char* command, int total_len) -{ - int ret, i; - int bytes_written = -1; - u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; - wl_uint32_list_t *list; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - 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); - 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])); - printf("%d ", dtoh32(list->element[i])); - } - printf("\n"); - ret = bytes_written; - } - - return ret; -} - -int -wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) -{ - int ret = 0; - int roam_trigger[2] = {0, 0}; - int trigger[2]= {0, 0}; - int bytes_written=-1; - - sscanf(command, "%*s %10d", &roam_trigger[0]); - - if (roam_trigger[0]) { - roam_trigger[1] = WLC_BAND_ALL; - 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)); - } else { - roam_trigger[1] = WLC_BAND_2G; - 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)); - - roam_trigger[1] = WLC_BAND_5G; - 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_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1])); - bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]); - ret = bytes_written; - } - - return ret; -} - -static int -wl_ext_pattern_atoh(char *src, char *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && - strncmp(src, "0X", 2) != 0) { - ANDROID_ERROR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - DHD_ERROR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - bcm_strncpy_s(num, sizeof(num), src, 2); - num[2] = '\0'; - dst[i] = (uint8)strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -int -wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) -{ - wl_mkeep_alive_pkt_t *mkeep_alive_pktp; - int ret = -1, i; - int id, period=-1, len_bytes=0, buf_len=0; - char data[200]="\0"; - char buf[WLC_IOCTL_SMLEN]="\0", iovar_buf[WLC_IOCTL_SMLEN]="\0"; - int bytes_written = -1; - - ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, command)); - sscanf(command, "%*s %d %d %s", &id, &period, data); - ANDROID_TRACE(("%s: id=%d, period=%d, data=%s\n", __FUNCTION__, id, period, data)); - - if (period >= 0) { - mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *)buf; - mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION); - mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); - mkeep_alive_pktp->keep_alive_id = id; - buf_len += WL_MKEEP_ALIVE_FIXED_LEN; - mkeep_alive_pktp->period_msec = period; - if (strlen(data)) { - len_bytes = wl_ext_pattern_atoh(data, (char *) mkeep_alive_pktp->data); - buf_len += len_bytes; - } - mkeep_alive_pktp->len_bytes = htod16(len_bytes); - - ret = wl_ext_iovar_setbuf(dev, "mkeep_alive", buf, buf_len, - iovar_buf, sizeof(iovar_buf), NULL); - } else { - if (id < 0) - id = 0; - ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL); - if (ret) { - goto exit; - } else { - mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; - printf("Id :%d\n" - "Period (msec) :%d\n" - "Length :%d\n" - "Packet :0x", - mkeep_alive_pktp->keep_alive_id, - dtoh32(mkeep_alive_pktp->period_msec), - dtoh16(mkeep_alive_pktp->len_bytes)); - for (i=0; ilen_bytes; i++) { - printf("%02x", mkeep_alive_pktp->data[i]); - } - printf("\n"); - } - 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; ilen_bytes; 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; - } - -exit: - return ret; -} - -int -wl_ext_pm(struct net_device *dev, char *command, int total_len) -{ - int pm=-1, ret = -1; - char *pm_local; - int bytes_written=-1; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - sscanf(command, "%*s %d", &pm); - - if (pm >= 0) { - ret = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE); - if (ret) - ANDROID_ERROR(("WLC_SET_PM ERROR %d ret=%d\n", pm, ret)); - } else { - ret = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), FALSE); - if (!ret) { - ANDROID_TRACE(("%s: PM = %d\n", __func__, pm)); - if (pm == PM_OFF) - pm_local = "PM_OFF"; - else if(pm == PM_MAX) - pm_local = "PM_MAX"; - else if(pm == PM_FAST) - pm_local = "PM_FAST"; - else { - pm = 0; - pm_local = "Invalid"; - } - bytes_written = snprintf(command, total_len, "PM %s", pm_local); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - - return ret; -} - -static int -wl_ext_monitor(struct net_device *dev, char *command, int total_len) -{ - int val, ret = -1; - int bytes_written=-1; - - sscanf(command, "%*s %d", &val); - - if (val >=0) { - ret = wldev_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(int), 1); - if (ret) - ANDROID_ERROR(("WLC_SET_MONITOR ERROR %d ret=%d\n", val, ret)); - } else { - ret = wldev_ioctl(dev, WLC_GET_MONITOR, &val, sizeof(val), FALSE); - if (!ret) { - ANDROID_TRACE(("%s: monitor = %d\n", __FUNCTION__, val)); - bytes_written = snprintf(command, total_len, "monitor %d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - - return ret; -} - -#ifdef WL_EXT_IAPSTA -struct wl_apsta_params g_apsta_params; -static int -wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) -{ - char hex[] = "XX"; - unsigned char *data = wsec_key->data; - char *keystr = key; - - switch (strlen(keystr)) { - case 5: - case 13: - case 16: - wsec_key->len = strlen(keystr); - memcpy(data, keystr, wsec_key->len + 1); - break; - case 12: - case 28: - case 34: - case 66: - /* strip leading 0x */ - if (!strnicmp(keystr, "0x", 2)) - keystr += 2; - else - return -1; - /* fall through */ - case 10: - case 26: - case 32: - case 64: - wsec_key->len = strlen(keystr) / 2; - while (*keystr) { - strncpy(hex, keystr, 2); - *data++ = (char) strtoul(hex, NULL, 16); - keystr += 2; - } - break; - default: - return -1; - } - - switch (wsec_key->len) { - case 5: - wsec_key->algo = CRYPTO_ALGO_WEP1; - break; - case 13: - wsec_key->algo = CRYPTO_ALGO_WEP128; - break; - case 16: - /* default to AES-CCM */ - wsec_key->algo = CRYPTO_ALGO_AES_CCM; - break; - case 32: - wsec_key->algo = CRYPTO_ALGO_TKIP; - break; - default: - return -1; - } - - /* Set as primary wsec_key by default */ - wsec_key->flags |= WL_PRIMARY_KEY; - - return 0; -} - -static int -wl_ext_set_bgnmode(struct wl_if_info *cur_if) -{ - struct net_device *dev = cur_if->dev; - bgnmode_t bgnmode = cur_if->bgnmode; - int val; - - if (bgnmode == 0) - return 0; - - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - if (bgnmode == IEEE80211B) { - wl_ext_iovar_setint(dev, "nmode", 0); - val = 0; - wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: B only\n", __FUNCTION__)); - } else if (bgnmode == IEEE80211G) { - wl_ext_iovar_setint(dev, "nmode", 0); - val = 2; - wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: G only\n", __FUNCTION__)); - } else if (bgnmode == IEEE80211BG) { - wl_ext_iovar_setint(dev, "nmode", 0); - val = 1; - wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: : B/G mixed\n", __FUNCTION__)); - } else if (bgnmode == IEEE80211BGN) { - wl_ext_iovar_setint(dev, "nmode", 0); - wl_ext_iovar_setint(dev, "nmode", 1); - wl_ext_iovar_setint(dev, "vhtmode", 0); - val = 1; - wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: : B/G/N mixed\n", __FUNCTION__)); - } else if (bgnmode == IEEE80211BGNAC) { - wl_ext_iovar_setint(dev, "nmode", 0); - wl_ext_iovar_setint(dev, "nmode", 1); - wl_ext_iovar_setint(dev, "vhtmode", 1); - val = 1; - wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); - ANDROID_TRACE(("%s: Network mode: : B/G/N/AC mixed\n", __FUNCTION__)); - } - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - - return 0; -} - -static int -wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params) -{ - struct net_device *dev = cur_if->dev; - authmode_t amode = cur_if->amode; - int auth=0, wpa_auth=0; - - if (amode == AUTH_OPEN) { - auth = 0; - wpa_auth = 0; - ANDROID_TRACE(("%s: Authentication: Open System\n", __FUNCTION__)); - } else if (amode == AUTH_SHARED) { - auth = 1; - wpa_auth = 0; - ANDROID_TRACE(("%s: Authentication: Shared Key\n", __FUNCTION__)); - } else if (amode == AUTH_WPAPSK) { - auth = 0; - wpa_auth = 4; - ANDROID_TRACE(("%s: Authentication: WPA-PSK\n", __FUNCTION__)); - } else if (amode == AUTH_WPA2PSK) { - auth = 0; - wpa_auth = 128; - ANDROID_TRACE(("%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__)); - } - wl_ext_iovar_setint(dev, "auth", auth); - - wl_ext_iovar_setint(dev, "wpa_auth", wpa_auth); - - return 0; -} - -static int -wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params) -{ - struct net_device *dev = cur_if->dev; - int wsec=0; - struct wl_wsec_key wsec_key; - wsec_pmk_t psk; - encmode_t emode = cur_if->emode; - char *key = cur_if->key; - - memset(&wsec_key, 0, sizeof(wsec_key)); - memset(&psk, 0, sizeof(psk)); - if (emode == ENC_NONE) { - wsec = 0; - ANDROID_TRACE(("%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)); - } 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) { - 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)); - } 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)); - } - - wl_ext_iovar_setint(dev, "wsec", wsec); - - if (wsec == 1) { - wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1); - } else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) { - if (dev) { - if (cur_if->ifmode == ISTA_MODE) - wl_ext_iovar_setint(dev, "sup_wpa", 1); - wl_ext_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk), 1); - } else { - ANDROID_ERROR(("%s: apdev is null\n", __FUNCTION__)); - } - } - - return 0; -} - -static int -wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len) -{ - s32 val = 0; - char *pch, *pick_tmp, *param; - wlc_ssid_t ssid = { 0, {0} }; - s8 iovar_buf[WLC_IOCTL_SMLEN]; - struct wl_apsta_params *apsta_params = &g_apsta_params; - wl_interface_create_t iface; - struct dhd_pub *dhd; - wl_p2p_if_t ifreq; - - if (apsta_params->init) { - ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__)); - return -1; - } - - dhd = dhd_get_pub(dev); - memset(apsta_params, 0, sizeof(struct wl_apsta_params)); - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - - pick_tmp = command; - param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init - param = bcmstrtok(&pick_tmp, " ", 0); - while (param != NULL) { - if (!strcmp(param, "mode")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "sta")) { - apsta_params->apstamode = ISTAONLY_MODE; - } else if (!strcmp(pch, "ap")) { - apsta_params->apstamode = IAPONLY_MODE; - } else if (!strcmp(pch, "apsta")) { - apsta_params->apstamode = IAPSTA_MODE; - } else if (!strcmp(pch, "dualap")) { - apsta_params->apstamode = IDUALAP_MODE; - } else if (!strcmp(pch, "gosta")) { - if (!FW_SUPPORTED(dhd, p2p)) { - return -1; - } - apsta_params->apstamode = IGOSTA_MODE; - } else if (!strcmp(pch, "gcsta")) { - if (!FW_SUPPORTED(dhd, p2p)) { - return -1; - } - apsta_params->apstamode = IGCSTA_MODE; - } else { - ANDROID_ERROR(("%s: mode [sta|ap|apsta|dualap]\n", __FUNCTION__)); - return -1; - } - } - } else if (!strcmp(param, "vifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(apsta_params->vif.ifname, pch); - else { - ANDROID_ERROR(("%s: vifname [wlan1]\n", __FUNCTION__)); - return -1; - } - } - param = bcmstrtok(&pick_tmp, " ", 0); - } - - if (apsta_params->apstamode == 0) { - ANDROID_ERROR(("%s: mode [sta|ap|apsta|dualap]\n", __FUNCTION__)); - return -1; - } - - apsta_params->pif.dev = dev; - apsta_params->pif.bssidx = 0; - strcpy(apsta_params->pif.ifname, dev->name); - strcpy(apsta_params->pif.ssid, "tttp"); - apsta_params->pif.maxassoc = -1; - apsta_params->pif.channel = 1; - - if (!strlen(apsta_params->vif.ifname)) - strcpy(apsta_params->vif.ifname, "wlan1"); - strcpy(apsta_params->vif.ssid, "tttv"); - apsta_params->vif.maxassoc = -1; - apsta_params->vif.channel = 1; - - if (apsta_params->apstamode == ISTAONLY_MODE) { - apsta_params->pif.ifmode = ISTA_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - 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) { - apsta_params->pif.ifmode = IAP_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); + } + + return err; +} + +int +wl_ext_channel(struct net_device *dev, char* command, int total_len) +{ + int ret; + int channel=0; + channel_info_t ci; + int bytes_written = 0; + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + + sscanf(command, "%*s %d", &channel); + + if (channel > 0) { + ret = wl_ext_set_chanspec(dev, channel); + } else { + 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); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + + return ret; +} + +int +wl_ext_channels(struct net_device *dev, char* command, int total_len) +{ + int ret, i; + int bytes_written = -1; + u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)]; + wl_uint32_list_t *list; + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + + 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); + 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])); + printf("%d ", dtoh32(list->element[i])); + } + printf("\n"); + ret = bytes_written; + } + + return ret; +} + +int +wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len) +{ + int ret = 0; + int roam_trigger[2] = {0, 0}; + int trigger[2]= {0, 0}; + int bytes_written=-1; + + sscanf(command, "%*s %10d", &roam_trigger[0]); + + if (roam_trigger[0]) { + roam_trigger[1] = WLC_BAND_ALL; + 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)); + } else { + roam_trigger[1] = WLC_BAND_2G; + 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)); + + roam_trigger[1] = WLC_BAND_5G; + 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_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1])); + bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]); + ret = bytes_written; + } + + return ret; +} + +static int +wl_ext_pattern_atoh(char *src, char *dst) +{ + int i; + if (strncmp(src, "0x", 2) != 0 && + strncmp(src, "0X", 2) != 0) { + ANDROID_ERROR(("Mask invalid format. Needs to start with 0x\n")); + return -1; + } + src = src + 2; /* Skip past 0x */ + if (strlen(src) % 2 != 0) { + DHD_ERROR(("Mask invalid format. Needs to be of even length\n")); + return -1; + } + for (i = 0; *src != '\0'; i++) { + char num[3]; + bcm_strncpy_s(num, sizeof(num), src, 2); + num[2] = '\0'; + dst[i] = (uint8)strtoul(num, NULL, 16); + src += 2; + } + return i; +} + +int +wl_ext_keep_alive(struct net_device *dev, char *command, int total_len) +{ + wl_mkeep_alive_pkt_t *mkeep_alive_pktp; + int ret = -1, i; + int id, period=-1, len_bytes=0, buf_len=0; + char data[200]="\0"; + char buf[WLC_IOCTL_SMLEN]="\0", iovar_buf[WLC_IOCTL_SMLEN]="\0"; + int bytes_written = -1; + + ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, command)); + sscanf(command, "%*s %d %d %s", &id, &period, data); + ANDROID_TRACE(("%s: id=%d, period=%d, data=%s\n", __FUNCTION__, id, period, data)); + + if (period >= 0) { + mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *)buf; + mkeep_alive_pktp->version = htod16(WL_MKEEP_ALIVE_VERSION); + mkeep_alive_pktp->length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); + mkeep_alive_pktp->keep_alive_id = id; + buf_len += WL_MKEEP_ALIVE_FIXED_LEN; + mkeep_alive_pktp->period_msec = period; + if (strlen(data)) { + len_bytes = wl_ext_pattern_atoh(data, (char *) mkeep_alive_pktp->data); + buf_len += len_bytes; + } + mkeep_alive_pktp->len_bytes = htod16(len_bytes); + + ret = wl_ext_iovar_setbuf(dev, "mkeep_alive", buf, buf_len, + iovar_buf, sizeof(iovar_buf), NULL); + } else { + if (id < 0) + id = 0; + ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL); + if (ret) { + goto exit; + } else { + mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf; + printf("Id :%d\n" + "Period (msec) :%d\n" + "Length :%d\n" + "Packet :0x", + mkeep_alive_pktp->keep_alive_id, + dtoh32(mkeep_alive_pktp->period_msec), + dtoh16(mkeep_alive_pktp->len_bytes)); + for (i=0; ilen_bytes; i++) { + printf("%02x", mkeep_alive_pktp->data[i]); + } + printf("\n"); + } + 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; ilen_bytes; 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; + } + +exit: + return ret; +} + +int +wl_ext_pm(struct net_device *dev, char *command, int total_len) +{ + int pm=-1, ret = -1; + char *pm_local; + int bytes_written=-1; + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + + sscanf(command, "%*s %d", &pm); + + if (pm >= 0) { + ret = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE); + if (ret) + ANDROID_ERROR(("WLC_SET_PM ERROR %d ret=%d\n", pm, ret)); + } else { + ret = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), FALSE); + if (!ret) { + ANDROID_TRACE(("%s: PM = %d\n", __func__, pm)); + if (pm == PM_OFF) + pm_local = "PM_OFF"; + else if(pm == PM_MAX) + pm_local = "PM_MAX"; + else if(pm == PM_FAST) + pm_local = "PM_FAST"; + else { + pm = 0; + pm_local = "Invalid"; + } + bytes_written = snprintf(command, total_len, "PM %s", pm_local); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + + return ret; +} + +static int +wl_ext_monitor(struct net_device *dev, char *command, int total_len) +{ + int val, ret = -1; + int bytes_written=-1; + + sscanf(command, "%*s %d", &val); + + if (val >=0) { + ret = wldev_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(int), 1); + if (ret) + ANDROID_ERROR(("WLC_SET_MONITOR ERROR %d ret=%d\n", val, ret)); + } else { + ret = wldev_ioctl(dev, WLC_GET_MONITOR, &val, sizeof(val), FALSE); + if (!ret) { + ANDROID_TRACE(("%s: monitor = %d\n", __FUNCTION__, val)); + bytes_written = snprintf(command, total_len, "monitor %d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + + return ret; +} + +#ifdef WL_EXT_IAPSTA +struct wl_apsta_params g_apsta_params; +static int +wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key) +{ + char hex[] = "XX"; + unsigned char *data = wsec_key->data; + char *keystr = key; + + switch (strlen(keystr)) { + case 5: + case 13: + case 16: + wsec_key->len = strlen(keystr); + memcpy(data, keystr, wsec_key->len + 1); + break; + case 12: + case 28: + case 34: + case 66: + /* strip leading 0x */ + if (!strnicmp(keystr, "0x", 2)) + keystr += 2; + else + return -1; + /* fall through */ + case 10: + case 26: + case 32: + case 64: + wsec_key->len = strlen(keystr) / 2; + while (*keystr) { + strncpy(hex, keystr, 2); + *data++ = (char) strtoul(hex, NULL, 16); + keystr += 2; + } + break; + default: + return -1; + } + + switch (wsec_key->len) { + case 5: + wsec_key->algo = CRYPTO_ALGO_WEP1; + break; + case 13: + wsec_key->algo = CRYPTO_ALGO_WEP128; + break; + case 16: + /* default to AES-CCM */ + wsec_key->algo = CRYPTO_ALGO_AES_CCM; + break; + case 32: + wsec_key->algo = CRYPTO_ALGO_TKIP; + break; + default: + return -1; + } + + /* Set as primary wsec_key by default */ + wsec_key->flags |= WL_PRIMARY_KEY; + + return 0; +} + +static int +wl_ext_set_bgnmode(struct wl_if_info *cur_if) +{ + struct net_device *dev = cur_if->dev; + bgnmode_t bgnmode = cur_if->bgnmode; + int val; + + if (bgnmode == 0) + return 0; + + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); + if (bgnmode == IEEE80211B) { + wl_ext_iovar_setint(dev, "nmode", 0); + val = 0; + wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); + ANDROID_TRACE(("%s: Network mode: B only\n", __FUNCTION__)); + } else if (bgnmode == IEEE80211G) { + wl_ext_iovar_setint(dev, "nmode", 0); + val = 2; + wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); + ANDROID_TRACE(("%s: Network mode: G only\n", __FUNCTION__)); + } else if (bgnmode == IEEE80211BG) { + wl_ext_iovar_setint(dev, "nmode", 0); + val = 1; + wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); + ANDROID_TRACE(("%s: Network mode: B/G mixed\n", __FUNCTION__)); + } else if (bgnmode == IEEE80211BGN) { + wl_ext_iovar_setint(dev, "nmode", 0); + wl_ext_iovar_setint(dev, "nmode", 1); + wl_ext_iovar_setint(dev, "vhtmode", 0); + val = 1; + wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); + ANDROID_TRACE(("%s: Network mode: B/G/N mixed\n", __FUNCTION__)); + } else if (bgnmode == IEEE80211BGNAC) { + wl_ext_iovar_setint(dev, "nmode", 0); + wl_ext_iovar_setint(dev, "nmode", 1); + wl_ext_iovar_setint(dev, "vhtmode", 1); + val = 1; + wl_ext_ioctl(dev, WLC_SET_GMODE, &val, sizeof(val), 1); + ANDROID_TRACE(("%s: Network mode: B/G/N/AC mixed\n", __FUNCTION__)); + } + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + + return 0; +} + +static int +wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params) +{ + struct net_device *dev = cur_if->dev; + authmode_t amode = cur_if->amode; + int auth=0, wpa_auth=0; + + if (amode == AUTH_OPEN) { + auth = 0; + wpa_auth = 0; + ANDROID_TRACE(("%s: Authentication: Open System\n", __FUNCTION__)); + } else if (amode == AUTH_SHARED) { + auth = 1; + wpa_auth = 0; + ANDROID_TRACE(("%s: Authentication: Shared Key\n", __FUNCTION__)); + } else if (amode == AUTH_WPAPSK) { + auth = 0; + wpa_auth = 4; + ANDROID_TRACE(("%s: Authentication: WPA-PSK\n", __FUNCTION__)); + } else if (amode == AUTH_WPA2PSK) { + auth = 0; + wpa_auth = 128; + ANDROID_TRACE(("%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__)); + } + wl_ext_iovar_setint(dev, "auth", auth); + + wl_ext_iovar_setint(dev, "wpa_auth", wpa_auth); + + return 0; +} + +static int +wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params) +{ + struct net_device *dev = cur_if->dev; + int wsec=0; + struct wl_wsec_key wsec_key; + wsec_pmk_t psk; + encmode_t emode = cur_if->emode; + char *key = cur_if->key; + + memset(&wsec_key, 0, sizeof(wsec_key)); + memset(&psk, 0, sizeof(psk)); + if (emode == ENC_NONE) { + wsec = 0; + ANDROID_TRACE(("%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)); + } 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) { + 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)); + } 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)); + } + + wl_ext_iovar_setint(dev, "wsec", wsec); + + if (wsec == 1) { + wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1); + } else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) { + if (dev) { + if (cur_if->ifmode == ISTA_MODE) + wl_ext_iovar_setint(dev, "sup_wpa", 1); + wl_ext_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk), 1); + } else { + ANDROID_ERROR(("%s: apdev is null\n", __FUNCTION__)); + } + } + + return 0; +} + +static int +wl_ext_iapsta_init(struct net_device *dev, char *command, int total_len) +{ + s32 val = 0; + char *pch, *pick_tmp, *param; + wlc_ssid_t ssid = { 0, {0} }; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + struct wl_apsta_params *apsta_params = &g_apsta_params; + wl_interface_create_t iface; + struct dhd_pub *dhd; + wl_p2p_if_t ifreq; + wl_country_t cspec = {{0}, 0, {0}}; + + if (apsta_params->init) { + ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__)); + return -1; + } + + dhd = dhd_get_pub(dev); + memset(apsta_params, 0, sizeof(struct wl_apsta_params)); + + ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init + param = bcmstrtok(&pick_tmp, " ", 0); + while (param != NULL) { + if (!strcmp(param, "mode")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) { + if (!strcmp(pch, "sta")) { + apsta_params->apstamode = ISTAONLY_MODE; + } else if (!strcmp(pch, "ap")) { + apsta_params->apstamode = IAPONLY_MODE; + } else if (!strcmp(pch, "apsta")) { + apsta_params->apstamode = IAPSTA_MODE; + } else if (!strcmp(pch, "dualap")) { + apsta_params->apstamode = IDUALAP_MODE; + } else if (!strcmp(pch, "gosta")) { + if (!FW_SUPPORTED(dhd, p2p)) { + return -1; + } + apsta_params->apstamode = IGOSTA_MODE; + } else if (!strcmp(pch, "gcsta")) { + if (!FW_SUPPORTED(dhd, p2p)) { + return -1; + } + apsta_params->apstamode = IGCSTA_MODE; + } else { + ANDROID_ERROR(("%s: mode [sta|ap|apsta|dualap]\n", __FUNCTION__)); + return -1; + } + } + } else if (!strcmp(param, "vifname")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) + strcpy(apsta_params->vif.ifname, pch); + else { + ANDROID_ERROR(("%s: vifname [wlan1]\n", __FUNCTION__)); + return -1; + } + } + param = bcmstrtok(&pick_tmp, " ", 0); + } + + if (apsta_params->apstamode == 0) { + ANDROID_ERROR(("%s: mode [sta|ap|apsta|dualap]\n", __FUNCTION__)); + return -1; + } + + apsta_params->pif.dev = dev; + apsta_params->pif.bssidx = 0; + strcpy(apsta_params->pif.ifname, dev->name); + strcpy(apsta_params->pif.ssid, "tttp"); + apsta_params->pif.maxassoc = -1; + apsta_params->pif.channel = 1; + + if (!strlen(apsta_params->vif.ifname)) + strcpy(apsta_params->vif.ifname, "wlan1"); + strcpy(apsta_params->vif.ssid, "tttv"); + apsta_params->vif.maxassoc = -1; + apsta_params->vif.channel = 1; + + if (apsta_params->apstamode == ISTAONLY_MODE) { + apsta_params->pif.ifmode = ISTA_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + 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) { + apsta_params->pif.ifmode = IAP_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + dhd_conf_get_country(dhd, &cspec); + if (!dhd_conf_map_country_list(dhd, &cspec, 1)) { + dhd_conf_set_country(dhd, &cspec); + dhd_bus_country_set(dev, &cspec, TRUE); + } + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); #ifdef ARP_OFFLOAD_SUPPORT - /* IF SoftAP is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, FALSE); -#endif /* ARP_OFFLOAD_SUPPORT */ - wl_ext_iovar_setint(dev, "mpc", 0); - wl_ext_iovar_setint(dev, "apsta", 0); - val = 1; - wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); - } else if (apsta_params->apstamode == IAPSTA_MODE) { - apsta_params->pif.ifmode = ISTA_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - apsta_params->vif.ifmode = IAP_MODE; - apsta_params->vif.ifstate = IF_STATE_INIT; - wl_ext_iovar_setint(dev, "mpc", 0); - 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); - 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); - } else { - wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf, - WLC_IOCTL_SMLEN, 1, NULL); - } - } - else if (apsta_params->apstamode == IDUALAP_MODE) { - apsta_params->pif.ifmode = IAP_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - apsta_params->vif.ifmode = IAP_MODE; - apsta_params->vif.ifstate = IF_STATE_INIT; - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_iovar_setint(dev, "apsta", 0); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - val = 1; - wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); - /* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */ + /* IF SoftAP is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, FALSE); +#endif /* ARP_OFFLOAD_SUPPORT */ + wl_ext_iovar_setint(dev, "mpc", 0); + wl_ext_iovar_setint(dev, "apsta", 0); + val = 1; + wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); + } else if (apsta_params->apstamode == IAPSTA_MODE) { + apsta_params->pif.ifmode = ISTA_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + apsta_params->vif.ifmode = IAP_MODE; + apsta_params->vif.ifstate = IF_STATE_INIT; + dhd_conf_get_country(dhd, &cspec); + if (!dhd_conf_map_country_list(dhd, &cspec, 1)) { + dhd_conf_set_country(dhd, &cspec); + dhd_bus_country_set(dev, &cspec, TRUE); + } + wl_ext_iovar_setint(dev, "mpc", 0); + 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); + 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); + } else { + wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf, + WLC_IOCTL_SMLEN, 1, NULL); + } + } + else if (apsta_params->apstamode == IDUALAP_MODE) { + apsta_params->pif.ifmode = IAP_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + apsta_params->vif.ifmode = IAP_MODE; + apsta_params->vif.ifstate = IF_STATE_INIT; + dhd_conf_get_country(dhd, &cspec); + if (!dhd_conf_map_country_list(dhd, &cspec, 1)) { + 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, "apsta", 0); + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + val = 1; + wl_ext_ioctl(dev, WLC_SET_AP, &val, sizeof(val), 1); + /* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */ #ifdef ARP_OFFLOAD_SUPPORT - /* IF SoftAP is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, FALSE); -#endif /* ARP_OFFLOAD_SUPPORT */ - 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); - } - else if (apsta_params->apstamode == IGOSTA_MODE) { - apsta_params->pif.ifmode = ISTA_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - apsta_params->vif.ifmode = IAP_MODE; - apsta_params->vif.ifstate = IF_STATE_INIT; - 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); - wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - } - else if (apsta_params->apstamode == IGCSTA_MODE) { - apsta_params->pif.ifmode = ISTA_MODE; - apsta_params->pif.ifstate = IF_STATE_INIT; - apsta_params->vif.ifmode = ISTA_MODE; - apsta_params->vif.ifstate = IF_STATE_INIT; - 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_CLIENT); - wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - } - - wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); - printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode); - - apsta_params->init = TRUE; - - return 0; -} - -static int -wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) -{ - int i; - char *pch, *pick_tmp, *param; - struct wl_apsta_params *apsta_params = &g_apsta_params; - char ifname[IFNAMSIZ+1]; - struct wl_if_info *cur_if = &apsta_params->pif; - - if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - - pick_tmp = command; - param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_config - param = bcmstrtok(&pick_tmp, " ", 0); - - if (param != NULL) { - if (strcmp(param, "ifname")) { - ANDROID_ERROR(("%s: first arg must be ifname\n", __FUNCTION__)); - return -1; - } - } - - while (param != NULL) { - if (!strcmp(param, "ifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(ifname, pch); - else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); - return -1; - } - if (!strcmp(apsta_params->pif.dev->name, ifname)) { - cur_if = &apsta_params->pif; - } else if (!strcmp(apsta_params->vif.ifname, ifname)) { - cur_if = &apsta_params->vif; - } else { - ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", __FUNCTION__, - ifname, apsta_params->apstamode)); - return -1; - } - } else if (!strcmp(param, "ssid")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(cur_if->ssid, pch); - } else if (!strcmp(param, "bssid")) { - pch = bcmstrtok(&pick_tmp, ": ", 0); - for (i=0; i<6 && pch; i++) { - ((u8 *)&cur_if->bssid)[i] = (int)simple_strtol(pch, NULL, 16); - pch = bcmstrtok(&pick_tmp, ": ", 0); - } - } else if (!strcmp(param, "bgnmode")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "b")) - cur_if->bgnmode = IEEE80211B; - else if (!strcmp(pch, "g")) - cur_if->bgnmode = IEEE80211G; - else if (!strcmp(pch, "bg")) - cur_if->bgnmode = IEEE80211BG; - else if (!strcmp(pch, "bgn")) - cur_if->bgnmode = IEEE80211BGN; - else if (!strcmp(pch, "bgnac")) - cur_if->bgnmode = IEEE80211BGNAC; - else { - ANDROID_ERROR(("%s: bgnmode [b|g|bg|bgn|bgnac]\n", __FUNCTION__)); - return -1; - } - } - } else if (!strcmp(param, "hidden")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "n")) - cur_if->hidden = 0; - else if (!strcmp(pch, "y")) - cur_if->hidden = 1; - else { - ANDROID_ERROR(("%s: hidden [y|n]\n", __FUNCTION__)); - return -1; - } - } - } else if (!strcmp(param, "maxassoc")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - cur_if->maxassoc = (int)simple_strtol(pch, NULL, 10); - } else if (!strcmp(param, "chan")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - cur_if->channel = (int)simple_strtol(pch, NULL, 10); - } else if (!strcmp(param, "amode")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "open")) - cur_if->amode = AUTH_OPEN; - else if (!strcmp(pch, "shared")) - cur_if->amode = AUTH_SHARED; - else if (!strcmp(pch, "wpapsk")) - cur_if->amode = AUTH_WPAPSK; - else if (!strcmp(pch, "wpa2psk")) - cur_if->amode = AUTH_WPA2PSK; - else if (!strcmp(pch, "wpawpa2psk")) - cur_if->amode = AUTH_WPAWPA2PSK; - else { - ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n", - __FUNCTION__)); - return -1; - } - } - } else if (!strcmp(param, "emode")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - if (!strcmp(pch, "none")) - cur_if->emode = ENC_NONE; - else if (!strcmp(pch, "wep")) - cur_if->emode = ENC_WEP; - else if (!strcmp(pch, "tkip")) - cur_if->emode = ENC_TKIP; - else if (!strcmp(pch, "aes")) - cur_if->emode = ENC_AES; - else if (!strcmp(pch, "tkipaes")) - cur_if->emode = ENC_TKIPAES; - else { - ANDROID_ERROR(("%s: emode [none|wep|tkip|aes|tkipaes]\n", - __FUNCTION__)); - return -1; - } - } - } else if (!strcmp(param, "key")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) { - strcpy(cur_if->key, pch); - } - } - param = bcmstrtok(&pick_tmp, " ", 0); - } - - return 0; -} - -static int -wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) -{ - char *pch, *pick_tmp, *param; - s8 iovar_buf[WLC_IOCTL_SMLEN]; - wlc_ssid_t ssid = { 0, {0} }; - scb_val_t scbval; - struct { - s32 tmp; + /* IF SoftAP is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, FALSE); +#endif /* ARP_OFFLOAD_SUPPORT */ + 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); + } + else if (apsta_params->apstamode == IGOSTA_MODE) { + apsta_params->pif.ifmode = ISTA_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + apsta_params->vif.ifmode = IAP_MODE; + apsta_params->vif.ifstate = IF_STATE_INIT; + 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); + wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + } + else if (apsta_params->apstamode == IGCSTA_MODE) { + apsta_params->pif.ifmode = ISTA_MODE; + apsta_params->pif.ifstate = IF_STATE_INIT; + apsta_params->vif.ifmode = ISTA_MODE; + apsta_params->vif.ifstate = IF_STATE_INIT; + 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_CLIENT); + wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + } + + wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver); + printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode); + + apsta_params->init = TRUE; + + return 0; +} + +static int +wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next) +{ + char *pch, *pick_tmp; + char name[20], data[100]; + int i, j; + char *ifname_head = NULL; + + typedef struct config_map_t { + char name[20]; + char *head; + char *tail; + } config_map_t; + + config_map_t config_map [] = { + {" ifname ", NULL, NULL}, + {" ssid ", NULL, NULL}, + {" bssid ", NULL, NULL}, + {" bgnmode ", NULL, NULL}, + {" hidden ", NULL, NULL}, + {" maxassoc ", NULL, NULL}, + {" chan ", NULL, NULL}, + {" amode ", NULL, NULL}, + {" emode ", NULL, NULL}, + {" key ", NULL, NULL}, + }; + config_map_t *row, *row_prev; + + pick_tmp = command; + + // reset head and tail + 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++) { + row = &config_map[i]; + pch = strstr(pick_tmp, row->name); + if (pch) { + row->head = pch; + } + } + + // sort by head + 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++) { + row = &config_map[j]; + if (row->head < row_prev->head) { + strcpy(name, row_prev->name); + strcpy(row_prev->name, row->name); + strcpy(row->name, name); + pch = row_prev->head; + row_prev->head = row->head; + row->head = pch; + } + } + } + + // pick tail + 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) { + row_prev->tail = row->head; + } + } + + // remove name from head + for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) { + row = &config_map[i]; + if (row->head) { + if (!strcmp(row->name, " ifname ")) { + ifname_head = row->head + 1; + break; + } + row->head += strlen(row->name); + } + } + + 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) { + strncpy(data, row->head, row->tail-row->head); + } else { + strcpy(data, row->head); + } + pick_tmp = data; + + if (!strcmp(row->name, " ssid ")) { + strcpy(cur_if->ssid, pick_tmp); + } else if (!strcmp(row->name, " bssid ")) { + pch = bcmstrtok(&pick_tmp, ": ", 0); + for (j=0; j<6 && pch; j++) { + ((u8 *)&cur_if->bssid)[j] = (int)simple_strtol(pch, NULL, 16); + pch = bcmstrtok(&pick_tmp, ": ", 0); + } + } else if (!strcmp(row->name, " bgnmode ")) { + if (!strcmp(pick_tmp, "b")) + cur_if->bgnmode = IEEE80211B; + else if (!strcmp(pick_tmp, "g")) + cur_if->bgnmode = IEEE80211G; + else if (!strcmp(pick_tmp, "bg")) + cur_if->bgnmode = IEEE80211BG; + else if (!strcmp(pick_tmp, "bgn")) + cur_if->bgnmode = IEEE80211BGN; + else if (!strcmp(pick_tmp, "bgnac")) + cur_if->bgnmode = IEEE80211BGNAC; + else { + ANDROID_ERROR(("%s: bgnmode [b|g|bg|bgn|bgnac]\n", __FUNCTION__)); + return -1; + } + } else if (!strcmp(row->name, " hidden ")) { + if (!strcmp(pick_tmp, "n")) + cur_if->hidden = 0; + else if (!strcmp(pick_tmp, "y")) + cur_if->hidden = 1; + else { + ANDROID_ERROR(("%s: hidden [y|n]\n", __FUNCTION__)); + return -1; + } + } else if (!strcmp(row->name, " maxassoc ")) { + cur_if->maxassoc = (int)simple_strtol(pick_tmp, NULL, 10); + } else if (!strcmp(row->name, " chan ")) { + cur_if->channel = (int)simple_strtol(pick_tmp, NULL, 10); + } else if (!strcmp(row->name, " amode ")) { + if (!strcmp(pick_tmp, "open")) + cur_if->amode = AUTH_OPEN; + else if (!strcmp(pick_tmp, "shared")) + cur_if->amode = AUTH_SHARED; + else if (!strcmp(pick_tmp, "wpapsk")) + cur_if->amode = AUTH_WPAPSK; + else if (!strcmp(pick_tmp, "wpa2psk")) + cur_if->amode = AUTH_WPA2PSK; + else if (!strcmp(pick_tmp, "wpawpa2psk")) + cur_if->amode = AUTH_WPAWPA2PSK; + else { + ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n", + __FUNCTION__)); + return -1; + } + } else if (!strcmp(row->name, " emode ")) { + if (!strcmp(pick_tmp, "none")) + cur_if->emode = ENC_NONE; + else if (!strcmp(pick_tmp, "wep")) + cur_if->emode = ENC_WEP; + else if (!strcmp(pick_tmp, "tkip")) + cur_if->emode = ENC_TKIP; + else if (!strcmp(pick_tmp, "aes")) + cur_if->emode = ENC_AES; + else if (!strcmp(pick_tmp, "tkipaes")) + cur_if->emode = ENC_TKIPAES; + else { + ANDROID_ERROR(("%s: emode [none|wep|tkip|aes|tkipaes]\n", + __FUNCTION__)); + return -1; + } + } else if (!strcmp(row->name, " key ")) { + strcpy(cur_if->key, pick_tmp); + } + } + } + + *pick_next = ifname_head; + return 0; +} + +static int +wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len) +{ + int ret=0; + 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->pif; + + if (!apsta_params->init) { + ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); + return -1; + } + + ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_config + + while (pick_tmp != NULL) { + memset(ifname, 0, IFNAMSIZ+1); + if (!strncmp(pick_tmp, "ifname ", strlen("ifname "))) { + pch = pick_tmp + strlen("ifname "); + pch2 = strchr(pch, ' '); + if (pch && pch2) { + strncpy(ifname, pch, pch2-pch); + } else { + ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); + return -1; + } + if (!strcmp(apsta_params->pif.dev->name, ifname)) { + cur_if = &apsta_params->pif; + } else if (!strcmp(apsta_params->vif.ifname, ifname)) { + cur_if = &apsta_params->vif; + } else { + 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); + if (ret) + return -1; + pick_tmp = pick_next; + } else { + ANDROID_ERROR(("%s: first arg must be ifname\n", __FUNCTION__)); + return -1; + } + + } + + return 0; +} + +static int +wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len) +{ + char *pch, *pick_tmp, *param; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wlc_ssid_t ssid = { 0, {0} }; + scb_val_t scbval; + struct { + s32 tmp; s32 cfg; s32 val; - } bss_setbuf; - struct wl_apsta_params *apsta_params = &g_apsta_params; - apstamode_t apstamode = apsta_params->apstamode; - char ifname[IFNAMSIZ+1]; - struct wl_if_info *cur_if; - struct dhd_pub *dhd; - - if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - dhd = dhd_get_pub(dev); - - pick_tmp = command; - param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable - param = bcmstrtok(&pick_tmp, " ", 0); - while (param != NULL) { - if (!strcmp(param, "ifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(ifname, pch); - else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); - return -1; - } - } - param = bcmstrtok(&pick_tmp, " ", 0); - } - if (!strcmp(apsta_params->pif.dev->name, ifname)) { - cur_if = &apsta_params->pif; - } else if (!strcmp(apsta_params->vif.ifname, ifname)) { - cur_if = &apsta_params->vif; - } else { - ANDROID_ERROR(("%s: wrong ifname=%s\n", __FUNCTION__, ifname)); - return -1; - } - if (!cur_if->dev) { - ANDROID_ERROR(("%s: %s is not ready\n", __FUNCTION__, ifname)); - return -1; - } - - if (cur_if->ifmode == ISTA_MODE) { - wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); - } else if (cur_if->ifmode == IAP_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) { - wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); - wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); // reset ssid - wl_ext_iovar_setint(dev, "mpc", 1); - } else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) && - cur_if->ifmode == IAP_MODE) { - // vif is AP mode - bss_setbuf.tmp = 0xffffffff; - bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down - bss_setbuf.val = htod32(0); - wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - wl_ext_iovar_setint(dev, "mpc", 1); -#ifdef ARP_OFFLOAD_SUPPORT - /* IF SoftAP is disabled, enable arpoe back for STA mode. */ - dhd_arp_offload_set(dhd, dhd_arp_mode); - dhd_arp_offload_enable(dhd, TRUE); -#endif /* ARP_OFFLOAD_SUPPORT */ - } else if (apstamode == IDUALAP_MODE) { - bss_setbuf.tmp = 0xffffffff; - bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down - bss_setbuf.val = htod32(0); - wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), - iovar_buf, WLC_IOCTL_SMLEN, NULL); - } - -#ifdef PROP_TXSTATUS_VSDB -#if defined(BCMSDIO) - if (cur_if==&apsta_params->vif && dhd->conf->disable_proptx!=0) { - bool enabled; - dhd_wlfc_get_enable(dhd, &enabled); - if (enabled) { - dhd_wlfc_deinit(dhd); - } - } -#endif -#endif /* PROP_TXSTATUS_VSDB */ - - cur_if->ifstate = IF_STATE_DISALBE; - printf("%s: apstamode=%d, ifname=%s\n", __FUNCTION__, apstamode, ifname); - - return 0; -} - -static int -wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) -{ - int ret = 0; - s32 val = 0; - char *pch, *pick_tmp, *param; - s8 iovar_buf[WLC_IOCTL_SMLEN]; - wlc_ssid_t ssid = { 0, {0} }; - struct { + } bss_setbuf; + struct wl_apsta_params *apsta_params = &g_apsta_params; + apstamode_t apstamode = apsta_params->apstamode; + char ifname[IFNAMSIZ+1]; + struct wl_if_info *cur_if; + struct dhd_pub *dhd; + + if (!apsta_params->init) { + ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); + return -1; + } + + ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + dhd = dhd_get_pub(dev); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_disable + param = bcmstrtok(&pick_tmp, " ", 0); + while (param != NULL) { + if (!strcmp(param, "ifname")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) + strcpy(ifname, pch); + else { + ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); + return -1; + } + } + param = bcmstrtok(&pick_tmp, " ", 0); + } + if (!strcmp(apsta_params->pif.dev->name, ifname)) { + cur_if = &apsta_params->pif; + } else if (!strcmp(apsta_params->vif.ifname, ifname)) { + cur_if = &apsta_params->vif; + } else { + ANDROID_ERROR(("%s: wrong ifname=%s\n", __FUNCTION__, ifname)); + return -1; + } + if (!cur_if->dev) { + ANDROID_ERROR(("%s: %s is not ready\n", __FUNCTION__, ifname)); + return -1; + } + + if (cur_if->ifmode == ISTA_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1); + } else if (cur_if->ifmode == IAP_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) { + wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1); + wl_ext_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); // reset ssid + wl_ext_iovar_setint(dev, "mpc", 1); + } else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) && + cur_if->ifmode == IAP_MODE) { + // vif is AP mode + bss_setbuf.tmp = 0xffffffff; + bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down + bss_setbuf.val = htod32(0); + wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + wl_ext_iovar_setint(dev, "mpc", 1); +#ifdef ARP_OFFLOAD_SUPPORT + /* IF SoftAP is disabled, enable arpoe back for STA mode. */ + dhd_arp_offload_set(dhd, dhd_arp_mode); + dhd_arp_offload_enable(dhd, TRUE); +#endif /* ARP_OFFLOAD_SUPPORT */ + } else if (apstamode == IDUALAP_MODE) { + bss_setbuf.tmp = 0xffffffff; + bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down + bss_setbuf.val = htod32(0); + wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf), + iovar_buf, WLC_IOCTL_SMLEN, NULL); + } + +#ifdef PROP_TXSTATUS_VSDB +#if defined(BCMSDIO) + if (cur_if==&apsta_params->vif && dhd->conf->disable_proptx!=0) { + bool enabled; + dhd_wlfc_get_enable(dhd, &enabled); + if (enabled) { + dhd_wlfc_deinit(dhd); + } + } +#endif +#endif /* PROP_TXSTATUS_VSDB */ + + cur_if->ifstate = IF_STATE_DISALBE; + printf("%s: apstamode=%d, ifname=%s\n", __FUNCTION__, apstamode, ifname); + + return 0; +} + +static int +wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len) +{ + int ret = 0; + s32 val = 0; + char *pch, *pick_tmp, *param; + s8 iovar_buf[WLC_IOCTL_SMLEN]; + wlc_ssid_t ssid = { 0, {0} }; + struct { s32 cfg; s32 val; - } bss_setbuf; - struct wl_apsta_params *apsta_params = &g_apsta_params; - apstamode_t apstamode = apsta_params->apstamode; - char ifname[IFNAMSIZ+1]; - struct wl_if_info *cur_if; - char cmd[128] = "iapsta_stop ifname "; - struct dhd_pub *dhd; - - if (!apsta_params->init) { - ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); - return -1; - } - - ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - dhd = dhd_get_pub(dev); - - pick_tmp = command; - param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_enable - param = bcmstrtok(&pick_tmp, " ", 0); - while (param != NULL) { - if (!strcmp(param, "ifname")) { - pch = bcmstrtok(&pick_tmp, " ", 0); - if (pch) - strcpy(ifname, pch); - else { - ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); - return -1; - } - } - param = bcmstrtok(&pick_tmp, " ", 0); - } - if (!strcmp(apsta_params->pif.dev->name, ifname)) { - cur_if = &apsta_params->pif; - } else if (!strcmp(apsta_params->vif.ifname, ifname)) { - cur_if = &apsta_params->vif; - } else { - ANDROID_ERROR(("%s: wrong ifname=%s\n", __FUNCTION__, ifname)); - return -1; - } - if (!cur_if->dev) { - ANDROID_ERROR(("%s: %s is not ready\n", __FUNCTION__, ifname)); - return -1; - } - 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)); - - snprintf(cmd, 128, "iapsta_stop ifname %s", cur_if->ifname); - ret = wl_ext_iapsta_disable(dev, cmd, strlen(cmd)); - if (ret) - goto exit; - - if (cur_if == &apsta_params->vif) { - 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 - if (cur_if->ifmode == IAP_MODE) { - wl_ext_iovar_setint(dev, "mpc", 0); - if (apstamode == IAPONLY_MODE) { - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - } else if (apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) { - wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "ssid", &ssid, sizeof(ssid), - iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL); - } - } - - if (cur_if->ifmode == IAP_MODE) { - wl_ext_set_bgnmode(cur_if); - wl_ext_set_chanspec(cur_if->dev, cur_if->channel); - } - wl_ext_set_amode(cur_if, apsta_params); - wl_ext_set_emode(cur_if, apsta_params); - - if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) { - if (!ETHER_ISBCAST(&cur_if->bssid) && !ETHER_ISNULLADDR(&cur_if->bssid)) { - printf("%s: BSSID: %pM\n", __FUNCTION__, &cur_if->bssid); - wl_ext_ioctl(cur_if->dev, WLC_SET_BSSID, &cur_if->bssid, ETHER_ADDR_LEN, 1); - } - val = 1; - wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); - } - if (cur_if->ifmode == IAP_MODE) { - if (cur_if->maxassoc >= 0) - wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc); - printf("%s: Broadcast SSID: %s\n", __FUNCTION__, cur_if->hidden ? "OFF":"ON"); - // terence: fix me, hidden does not work in dualAP mode - wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1); - } - - if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) { - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); - } else if (apstamode == IAPONLY_MODE) { - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - } else if (apstamode == IAPSTA_MODE || apstamode == IGOSTA_MODE) { - if (cur_if->ifmode == ISTA_MODE) { - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); - } else { - if (FW_SUPPORTED(dhd, rsdb)) { - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); - } 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); - } + } bss_setbuf; + struct wl_apsta_params *apsta_params = &g_apsta_params; + apstamode_t apstamode = apsta_params->apstamode; + char ifname[IFNAMSIZ+1]; + struct wl_if_info *cur_if; + char cmd[128] = "iapsta_stop ifname "; + struct dhd_pub *dhd; + + if (!apsta_params->init) { + ANDROID_ERROR(("%s: please init first\n", __FUNCTION__)); + return -1; + } + + ANDROID_TRACE(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); + dhd = dhd_get_pub(dev); + + pick_tmp = command; + param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_enable + param = bcmstrtok(&pick_tmp, " ", 0); + while (param != NULL) { + if (!strcmp(param, "ifname")) { + pch = bcmstrtok(&pick_tmp, " ", 0); + if (pch) + strcpy(ifname, pch); + else { + ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__)); + return -1; + } + } + param = bcmstrtok(&pick_tmp, " ", 0); + } + if (!strcmp(apsta_params->pif.dev->name, ifname)) { + cur_if = &apsta_params->pif; + } else if (!strcmp(apsta_params->vif.ifname, ifname)) { + cur_if = &apsta_params->vif; + } else { + ANDROID_ERROR(("%s: wrong ifname=%s\n", __FUNCTION__, ifname)); + return -1; + } + if (!cur_if->dev) { + ANDROID_ERROR(("%s: %s is not ready\n", __FUNCTION__, ifname)); + return -1; + } + 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)); + + snprintf(cmd, 128, "iapsta_stop ifname %s", cur_if->ifname); + ret = wl_ext_iapsta_disable(dev, cmd, strlen(cmd)); + if (ret) + goto exit; + + if (cur_if == &apsta_params->vif) { + 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 + if (cur_if->ifmode == IAP_MODE) { + wl_ext_iovar_setint(dev, "mpc", 0); + if (apstamode == IAPONLY_MODE) { + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + } else if (apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) { + wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "ssid", &ssid, sizeof(ssid), + iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL); + } + } + + if (cur_if->ifmode == IAP_MODE) { + wl_ext_set_bgnmode(cur_if); + wl_ext_set_chanspec(cur_if->dev, cur_if->channel); + } + wl_ext_set_amode(cur_if, apsta_params); + wl_ext_set_emode(cur_if, apsta_params); + + if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) { + if (!ETHER_ISBCAST(&cur_if->bssid) && !ETHER_ISNULLADDR(&cur_if->bssid)) { + printf("%s: BSSID: %pM\n", __FUNCTION__, &cur_if->bssid); + wl_ext_ioctl(cur_if->dev, WLC_SET_BSSID, &cur_if->bssid, ETHER_ADDR_LEN, 1); + } + val = 1; + wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1); + } + if (cur_if->ifmode == IAP_MODE) { + if (cur_if->maxassoc >= 0) + wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc); + printf("%s: Broadcast SSID: %s\n", __FUNCTION__, cur_if->hidden ? "OFF":"ON"); + // terence: fix me, hidden does not work in dualAP mode + wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1); + } + + if (apstamode == ISTAONLY_MODE || apstamode == IGCSTA_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } else if (apstamode == IAPONLY_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + } else if (apstamode == IAPSTA_MODE || apstamode == IGOSTA_MODE) { + if (cur_if->ifmode == ISTA_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } else { + if (FW_SUPPORTED(dhd, rsdb)) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } 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); + } #ifdef ARP_OFFLOAD_SUPPORT - /* IF SoftAP is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, FALSE); -#endif /* ARP_OFFLOAD_SUPPORT */ - } - } - else if (apstamode == IDUALAP_MODE) { - wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); - } - -#ifdef PROP_TXSTATUS_VSDB -#if defined(BCMSDIO) - if (cur_if==&apsta_params->vif && !disable_proptx) { - bool enabled; - dhd_wlfc_get_enable(dhd, &enabled); - if (!enabled) { - dhd_wlfc_init(dhd); - wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); - } - } -#endif -#endif /* PROP_TXSTATUS_VSDB */ - - printf("%s: ifname=%s, SSID: %s\n", __FUNCTION__, ifname, cur_if->ssid); - - cur_if->ifstate = IF_STATE_ENABLE; - -exit: - return ret; -} - -void -wl_android_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - struct wl_if_info *cur_if = &apsta_params->vif; - scb_val_t scbval; - int ret; - channel_info_t ci; - struct dhd_pub *dhd; - - if (apsta_params->apstamode==IAPSTA_MODE && cur_if->ifstate==IF_STATE_ENABLE) { - dhd = dhd_get_pub(dev); - if (!FW_SUPPORTED(dhd, vsdb)) { - if (!(ret = wldev_ioctl(cur_if->dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) { - if (channel != ci.target_channel) { - printf("%s: deauthenticate all STA on vif\n", __FUNCTION__); - memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN); - wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1); - } - } - } - } -} - -int wl_android_ext_attach_netdev(struct net_device *net, uint8 bssidx) -{ - g_apsta_params.vif.dev = net; - g_apsta_params.vif.bssidx = bssidx; - if (strlen(g_apsta_params.vif.ifname)) { - memset(net->name, 0, sizeof(IFNAMSIZ)); - strcpy(net->name, g_apsta_params.vif.ifname); - net->name[IFNAMSIZ - 1] = '\0'; - } - if (g_apsta_params.pif.dev) { - memcpy(net->dev_addr, g_apsta_params.pif.dev->dev_addr, ETHER_ADDR_LEN); - net->dev_addr[0] |= 0x02; - } - - return 0; -} - -int wl_android_ext_dettach_netdev(void) -{ - struct wl_apsta_params *apsta_params = &g_apsta_params; - - ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); - memset(apsta_params, 0, sizeof(struct wl_apsta_params)); - - return 0; -} -#endif - -#ifdef IDHCP -int wl_ext_ip_dump(int ip, char *buf) -{ - unsigned char bytes[4]; - int bytes_written=-1; - - bytes[0] = ip & 0xFF; - bytes[1] = (ip >> 8) & 0xFF; - bytes[2] = (ip >> 16) & 0xFF; - bytes[3] = (ip >> 24) & 0xFF; - bytes_written = sprintf(buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); - - return bytes_written; -} - -/* -terence 20170215: -dhd_priv dhcpc_dump ifname [wlan0|wlan1] -dhd_priv dhcpc_enable [0|1] -*/ -int -wl_ext_dhcpc_enable(struct net_device *dev, char *command, int total_len) -{ - int enable = -1, ret = -1; - int bytes_written = -1; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - sscanf(command, "%*s %d", &enable); - - if (enable >= 0) - ret = wl_ext_iovar_setint(dev, "dhcpc_enable", enable); - else { - ret = wl_ext_iovar_getint(dev, "dhcpc_enable", &enable); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", enable); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - - return ret; -} - -int -wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len) -{ - - int ret = 0; - int bytes_written = 0; - uint32 ip_addr; - char buf[20]=""; - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_addr", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "ipaddr %s ", buf); - } - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_mask", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "mask %s ", buf); - } - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_gateway", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "gw %s ", buf); - } - - ret = wl_ext_iovar_getint(dev, "dhcpc_ip_dnsserv", &ip_addr); - if (!ret) { - wl_ext_ip_dump(ip_addr, buf); - bytes_written += snprintf(command+bytes_written, total_len, "dnsserv %s ", buf); - } - - if (!bytes_written) - bytes_written = -1; - - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - - return bytes_written; -} -#endif - -/* -dhd_priv dhd [string] ==> Not ready -1. Get dhd val: - Ex: dhd_priv dhd bussleep -2. Set dhd val: - Ex: dhd_priv dhd bussleep 1 - -dhd_priv wl [WLC_GET_PM] ==> Ready to get int val -dhd_priv wl [WLC_SET_PM] [int] ==> Ready to set int val -dhd_priv wl [string] ==> Ready to get int val -dhd_priv wl [string] [int] ==> Ready to set int val -Ex: get/set WLC_PM - dhd_priv wl 85 - dhd_priv wl 86 1 -Ex: get/set mpc - dhd_priv wl mpc - dhd_priv wl mpc 1 -*/ -int -wl_ext_iovar(struct net_device *dev, char *command, int total_len) -{ - int ret = 0; - char wl[3]="\0", arg[20]="\0", cmd_str[20]="\0", val_str[20]="\0"; - int cmd=-1, val=0; - int bytes_written=-1; - - ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); - - sscanf(command, "%s %d %s", wl, &cmd, arg); - if (cmd < 0) - sscanf(command, "%s %s %s", wl, cmd_str, val_str); - - if (!strcmp(wl, "wl")) { - if (cmd>=0 && cmd!=WLC_GET_VAR && cmd!=WLC_SET_VAR) { - ret = sscanf(arg, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); - } else { // get - ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - } else if (strlen(cmd_str)) { - ret = sscanf(val_str, "%d", &val); - if (ret > 0) { // set - ret = wl_ext_iovar_setint(dev, cmd_str, val); - } else { // get - ret = wl_ext_iovar_getint(dev, cmd_str, &val); - if (!ret) { - bytes_written = snprintf(command, total_len, "%d", val); - ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); - ret = bytes_written; - } - } - } - } - - return ret; -} - -int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, - int *bytes_written) -{ - int ret = 0; - - if (strnicmp(command, CMD_CHANNELS, strlen(CMD_CHANNELS)) == 0) { - *bytes_written = wl_ext_channels(net, command, total_len); - } - else if (strnicmp(command, CMD_CHANNEL, strlen(CMD_CHANNEL)) == 0) { - *bytes_written = wl_ext_channel(net, command, total_len); - } - else if (strnicmp(command, CMD_ROAM_TRIGGER, strlen(CMD_ROAM_TRIGGER)) == 0) { - *bytes_written = wl_ext_roam_trigger(net, command, total_len); - } - else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) { - *bytes_written = wl_ext_keep_alive(net, command, total_len); - } - else if (strnicmp(command, CMD_PM, strlen(CMD_PM)) == 0) { - *bytes_written = wl_ext_pm(net, command, total_len); - } + /* IF SoftAP is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, FALSE); +#endif /* ARP_OFFLOAD_SUPPORT */ + } + } + else if (apstamode == IDUALAP_MODE) { + wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1); + } + +#ifdef PROP_TXSTATUS_VSDB +#if defined(BCMSDIO) + if (cur_if==&apsta_params->vif && !disable_proptx) { + bool enabled; + dhd_wlfc_get_enable(dhd, &enabled); + if (!enabled) { + dhd_wlfc_init(dhd); + wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1); + } + } +#endif +#endif /* PROP_TXSTATUS_VSDB */ + + printf("%s: ifname=%s, SSID: \"%s\"\n", __FUNCTION__, ifname, cur_if->ssid); + + cur_if->ifstate = IF_STATE_ENABLE; + +exit: + return ret; +} + +void +wl_android_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel) +{ + struct wl_apsta_params *apsta_params = &g_apsta_params; + struct wl_if_info *cur_if = &apsta_params->vif; + scb_val_t scbval; + int ret; + channel_info_t ci; + struct dhd_pub *dhd; + + if (apsta_params->apstamode==IAPSTA_MODE && cur_if->ifstate==IF_STATE_ENABLE) { + dhd = dhd_get_pub(dev); + if (!FW_SUPPORTED(dhd, vsdb)) { + if (!(ret = wldev_ioctl(cur_if->dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) { + if (channel != ci.target_channel) { + printf("%s: deauthenticate all STA on vif\n", __FUNCTION__); + memcpy(scbval.ea.octet, ðer_bcast, ETHER_ADDR_LEN); + wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1); + } + } + } + } +} + +int wl_android_ext_attach_netdev(struct net_device *net, uint8 bssidx) +{ + g_apsta_params.vif.dev = net; + g_apsta_params.vif.bssidx = bssidx; + if (strlen(g_apsta_params.vif.ifname)) { + memset(net->name, 0, sizeof(IFNAMSIZ)); + strcpy(net->name, g_apsta_params.vif.ifname); + net->name[IFNAMSIZ - 1] = '\0'; + } + if (g_apsta_params.pif.dev) { + memcpy(net->dev_addr, g_apsta_params.pif.dev->dev_addr, ETHER_ADDR_LEN); + net->dev_addr[0] |= 0x02; + } + + return 0; +} + +int wl_android_ext_dettach_netdev(void) +{ + struct wl_apsta_params *apsta_params = &g_apsta_params; + + ANDROID_TRACE(("%s: Enter\n", __FUNCTION__)); + memset(apsta_params, 0, sizeof(struct wl_apsta_params)); + + return 0; +} +#endif + +#ifdef IDHCP +int wl_ext_ip_dump(int ip, char *buf) +{ + unsigned char bytes[4]; + int bytes_written=-1; + + bytes[0] = ip & 0xFF; + bytes[1] = (ip >> 8) & 0xFF; + bytes[2] = (ip >> 16) & 0xFF; + bytes[3] = (ip >> 24) & 0xFF; + bytes_written = sprintf(buf, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2], bytes[3]); + + return bytes_written; +} + +/* +terence 20170215: +dhd_priv dhcpc_dump ifname [wlan0|wlan1] +dhd_priv dhcpc_enable [0|1] +*/ +int +wl_ext_dhcpc_enable(struct net_device *dev, char *command, int total_len) +{ + int enable = -1, ret = -1; + int bytes_written = -1; + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + + sscanf(command, "%*s %d", &enable); + + if (enable >= 0) + ret = wl_ext_iovar_setint(dev, "dhcpc_enable", enable); + else { + ret = wl_ext_iovar_getint(dev, "dhcpc_enable", &enable); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", enable); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + + return ret; +} + +int +wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len) +{ + + int ret = 0; + int bytes_written = 0; + uint32 ip_addr; + char buf[20]=""; + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_addr", &ip_addr); + if (!ret) { + wl_ext_ip_dump(ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, "ipaddr %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_mask", &ip_addr); + if (!ret) { + wl_ext_ip_dump(ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, "mask %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_gateway", &ip_addr); + if (!ret) { + wl_ext_ip_dump(ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, "gw %s ", buf); + } + + ret = wl_ext_iovar_getint(dev, "dhcpc_ip_dnsserv", &ip_addr); + if (!ret) { + wl_ext_ip_dump(ip_addr, buf); + bytes_written += snprintf(command+bytes_written, total_len, "dnsserv %s ", buf); + } + + if (!bytes_written) + bytes_written = -1; + + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + + return bytes_written; +} +#endif + +/* +dhd_priv dhd [string] ==> Not ready +1. Get dhd val: + Ex: dhd_priv dhd bussleep +2. Set dhd val: + Ex: dhd_priv dhd bussleep 1 + +dhd_priv wl [WLC_GET_PM] ==> Ready to get int val +dhd_priv wl [WLC_SET_PM] [int] ==> Ready to set int val +dhd_priv wl [string] ==> Ready to get int val +dhd_priv wl [string] [int] ==> Ready to set int val +Ex: get/set WLC_PM + dhd_priv wl 85 + dhd_priv wl 86 1 +Ex: get/set mpc + dhd_priv wl mpc + dhd_priv wl mpc 1 +*/ +int +wl_ext_iovar(struct net_device *dev, char *command, int total_len) +{ + int ret = 0; + char wl[3]="\0", arg[20]="\0", cmd_str[20]="\0", val_str[20]="\0"; + int cmd=-1, val=0; + int bytes_written=-1; + + ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command)); + + sscanf(command, "%s %d %s", wl, &cmd, arg); + if (cmd < 0) + sscanf(command, "%s %s %s", wl, cmd_str, val_str); + + if (!strcmp(wl, "wl")) { + if (cmd>=0 && cmd!=WLC_GET_VAR && cmd!=WLC_SET_VAR) { + ret = sscanf(arg, "%d", &val); + if (ret > 0) { // set + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), TRUE); + } else { // get + ret = wl_ext_ioctl(dev, cmd, &val, sizeof(val), FALSE); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + } else if (strlen(cmd_str)) { + ret = sscanf(val_str, "%d", &val); + if (ret > 0) { // set + ret = wl_ext_iovar_setint(dev, cmd_str, val); + } else { // get + ret = wl_ext_iovar_getint(dev, cmd_str, &val); + if (!ret) { + bytes_written = snprintf(command, total_len, "%d", val); + ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command)); + ret = bytes_written; + } + } + } + } + + return ret; +} + +int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len, + int *bytes_written) +{ + int ret = 0; + + if (strnicmp(command, CMD_CHANNELS, strlen(CMD_CHANNELS)) == 0) { + *bytes_written = wl_ext_channels(net, command, total_len); + } + else if (strnicmp(command, CMD_CHANNEL, strlen(CMD_CHANNEL)) == 0) { + *bytes_written = wl_ext_channel(net, command, total_len); + } + else if (strnicmp(command, CMD_ROAM_TRIGGER, strlen(CMD_ROAM_TRIGGER)) == 0) { + *bytes_written = wl_ext_roam_trigger(net, command, total_len); + } + else if (strnicmp(command, CMD_KEEP_ALIVE, strlen(CMD_KEEP_ALIVE)) == 0) { + *bytes_written = wl_ext_keep_alive(net, command, total_len); + } + else if (strnicmp(command, CMD_PM, strlen(CMD_PM)) == 0) { + *bytes_written = wl_ext_pm(net, command, total_len); + } else if (strnicmp(command, CMD_MONITOR, strlen(CMD_MONITOR)) == 0) { - *bytes_written = wl_ext_monitor(net, command, total_len); - } - else if (strnicmp(command, CMD_SET_SUSPEND_BCN_LI_DTIM, strlen(CMD_SET_SUSPEND_BCN_LI_DTIM)) == 0) { - int bcn_li_dtim; - bcn_li_dtim = (int)simple_strtol((command + strlen(CMD_SET_SUSPEND_BCN_LI_DTIM) + 1), NULL, 10); - *bytes_written = net_os_set_suspend_bcn_li_dtim(net, bcn_li_dtim); - } -#ifdef WL_EXT_IAPSTA - else if (strnicmp(command, CMD_IAPSTA_INIT, strlen(CMD_IAPSTA_INIT)) == 0) { - *bytes_written = wl_ext_iapsta_init(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_CONFIG, strlen(CMD_IAPSTA_CONFIG)) == 0) { - *bytes_written = wl_ext_iapsta_config(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_ENABLE, strlen(CMD_IAPSTA_ENABLE)) == 0) { - *bytes_written = wl_ext_iapsta_enable(net, command, total_len); - } - else if (strnicmp(command, CMD_IAPSTA_DISABLE, strlen(CMD_IAPSTA_DISABLE)) == 0) { - *bytes_written = wl_ext_iapsta_disable(net, command, total_len); - } -#endif -#ifdef IDHCP - else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) { - *bytes_written = wl_ext_dhcpc_enable(net, command, total_len); - } - else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) { - *bytes_written = wl_ext_dhcpc_dump(net, command, total_len); - } -#endif - else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) { - *bytes_written = wl_ext_iovar(net, command, total_len); - } - else - ret = -1; - - return ret; -} - -#if defined(RSSIAVG) -void -wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) -{ - wl_rssi_cache_t *node, *cur, **rssi_head; - int i=0; - - rssi_head = &rssi_cache_ctrl->m_cache_head; - node = *rssi_head; - - for (;node;) { - ANDROID_INFO(("%s: Free %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); - cur = node; - node = cur->next; - kfree(cur); - i++; - } - *rssi_head = NULL; -} - -void -wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) -{ - wl_rssi_cache_t *node, *prev, **rssi_head; - int i = -1, tmp = 0; - struct timeval now; - - do_gettimeofday(&now); - - rssi_head = &rssi_cache_ctrl->m_cache_head; - node = *rssi_head; - prev = node; - for (;node;) { - i++; - if (now.tv_sec > node->tv.tv_sec) { - if (node == *rssi_head) { - tmp = 1; - *rssi_head = node->next; - } else { - tmp = 0; - prev->next = node->next; - } - ANDROID_INFO(("%s: Del %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); - kfree(node); - if (tmp == 1) { - node = *rssi_head; - prev = node; - } else { - node = prev->next; - } - continue; - } - prev = node; - node = node->next; - } -} - -void -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; - - rssi_head = &rssi_cache_ctrl->m_cache_head; - node = *rssi_head; - prev = node; - for (;node;) { - i++; - if (!memcmp(&node->BSSID, bssid, ETHER_ADDR_LEN)) { - if (node == *rssi_head) { - tmp = 1; - *rssi_head = node->next; - } else { - tmp = 0; - prev->next = node->next; - } - ANDROID_INFO(("%s: Del %d with BSSID %pM\n", - __FUNCTION__, i, &node->BSSID)); - kfree(node); - if (tmp == 1) { - node = *rssi_head; - prev = node; - } else { - node = prev->next; - } - continue; - } - prev = node; - node = node->next; - } -} - -void -wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) -{ - wl_rssi_cache_t *node, **rssi_head; - - rssi_head = &rssi_cache_ctrl->m_cache_head; - - /* reset dirty */ - node = *rssi_head; - for (;node;) { - node->dirty += 1; - node = node->next; - } -} - -int -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; - - if (!g_wifi_on) - return 0; - - error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false); - if (error == BCME_NOTASSOCIATED) { - ANDROID_INFO(("%s: Not Associated! res:%d\n", __FUNCTION__, error)); - return 0; - } - if (error) { - ANDROID_ERROR(("Could not get bssid (%d)\n", error)); - } - error = wldev_get_rssi(net, &rssi); - if (error) { - ANDROID_ERROR(("Could not get rssi (%d)\n", error)); - return error; - } - - do_gettimeofday(&now); - timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; - if (timeout.tv_sec < now.tv_sec) { - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); - } - - /* update RSSI */ - rssi_head = &rssi_cache_ctrl->m_cache_head; - node = *rssi_head; - prev = NULL; - for (;node;) { - if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) { - ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n", - __FUNCTION__, k, &bssid, rssi)); - for (j=0; jRSSI[j] = node->RSSI[j+1]; - node->RSSI[j] = rssi; - node->dirty = 0; - node->tv = timeout; - goto exit; - } - prev = node; - node = node->next; - k++; - } - - leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); - if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", - __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); - return 0; - } - ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n", - __FUNCTION__, k, &bssid, rssi)); - - leaf->next = NULL; - leaf->dirty = 0; - leaf->tv = timeout; - memcpy(&leaf->BSSID, &bssid, ETHER_ADDR_LEN); - for (j=0; jRSSI[j] = rssi; - - if (!prev) - *rssi_head = leaf; - else - prev->next = leaf; - -exit: - *rssi_avg = (int)wl_get_avg_rssi(rssi_cache_ctrl, &bssid); - - return error; -} - -void -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; - int i, j, k; - struct timeval now, timeout; - - if (!ss_list->count) - return; - - do_gettimeofday(&now); - timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; - if (timeout.tv_sec < now.tv_sec) { - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); - } - - rssi_head = &rssi_cache_ctrl->m_cache_head; - - /* update RSSI */ - for (i = 0; i < ss_list->count; i++) { - node = *rssi_head; - prev = NULL; - k = 0; - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; - for (;node;) { - if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { - ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); - for (j=0; jRSSI[j] = node->RSSI[j+1]; - node->RSSI[j] = dtoh16(bi->RSSI); - node->dirty = 0; - node->tv = timeout; - break; - } - prev = node; - node = node->next; - k++; - } - - if (node) - continue; - - leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); - if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", - __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); - return; - } - ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); - - leaf->next = NULL; - leaf->dirty = 0; - leaf->tv = timeout; - memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN); - for (j=0; jRSSI[j] = dtoh16(bi->RSSI); - - if (!prev) - *rssi_head = leaf; - else - prev->next = leaf; - } -} - -int16 -wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) -{ - wl_rssi_cache_t *node, **rssi_head; - int j, rssi_sum, rssi=RSSI_MINVAL; - - rssi_head = &rssi_cache_ctrl->m_cache_head; - - node = *rssi_head; - for (;node;) { - if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) { - rssi_sum = 0; - rssi = 0; - for (j=0; jRSSI[RSSIAVG_LEN-j-1]; - rssi = rssi_sum / j; - break; - } - node = node->next; - } - rssi = MIN(rssi, RSSI_MAXVAL); - if (rssi == RSSI_MINVAL) { - ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n", - __FUNCTION__, addr)); - } - return (int16)rssi; -} -#endif - -#if defined(RSSIOFFSET) -int -wl_update_rssi_offset(struct net_device *net, int rssi) -{ -#if defined(RSSIOFFSET_NEW) - int j; -#endif - - if (!g_wifi_on) - return rssi; - -#if defined(RSSIOFFSET_NEW) - for (j=0; jm_cache_head; - node = *bss_head; - - for (;node;) { - ANDROID_TRACE(("%s: Free %d with BSSID %pM\n", - __FUNCTION__, i, &node->results.bss_info->BSSID)); - cur = node; - node = cur->next; - kfree(cur); - i++; - } - *bss_head = NULL; -} - -void -wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) -{ - wl_bss_cache_t *node, *prev, **bss_head; - int i = -1, tmp = 0; - struct timeval now; - - do_gettimeofday(&now); - - bss_head = &bss_cache_ctrl->m_cache_head; - node = *bss_head; - prev = node; - for (;node;) { - i++; - if (now.tv_sec > node->tv.tv_sec) { - if (node == *bss_head) { - tmp = 1; - *bss_head = node->next; - } else { - tmp = 0; - prev->next = node->next; - } - ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, i, &node->results.bss_info->BSSID, - dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); - kfree(node); - if (tmp == 1) { - node = *bss_head; - prev = node; - } else { - node = prev->next; - } - continue; - } - prev = node; - node = node->next; - } -} - -void -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; - - bss_head = &bss_cache_ctrl->m_cache_head; - node = *bss_head; - prev = node; - for (;node;) { - i++; - if (!memcmp(&node->results.bss_info->BSSID, bssid, ETHER_ADDR_LEN)) { - if (node == *bss_head) { - tmp = 1; - *bss_head = node->next; - } else { - tmp = 0; - prev->next = node->next; - } - ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, i, &node->results.bss_info->BSSID, - dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); - kfree(node); - if (tmp == 1) { - node = *bss_head; - prev = node; - } else { - node = prev->next; - } - continue; - } - prev = node; - node = node->next; - } -} - -void -wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) -{ - wl_bss_cache_t *node, **bss_head; - - bss_head = &bss_cache_ctrl->m_cache_head; - - /* reset dirty */ - node = *bss_head; - for (;node;) { - node->dirty += 1; - node = node->next; - } -} - -void dump_bss_cache( -#if defined(RSSIAVG) - wl_rssi_cache_ctrl_t *rssi_cache_ctrl, -#endif - wl_bss_cache_t *node) -{ - int k = 0; - int16 rssi; - - for (;node;) { -#if defined(RSSIAVG) - rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); -#else - 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)); - k++; - node = node->next; - } -} - -void -wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, -#if defined(RSSIAVG) - wl_rssi_cache_ctrl_t *rssi_cache_ctrl, -#endif - wl_scan_results_t *ss_list) -{ - wl_bss_cache_t *node, *prev, *leaf, **bss_head; - wl_bss_info_t *bi = NULL; - int i, k=0; -#if defined(SORT_BSS_BY_RSSI) - int16 rssi, rssi_node; -#endif - struct timeval now, timeout; - - if (!ss_list->count) - return; - - do_gettimeofday(&now); - timeout.tv_sec = now.tv_sec + BSSCACHE_TIMEOUT; - if (timeout.tv_sec < now.tv_sec) { - /* - * Integer overflow - assume long enough timeout to be assumed - * to be infinite, i.e., the timeout would never happen. - */ - ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", - __FUNCTION__, BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); - } - - bss_head = &bss_cache_ctrl->m_cache_head; - - for (i=0; i < ss_list->count; i++) { - node = *bss_head; - prev = NULL; - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; - - for (;node;) { - if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { - if (node == *bss_head) - *bss_head = node->next; - else { - prev->next = node->next; - } - break; - } - prev = node; - node = node->next; - } - - leaf = kmalloc(dtoh32(bi->length) + sizeof(wl_bss_cache_t), GFP_KERNEL); - if (!leaf) { - ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__, - dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t))); - return; - } - if (node) { - kfree(node); - node = NULL; - ANDROID_TRACE(("%s: Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); - } else - ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", - __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); - - memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); - leaf->next = NULL; - leaf->dirty = 0; - leaf->tv = timeout; - leaf->results.count = 1; - leaf->results.version = ss_list->version; - k++; - - if (*bss_head == NULL) - *bss_head = leaf; - else { -#if defined(SORT_BSS_BY_RSSI) - node = *bss_head; -#if defined(RSSIAVG) - rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID); -#else - rssi = dtoh16(leaf->results.bss_info->RSSI); -#endif - for (;node;) { -#if defined(RSSIAVG) - rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); -#else - rssi_node = dtoh16(node->results.bss_info->RSSI); -#endif - if (rssi > rssi_node) { - leaf->next = node; - if (node == *bss_head) - *bss_head = leaf; - else - prev->next = leaf; - break; - } - prev = node; - node = node->next; - } - if (node == NULL) - prev->next = leaf; -#else - leaf->next = *bss_head; - *bss_head = leaf; -#endif - } - } - dump_bss_cache( -#if defined(RSSIAVG) - rssi_cache_ctrl, -#endif - *bss_head); -} - -void -wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) -{ - ANDROID_TRACE(("%s:\n", __FUNCTION__)); - wl_free_bss_cache(bss_cache_ctrl); -} -#endif - - + *bytes_written = wl_ext_monitor(net, command, total_len); + } + else if (strnicmp(command, CMD_SET_SUSPEND_BCN_LI_DTIM, strlen(CMD_SET_SUSPEND_BCN_LI_DTIM)) == 0) { + int bcn_li_dtim; + bcn_li_dtim = (int)simple_strtol((command + strlen(CMD_SET_SUSPEND_BCN_LI_DTIM) + 1), NULL, 10); + *bytes_written = net_os_set_suspend_bcn_li_dtim(net, bcn_li_dtim); + } +#ifdef WL_EXT_IAPSTA + else if (strnicmp(command, CMD_IAPSTA_INIT, strlen(CMD_IAPSTA_INIT)) == 0) { + *bytes_written = wl_ext_iapsta_init(net, command, total_len); + } + else if (strnicmp(command, CMD_IAPSTA_CONFIG, strlen(CMD_IAPSTA_CONFIG)) == 0) { + *bytes_written = wl_ext_iapsta_config(net, command, total_len); + } + else if (strnicmp(command, CMD_IAPSTA_ENABLE, strlen(CMD_IAPSTA_ENABLE)) == 0) { + *bytes_written = wl_ext_iapsta_enable(net, command, total_len); + } + else if (strnicmp(command, CMD_IAPSTA_DISABLE, strlen(CMD_IAPSTA_DISABLE)) == 0) { + *bytes_written = wl_ext_iapsta_disable(net, command, total_len); + } +#endif +#ifdef IDHCP + else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) { + *bytes_written = wl_ext_dhcpc_enable(net, command, total_len); + } + else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) { + *bytes_written = wl_ext_dhcpc_dump(net, command, total_len); + } +#endif + else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) { + *bytes_written = wl_ext_iovar(net, command, total_len); + } + else + ret = -1; + + return ret; +} + +#if defined(RSSIAVG) +void +wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) +{ + wl_rssi_cache_t *node, *cur, **rssi_head; + int i=0; + + rssi_head = &rssi_cache_ctrl->m_cache_head; + node = *rssi_head; + + for (;node;) { + ANDROID_INFO(("%s: Free %d with BSSID %pM\n", + __FUNCTION__, i, &node->BSSID)); + cur = node; + node = cur->next; + kfree(cur); + i++; + } + *rssi_head = NULL; +} + +void +wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) +{ + wl_rssi_cache_t *node, *prev, **rssi_head; + int i = -1, tmp = 0; + struct timeval now; + + do_gettimeofday(&now); + + rssi_head = &rssi_cache_ctrl->m_cache_head; + node = *rssi_head; + prev = node; + for (;node;) { + i++; + if (now.tv_sec > node->tv.tv_sec) { + if (node == *rssi_head) { + tmp = 1; + *rssi_head = node->next; + } else { + tmp = 0; + prev->next = node->next; + } + ANDROID_INFO(("%s: Del %d with BSSID %pM\n", + __FUNCTION__, i, &node->BSSID)); + kfree(node); + if (tmp == 1) { + node = *rssi_head; + prev = node; + } else { + node = prev->next; + } + continue; + } + prev = node; + node = node->next; + } +} + +void +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; + + rssi_head = &rssi_cache_ctrl->m_cache_head; + node = *rssi_head; + prev = node; + for (;node;) { + i++; + if (!memcmp(&node->BSSID, bssid, ETHER_ADDR_LEN)) { + if (node == *rssi_head) { + tmp = 1; + *rssi_head = node->next; + } else { + tmp = 0; + prev->next = node->next; + } + ANDROID_INFO(("%s: Del %d with BSSID %pM\n", + __FUNCTION__, i, &node->BSSID)); + kfree(node); + if (tmp == 1) { + node = *rssi_head; + prev = node; + } else { + node = prev->next; + } + continue; + } + prev = node; + node = node->next; + } +} + +void +wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl) +{ + wl_rssi_cache_t *node, **rssi_head; + + rssi_head = &rssi_cache_ctrl->m_cache_head; + + /* reset dirty */ + node = *rssi_head; + for (;node;) { + node->dirty += 1; + node = node->next; + } +} + +int +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; + + if (!g_wifi_on) + return 0; + + error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false); + if (error == BCME_NOTASSOCIATED) { + ANDROID_INFO(("%s: Not Associated! res:%d\n", __FUNCTION__, error)); + return 0; + } + if (error) { + ANDROID_ERROR(("Could not get bssid (%d)\n", error)); + } + error = wldev_get_rssi(net, &rssi); + if (error) { + ANDROID_ERROR(("Could not get rssi (%d)\n", error)); + return error; + } + + do_gettimeofday(&now); + timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; + if (timeout.tv_sec < now.tv_sec) { + /* + * Integer overflow - assume long enough timeout to be assumed + * to be infinite, i.e., the timeout would never happen. + */ + ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", + __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + } + + /* update RSSI */ + rssi_head = &rssi_cache_ctrl->m_cache_head; + node = *rssi_head; + prev = NULL; + for (;node;) { + if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) { + ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n", + __FUNCTION__, k, &bssid, rssi)); + for (j=0; jRSSI[j] = node->RSSI[j+1]; + node->RSSI[j] = rssi; + node->dirty = 0; + node->tv = timeout; + goto exit; + } + prev = node; + node = node->next; + k++; + } + + leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); + if (!leaf) { + ANDROID_ERROR(("%s: Memory alloc failure %d\n", + __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); + return 0; + } + ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n", + __FUNCTION__, k, &bssid, rssi)); + + leaf->next = NULL; + leaf->dirty = 0; + leaf->tv = timeout; + memcpy(&leaf->BSSID, &bssid, ETHER_ADDR_LEN); + for (j=0; jRSSI[j] = rssi; + + if (!prev) + *rssi_head = leaf; + else + prev->next = leaf; + +exit: + *rssi_avg = (int)wl_get_avg_rssi(rssi_cache_ctrl, &bssid); + + return error; +} + +void +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; + int i, j, k; + struct timeval now, timeout; + + if (!ss_list->count) + return; + + do_gettimeofday(&now); + timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT; + if (timeout.tv_sec < now.tv_sec) { + /* + * Integer overflow - assume long enough timeout to be assumed + * to be infinite, i.e., the timeout would never happen. + */ + ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", + __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + } + + rssi_head = &rssi_cache_ctrl->m_cache_head; + + /* update RSSI */ + for (i = 0; i < ss_list->count; i++) { + node = *rssi_head; + prev = NULL; + k = 0; + bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; + for (;node;) { + if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { + ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + for (j=0; jRSSI[j] = node->RSSI[j+1]; + node->RSSI[j] = dtoh16(bi->RSSI); + node->dirty = 0; + node->tv = timeout; + break; + } + prev = node; + node = node->next; + k++; + } + + if (node) + continue; + + leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL); + if (!leaf) { + ANDROID_ERROR(("%s: Memory alloc failure %d\n", + __FUNCTION__, (int)sizeof(wl_rssi_cache_t))); + return; + } + ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n", + __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + + leaf->next = NULL; + leaf->dirty = 0; + leaf->tv = timeout; + memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN); + for (j=0; jRSSI[j] = dtoh16(bi->RSSI); + + if (!prev) + *rssi_head = leaf; + else + prev->next = leaf; + } +} + +int16 +wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr) +{ + wl_rssi_cache_t *node, **rssi_head; + int j, rssi_sum, rssi=RSSI_MINVAL; + + rssi_head = &rssi_cache_ctrl->m_cache_head; + + node = *rssi_head; + for (;node;) { + if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) { + rssi_sum = 0; + rssi = 0; + for (j=0; jRSSI[RSSIAVG_LEN-j-1]; + rssi = rssi_sum / j; + break; + } + node = node->next; + } + rssi = MIN(rssi, RSSI_MAXVAL); + if (rssi == RSSI_MINVAL) { + ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n", + __FUNCTION__, addr)); + } + return (int16)rssi; +} +#endif + +#if defined(RSSIOFFSET) +int +wl_update_rssi_offset(struct net_device *net, int rssi) +{ +#if defined(RSSIOFFSET_NEW) + int j; +#endif + + if (!g_wifi_on) + return rssi; + +#if defined(RSSIOFFSET_NEW) + for (j=0; jm_cache_head; + node = *bss_head; + + for (;node;) { + ANDROID_TRACE(("%s: Free %d with BSSID %pM\n", + __FUNCTION__, i, &node->results.bss_info->BSSID)); + cur = node; + node = cur->next; + kfree(cur); + i++; + } + *bss_head = NULL; +} + +void +wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) +{ + wl_bss_cache_t *node, *prev, **bss_head; + int i = -1, tmp = 0; + struct timeval now; + + do_gettimeofday(&now); + + bss_head = &bss_cache_ctrl->m_cache_head; + node = *bss_head; + prev = node; + for (;node;) { + i++; + if (now.tv_sec > node->tv.tv_sec) { + if (node == *bss_head) { + tmp = 1; + *bss_head = node->next; + } else { + tmp = 0; + prev->next = node->next; + } + ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + __FUNCTION__, i, &node->results.bss_info->BSSID, + dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); + kfree(node); + if (tmp == 1) { + node = *bss_head; + prev = node; + } else { + node = prev->next; + } + continue; + } + prev = node; + node = node->next; + } +} + +void +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; + + bss_head = &bss_cache_ctrl->m_cache_head; + node = *bss_head; + prev = node; + for (;node;) { + i++; + if (!memcmp(&node->results.bss_info->BSSID, bssid, ETHER_ADDR_LEN)) { + if (node == *bss_head) { + tmp = 1; + *bss_head = node->next; + } else { + tmp = 0; + prev->next = node->next; + } + ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + __FUNCTION__, i, &node->results.bss_info->BSSID, + dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID)); + kfree(node); + if (tmp == 1) { + node = *bss_head; + prev = node; + } else { + node = prev->next; + } + continue; + } + prev = node; + node = node->next; + } +} + +void +wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl) +{ + wl_bss_cache_t *node, **bss_head; + + bss_head = &bss_cache_ctrl->m_cache_head; + + /* reset dirty */ + node = *bss_head; + for (;node;) { + node->dirty += 1; + node = node->next; + } +} + +void dump_bss_cache( +#if defined(RSSIAVG) + wl_rssi_cache_ctrl_t *rssi_cache_ctrl, +#endif + wl_bss_cache_t *node) +{ + int k = 0; + int16 rssi; + + for (;node;) { +#if defined(RSSIAVG) + rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); +#else + 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)); + k++; + node = node->next; + } +} + +void +wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, +#if defined(RSSIAVG) + wl_rssi_cache_ctrl_t *rssi_cache_ctrl, +#endif + wl_scan_results_t *ss_list) +{ + wl_bss_cache_t *node, *prev, *leaf, **bss_head; + wl_bss_info_t *bi = NULL; + int i, k=0; +#if defined(SORT_BSS_BY_RSSI) + int16 rssi, rssi_node; +#endif + struct timeval now, timeout; + + if (!ss_list->count) + return; + + do_gettimeofday(&now); + timeout.tv_sec = now.tv_sec + BSSCACHE_TIMEOUT; + if (timeout.tv_sec < now.tv_sec) { + /* + * Integer overflow - assume long enough timeout to be assumed + * to be infinite, i.e., the timeout would never happen. + */ + ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu", + __FUNCTION__, BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec)); + } + + bss_head = &bss_cache_ctrl->m_cache_head; + + for (i=0; i < ss_list->count; i++) { + node = *bss_head; + prev = NULL; + bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; + + for (;node;) { + if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { + if (node == *bss_head) + *bss_head = node->next; + else { + prev->next = node->next; + } + break; + } + prev = node; + node = node->next; + } + + leaf = kmalloc(dtoh32(bi->length) + sizeof(wl_bss_cache_t), GFP_KERNEL); + if (!leaf) { + ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__, + dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t))); + return; + } + if (node) { + kfree(node); + node = NULL; + ANDROID_TRACE(("%s: Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + } else + ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n", + __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID)); + + memcpy(leaf->results.bss_info, bi, dtoh32(bi->length)); + leaf->next = NULL; + leaf->dirty = 0; + leaf->tv = timeout; + leaf->results.count = 1; + leaf->results.version = ss_list->version; + k++; + + if (*bss_head == NULL) + *bss_head = leaf; + else { +#if defined(SORT_BSS_BY_RSSI) + node = *bss_head; +#if defined(RSSIAVG) + rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID); +#else + rssi = dtoh16(leaf->results.bss_info->RSSI); +#endif + for (;node;) { +#if defined(RSSIAVG) + rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID); +#else + rssi_node = dtoh16(node->results.bss_info->RSSI); +#endif + if (rssi > rssi_node) { + leaf->next = node; + if (node == *bss_head) + *bss_head = leaf; + else + prev->next = leaf; + break; + } + prev = node; + node = node->next; + } + if (node == NULL) + prev->next = leaf; +#else + leaf->next = *bss_head; + *bss_head = leaf; +#endif + } + } + dump_bss_cache( +#if defined(RSSIAVG) + rssi_cache_ctrl, +#endif + *bss_head); +} + +void +wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl) +{ + ANDROID_TRACE(("%s:\n", __FUNCTION__)); + wl_free_bss_cache(bss_cache_ctrl); +} +#endif + + diff --git a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c index efadf25..5651601 100644 --- a/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c +++ b/bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c @@ -3774,7 +3774,7 @@ wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg, dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum))); chipnum = revinfo.chipnum; if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) || - (chipnum == BCM4345_CHIP_ID)) { + (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID)) { /* WAR required */ return true; } @@ -11203,6 +11203,9 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev, printf("%s: ** AP/GO Link up event **\n", __FUNCTION__); wl_set_drv_status(cfg, AP_CREATED, ndev); wake_up_interruptible(&cfg->netif_change_event); + if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { + dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1); + } return 0; } } @@ -11857,6 +11860,9 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT); wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID); dhd_conf_set_wme(cfg->pub, 0); + if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) { + dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1); + } } else if (WL_IS_LINKDOWN(cfg, e, data) || ((event == WLC_E_SET_SSID) && (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) && diff --git a/bcmdhd.1.579.77.41.1.cn/wldev_common.c b/bcmdhd.1.579.77.41.1.cn/wldev_common.c index 1b985b0..ebe656f 100644 --- a/bcmdhd.1.579.77.41.1.cn/wldev_common.c +++ b/bcmdhd.1.579.77.41.1.cn/wldev_common.c @@ -495,7 +495,7 @@ int wldev_set_country( cspec.rev = revinfo; memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); - error = dhd_conf_get_country_from_config(dhd_get_pub(dev), &cspec); + error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec, 0); if (error) dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);