diff options
| author | Jan Engelmohr <jan.engelmohr@mailbox.tu-dresden.de> | 2016-08-16 00:02:57 +0200 |
|---|---|---|
| committer | Jan Engelmohr <jan.engelmohr@mailbox.tu-dresden.de> | 2016-08-16 00:02:57 +0200 |
| commit | 27d23ae4b8ba7e4bbd34a06f8c2e17ac8fa535bf (patch) | |
| tree | ddad3e769e79b3222c61bb0f0e208c9993ca378f /MediaTek/lib_driver_cmd_mt66xx | |
set up mt6753 device tree
Diffstat (limited to 'MediaTek/lib_driver_cmd_mt66xx')
| -rw-r--r-- | MediaTek/lib_driver_cmd_mt66xx/Android.mk | 55 | ||||
| -rw-r--r-- | MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_cmd_nl80211.c | 1894 | ||||
| -rw-r--r-- | MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_nl80211.h | 344 |
3 files changed, 2293 insertions, 0 deletions
diff --git a/MediaTek/lib_driver_cmd_mt66xx/Android.mk b/MediaTek/lib_driver_cmd_mt66xx/Android.mk new file mode 100644 index 0000000..e7916e9 --- /dev/null +++ b/MediaTek/lib_driver_cmd_mt66xx/Android.mk @@ -0,0 +1,55 @@ +LOCAL_PATH := $(call my-dir) + +##### For Google SUPPLICANT +ifeq ($(WPA_SUPPLICANT_VERSION),VER_0_8_X) + WPA_SUPPL_DIR = external/wpa_supplicant_8 + WPA_SRC_FILE := + +ifneq ($(BOARD_WPA_SUPPLICANT_DRIVER),) + CONFIG_DRIVER_$(BOARD_WPA_SUPPLICANT_DRIVER) := y +endif +ifneq ($(BOARD_HOSTAPD_DRIVER),) + CONFIG_DRIVER_$(BOARD_HOSTAPD_DRIVER) := y +endif + +include $(WPA_SUPPL_DIR)/wpa_supplicant/android.config + +WPA_SUPPL_DIR_INCLUDE = $(WPA_SUPPL_DIR)/src \ + $(WPA_SUPPL_DIR)/src/common \ + $(WPA_SUPPL_DIR)/src/drivers \ + $(WPA_SUPPL_DIR)/src/l2_packet \ + $(WPA_SUPPL_DIR)/src/utils \ + $(WPA_SUPPL_DIR)/src/wps \ + $(WPA_SUPPL_DIR)/wpa_supplicant + +ifdef CONFIG_DRIVER_NL80211 +WPA_SUPPL_DIR_INCLUDE += external/libnl/include +WPA_SRC_FILE += mediatek_driver_cmd_nl80211.c +endif + +ifdef CONFIG_DRIVER_WEXT +#error doesn't support CONFIG_DRIVER_WEXT +endif + +# To force sizeof(enum) = 4 +ifeq ($(TARGET_ARCH),arm) +L_CFLAGS += -mabi=aapcs-linux +endif + +ifdef CONFIG_ANDROID_LOG +L_CFLAGS += -DCONFIG_ANDROID_LOG +endif + +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE := lib_driver_cmd_mt66xx +LOCAL_SHARED_LIBRARIES := libc libcutils +LOCAL_CFLAGS := $(L_CFLAGS) +LOCAL_SRC_FILES := $(WPA_SRC_FILE) +LOCAL_C_INCLUDES := $(WPA_SUPPL_DIR_INCLUDE) +include $(BUILD_STATIC_LIBRARY) + +######################## + +endif diff --git a/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_cmd_nl80211.c b/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_cmd_nl80211.c new file mode 100644 index 0000000..9b66b1f --- /dev/null +++ b/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_cmd_nl80211.c @@ -0,0 +1,1894 @@ +#include "hardware_legacy/driver_nl80211.h" +#include "mediatek_driver_nl80211.h" +#include "wpa_supplicant_i.h" +#include "config.h" +#include "driver_i.h" + +#ifdef ANDROID +#include "android_drv.h" +#endif + +#ifdef CONFIG_MTK_P2P_SIGMA +#include "p2p/p2p_i.h" +#endif + +typedef struct android_wifi_priv_cmd { + char *buf; + int used_len; + int total_len; +} android_wifi_priv_cmd; + +static int drv_errors = 0; + +static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv) +{ + drv_errors++; + if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) { + drv_errors = 0; + /* avoid the framework to handle HANGED */ + //wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); + } +} + +#ifdef CONFIG_MTK_TURNKEY_WLAN +static int ack_handler(struct nl_msg *msg, void *arg) +{ + int *err = arg; + *err = 0; + return NL_STOP; +} + +static int finish_handler(struct nl_msg *msg, void *arg) +{ + int *ret = arg; + *ret = 0; + return NL_SKIP; +} + +static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, + void *arg) +{ + int *ret = arg; + *ret = err->error; + return NL_SKIP; +} + +static int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, + int (*valid_handler)(struct nl_msg *, void *), + void *valid_data) +{ + struct nl_cb *cb; + struct nl80211_global *global = drv->global; + int err = -ENOMEM; + + cb = nl_cb_clone(global->nl_cb); + if (!cb) + goto out; + + err = nl_send_auto_complete(global->nl, msg); + if (err < 0) + goto out; + + err = 1; + + nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + + if (valid_handler) + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, + valid_handler, valid_data); + + while (err > 0) { + int res = nl_recvmsgs(global->nl, cb); + if (res) { + wpa_printf(MSG_INFO, + "nl80211: %s->nl_recvmsgs failed: %d", + __func__, res); + } + } + out: + nl_cb_put(cb); + nlmsg_free(msg); + return err; +} +#endif + +static int testmode_sta_statistics_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_TESTMODE_STA_STATISTICS_NUM]; + struct wpa_driver_sta_statistics_s *sta_statistics = (struct wpa_driver_sta_statistics_s *)arg; + unsigned char i = 0; + static struct nla_policy policy[NL80211_TESTMODE_STA_STATISTICS_NUM] = { + [NL80211_TESTMODE_STA_STATISTICS_VERSION] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_MAC] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_FLAG] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_PER] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_RSSI] = { .type = NLA_U8 }, + [NL80211_TESTMODE_STA_STATISTICS_PHY_MODE] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TX_RATE] = { .type = NLA_U16 }, + [NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME] = { .type = NLA_U32 }, + [NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY] = { .type = NLA_UNSPEC }, + [NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY] = { .type = NLA_UNSPEC } + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(sinfo, NL80211_TESTMODE_STA_STATISTICS_MAX, tb[NL80211_ATTR_TESTDATA], policy)) + return NL_SKIP; + + for(i=1; i < NL80211_TESTMODE_STA_STATISTICS_NUM; i++) { + if(sinfo[i]) { + switch(i) { + case NL80211_TESTMODE_STA_STATISTICS_VERSION: + sta_statistics->version = nla_get_u8(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_MAC: + nla_memcpy(sta_statistics->addr, sinfo[i], ETH_ALEN); + break; + case NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE: + sta_statistics->link_score = nla_get_u8(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_FLAG: + sta_statistics->flag = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_PER: + sta_statistics->per = nla_get_u8(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_RSSI: + sta_statistics->rssi = (((int)nla_get_u8(sinfo[i]) - 220) / 2); + break; + case NL80211_TESTMODE_STA_STATISTICS_PHY_MODE: + sta_statistics->phy_mode = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TX_RATE: + sta_statistics->tx_rate = (((double)nla_get_u16(sinfo[i])) / 2); + break; + case NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT: + sta_statistics->tx_fail_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT: + sta_statistics->tx_timeout_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME: + sta_statistics->tx_avg_air_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT: + sta_statistics->tx_total_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT: + sta_statistics->tx_exc_threshold_cnt = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME: + sta_statistics->tx_avg_process_time = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY: + nla_memcpy(sta_statistics->tc_buf_full_cnt, sinfo[i], sizeof(sta_statistics->tc_buf_full_cnt)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_que_len, sinfo[i], sizeof(sta_statistics->tc_que_len)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_avg_que_len, sinfo[i], sizeof(sta_statistics->tc_avg_que_len)); + break; + case NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY: + nla_memcpy(sta_statistics->tc_cur_que_len, sinfo[i], sizeof(sta_statistics->tc_cur_que_len)); + break; + case NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY: + nla_memcpy(sta_statistics->reserved, sinfo[i], sizeof(sta_statistics->reserved)); + break; + default: + break; + } + } + } + + return NL_SKIP; +} +#ifdef CONFIG_MEDIATEK_WIFI_BEAM +// Peter: add for Beamplus application +static int testmode_beamplus_go_ready_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_TESTMODE_GO_READY_NUM]; + u32 *go_ready = (u32 *)arg; + unsigned char i = 0; + static struct nla_policy policy[NL80211_TESTMODE_GO_READY_NUM] = { + [NL80211_TESTMODE_GO_READY_STATE] = { .type = NLA_U32 }, + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(sinfo, NL80211_TESTMODE_GO_READY_MAX, tb[NL80211_ATTR_TESTDATA], policy)) + return NL_SKIP; + + for(i=1; i < NL80211_TESTMODE_GO_READY_NUM; i++) { + if(sinfo[i]) { + switch(i) { + case NL80211_TESTMODE_GO_READY_STATE: + *go_ready = nla_get_u32(sinfo[i]); + break; + default: + break; + } + } + } + + return NL_SKIP; +} +// Peter: end of Beamplus application +#endif /*Mediatek Modified*/ +#ifdef CONFIG_MTK_POOR_LINK_DETECT +static int testmode_sta_link_detect_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_TESTMODE_LINK_DETECT_NUM]; + struct wpa_driver_sta_link_detect_s *sta_link_detect = (struct wpa_driver_sta_link_detect_s *)arg; + unsigned char i = 0; + s64 ack_cnt; + static struct nla_policy policy[NL80211_TESTMODE_LINK_DETECT_NUM] = { + [NL80211_TESTMODE_LINK_TX_FAIL_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_TX_RETRY_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_ACK_FAIL_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_FCS_ERR_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_TX_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_TX_OK_CNT] = { .type = NLA_U64 }, + [NL80211_TESTMODE_LINK_TX_OS_CNT] = { .type = NLA_U64 }, + }; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(sinfo, NL80211_TESTMODE_LINK_DETECT_MAX, tb[NL80211_ATTR_TESTDATA], policy)) + return NL_SKIP; + + for(i=1; i < NL80211_TESTMODE_LINK_DETECT_NUM; i++) { + if(sinfo[i]) { + switch(i) { + case NL80211_TESTMODE_LINK_TX_FAIL_CNT: + sta_link_detect->tx_fail_cnt =nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_TX_RETRY_CNT: + sta_link_detect->tx_retry_cnt = nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT: + sta_link_detect->tx_multi_retry_cnt = nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_ACK_FAIL_CNT: + ack_cnt = nla_get_u64(sinfo[i]); + if (ack_cnt < 0) + sta_link_detect->ack_fail_cnt = -ack_cnt; + else + sta_link_detect->ack_fail_cnt = ack_cnt; + break; + case NL80211_TESTMODE_LINK_FCS_ERR_CNT: + sta_link_detect->fcs_err_cnt = nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_TX_CNT: + sta_link_detect->tx_cnt = nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_TX_OK_CNT: + sta_link_detect->tx_ok_cnt = nla_get_u64(sinfo[i]); + break; + case NL80211_TESTMODE_LINK_TX_OS_CNT: + sta_link_detect->tx_os_cnt = nla_get_u64(sinfo[i]); + break; + default: + break; + } + } + } + + return NL_SKIP; +} +#endif +#ifdef CONFIG_MTK_LTE_COEX +static int testmode_available_channel_handler(struct nl_msg *msg, void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + struct nlattr *sinfo[NL80211_TESTMODE_AVAILABLE_CHAN_NUM]; + struct wpa_driver_available_chan_s *available_chan = (struct wpa_driver_available_chan_s *)arg; + static struct nla_policy policy[NL80211_TESTMODE_AVAILABLE_CHAN_NUM] = { + [NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_100] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149] = { .type = NLA_U32 }, + [NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184] = { .type = NLA_U32 }, + }; + unsigned char i = 0; + + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_TESTDATA] || + nla_parse_nested(sinfo, NL80211_TESTMODE_AVAILABLE_CHAN_MAX, tb[NL80211_ATTR_TESTDATA], policy)) + return NL_SKIP; + + for(i=1; i < NL80211_TESTMODE_AVAILABLE_CHAN_NUM; i++) { + if(sinfo[i]) { + switch(i) { + case NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1: + available_chan->ch_2g_base1 =nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34: + available_chan->ch_5g_base34 = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_100: + available_chan->ch_5g_base100 = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149: + available_chan->ch_5g_base149 = nla_get_u32(sinfo[i]); + break; + case NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184: + available_chan->ch_5g_base184 = nla_get_u32(sinfo[i]); + default: + break; + } + } + } + + return NL_SKIP; +} +static void wpa_driver_nl80211_scan_loading_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_driver_nl80211_data *drv = eloop_ctx; + + wpa_printf(MSG_DEBUG, "Scan loading timeout - update channel list"); + wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, + NULL); +} +#endif +static void * nl80211_cmd(struct wpa_driver_nl80211_data *drv, + struct nl_msg *msg, int flags, uint8_t cmd) +{ + return genlmsg_put(msg, 0, 0, drv->global->nl80211_id, + 0, flags, cmd, 0); +} + +int wpa_driver_nl80211_testmode(void *priv, const u8 *data, + size_t data_len) +{ +#ifdef CONFIG_MTK_TURNKEY_WLAN + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg, *cqm = NULL; + struct wpa_driver_testmode_params *params; + int index; + + msg = nlmsg_alloc(); + if (!msg) + return -1; + + wpa_printf(MSG_DEBUG, "nl80211: Test Mode buflen = %d, ifindex=%d", data_len,drv->ifindex); + + nl80211_cmd(drv, msg, 0, NL80211_CMD_TESTMODE); + + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); + NLA_PUT(msg, NL80211_ATTR_TESTDATA, data_len, data); + + params = (struct wpa_driver_testmode_params *)data; + + /* Mask version field */ + index = params->hdr.index & BITS(0, 23); + + switch(index) { + case 0x10: + { + struct wpa_driver_get_sta_statistics_params *sta_params = (struct wpa_driver_get_sta_statistics_params *)data; + + return send_and_recv_msgs(drv, msg, testmode_sta_statistics_handler, sta_params->buf); + } +#ifdef CONFIG_MEDIATEK_WIFI_BEAM + case 0x12: + { + struct wpa_driver_set_beamplus_params *sta_params = (struct wpa_driver_set_beamplus_params *)data; + + return send_and_recv_msgs(drv, msg, testmode_beamplus_go_ready_handler, &sta_params->value); + } +#endif +#ifdef CONFIG_MTK_POOR_LINK_DETECT + case 0x20: + { + struct wpa_driver_get_sta_link_detect_params *sta_params = (struct wpa_driver_get_sta_link_detect_params *)data; + + return send_and_recv_msgs(drv, msg, testmode_sta_link_detect_handler, sta_params->buf); + } +#endif +#ifdef CONFIG_MTK_LTE_COEX + case 0x30: + { + struct wpa_driver_get_available_channel_params *chan_params = (struct wpa_driver_get_available_channel_params *) data; + + return send_and_recv_msgs(drv, msg, testmode_available_channel_handler, chan_params->buf); + } +#endif + default: + { + int ret = 0; + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + wpa_printf(MSG_DEBUG, "ret = %d, nl=%d",ret, drv->global->nl); + return ret; + } + } + + nla_put_failure: + return -ENOBUFS; +#else + return 0; +#endif +} + +static int wpa_driver_nl80211_driver_sw_cmd(void *priv, + int set, u32 *adr, u32 *dat) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct wpa_driver_sw_cmd_params params; + struct nl_msg *msg, *cqm = NULL; + int ret = 0; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = NL80211_TESTMODE_SW_CMD; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_sw_cmd_params); + + params.adr = *adr; + params.data = *dat; + + if(set) + params.set = 1; + else + params.set = 0; + + wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, sizeof(struct wpa_driver_sw_cmd_params)); + return 0; +} + +#ifdef CONFIG_HOTSPOT_MGR_SUPPORT +static int wpa_driver_hotspot_block_list_update(void *priv, + const u8 *bssid, int blocked) + +{ + struct wpa_driver_hotspot_params params; + + os_memset(¶ms, 0, sizeof(params)); + + if(bssid) + os_memcpy(params.bssid, bssid, ETH_ALEN); + + params.blocked = (u8)blocked; + + params.hdr.index = NL80211_TESTMODE_HS20; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_hotspot_params); + + return wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, + sizeof(struct wpa_driver_hotspot_params)); +} + +static int wpa_driver_sta_block(void *priv, char *cmd) +{ + u8 bssid[ETH_ALEN]; + int blocked = 1; + + /* Block client device */ + if (hwaddr_aton(cmd, bssid)) { + wpa_printf(MSG_DEBUG, "STA block: invalid DEVICE ADDRESS '%s'", + cmd); + return -1; + } + + wpa_printf(MSG_DEBUG, "Block STA " MACSTR, MAC2STR(bssid)); + return wpa_driver_hotspot_block_list_update(priv, bssid, blocked); +} + +static int wpa_driver_sta_unblock(void *priv, char *cmd) +{ + u8 bssid[ETH_ALEN]; + int blocked = 0; + + /* Unblock client device */ + if (hwaddr_aton(cmd, bssid)) { + wpa_printf(MSG_DEBUG, "STA unblock : invalid DEVICE ADDRESS '%s'", + cmd); + return -1; + } + + wpa_printf(MSG_DEBUG, "Unblock STA " MACSTR, MAC2STR(bssid)); + return wpa_driver_hotspot_block_list_update(priv, bssid, blocked); +} +#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */ + +#ifdef CONFIG_WAPI_SUPPORT +int wpa_driver_nl80211_set_wapi_key(void *priv, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, + size_t seq_len, + const u8 *key, size_t key_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg, *cqm = NULL; + struct wpa_driver_wapi_key_params params; + int ret = 0; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = NL80211_TESTMODE_WAPI; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_wapi_key_params); + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]1 %s: ", + __FUNCTION__); + + if(seq_len > IW_ENCODE_SEQ_MAX_SIZE * 2){ + wpa_printf(MSG_DEBUG, "[WAPI-Debug]%s: Invalid seq_len %lu", + __FUNCTION__, (unsigned long) seq_len); + return -1; + } + + params.key_index = key_idx + 1; + params.key_len = key_len; + + if (addr == NULL || + os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0) + params.extparams.ext_flags |= IW_ENCODE_EXT_GROUP_KEY; + if (set_tx) + params.extparams.ext_flags |= IW_ENCODE_EXT_SET_TX_KEY; + + if (addr) + os_memcpy(params.extparams.addr, addr, ETH_ALEN); + else + os_memset(params.extparams.addr, 0xff, ETH_ALEN); + + if (key && key_len) { + os_memcpy(params.extparams.key, key, key_len); + params.extparams.key_len = key_len; + } + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]2 %s:",__FUNCTION__); + + wpa_printf(MSG_DEBUG, "%s: Set IW_ENCODE_ALG_SMS4 to ext->alg", + __FUNCTION__); + + params.extparams.alg = IW_ENCODE_ALG_SMS4; + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]3 %s: ",__FUNCTION__); + + if(seq && seq_len) + os_memcpy(params.extparams.tx_seq, seq, seq_len); + + wpa_hexdump(MSG_DEBUG, "seq", seq, seq_len); + + wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]4 Copy buffer %s: ",__FUNCTION__); + + wpa_driver_nl80211_testmode(priv, (u8 *)¶ms, sizeof(struct wpa_driver_wapi_key_params)); + + return 0; +} + +/** + * wpa_driver_nl80211_send_msg - send some information to driver + * @priv: private driver interface data from init() + * @msg_in: the message sent to driver + * @msg_in_len: the length of sent message + * @msg_out: the message given back from driver + * @msg_out_len: the length of message given back from driver + * + * Returns: 0 on success, -1 on failure + * + */ +static int wpa_driver_nl80211_send_msg(void *priv, const u8 *msg_in, int msg_in_len, + u8 *msg_out, int *msg_out_len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int ret = 0; + + if(msg_in_len > 1024){ + wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_send_msg: msg too long"); + return -1; + } + + return ret; +} +#endif /* CONFIG_WAPI_SUPPORT */ +#if defined (CONFIG_MTK_P2P) || defined (CONFIG_MEDIATEK_WIFI_BEAM) +static inline int wpa_drv_set_test_mode(struct wpa_supplicant *wpa_s, + const u8 *buf, size_t buf_len) +{ + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, buf, buf_len); +} +#endif +#ifdef CONFIG_MTK_P2P +int wpas_wfd_data_update(struct wpa_supplicant *wpa_s, + struct wfd_data_s *p_wfd_data) +{ + struct wpa_driver_wfd_data_s params; + os_memset(¶ms, 0, sizeof(params)); + + wpa_printf(MSG_DEBUG, "WFD: wpas_wfd_data_update wfd_en %u wfd_dev_info 0x%x wfd_ctrl_port %u wfd_state 0x%x", + p_wfd_data->WfdEnable, p_wfd_data->WfdDevInfo, p_wfd_data->WfdControlPort, p_wfd_data->WfdState); + + + params.hdr.index = 2; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wfd_data_s); + + params.WfdCmdType = p_wfd_data->WfdCmdType; + params.WfdEnable = p_wfd_data->WfdEnable; + params.WfdCoupleSinkStatus = p_wfd_data->WfdCoupleSinkStatus; + params.WfdDevInfo = p_wfd_data->WfdDevInfo; + params.WfdControlPort = p_wfd_data->WfdControlPort; + params.WfdMaximumTp = p_wfd_data->WfdMaximumTp; + params.WfdExtendCap = p_wfd_data->WfdExtendCap; + os_memcpy(params.WfdCoupleSinkAddress, p_wfd_data->WfdCoupleSinkAddress, ETH_ALEN); + os_memcpy(params.WfdAssociatedBssid, p_wfd_data->WfdAssociatedBssid, ETH_ALEN); + os_memcpy(params.WfdVideoIp, p_wfd_data->WfdVideoIp, sizeof(p_wfd_data->WfdVideoIp)); + os_memcpy(params.WfdAudioIp, p_wfd_data->WfdAudioIp, sizeof(p_wfd_data->WfdAudioIp)); + params.WfdVideoPort = p_wfd_data->WfdVideoPort; + params.WfdAudioPort = p_wfd_data->WfdAudioPort; + params.WfdFlag = p_wfd_data->WfdFlag; + params.WfdPolicy = p_wfd_data->WfdPolicy; + params.WfdState = p_wfd_data->WfdState; + params.WfdSessionInformationIELen = p_wfd_data->WfdSessionInformationIELen; + os_memcpy(params.WfdSessionInformationIE, p_wfd_data->WfdSessionInformationIE, + p_wfd_data->WfdSessionInformationIELen); + os_memcpy(params.WfdPrimarySinkMac, p_wfd_data->WfdPrimarySinkMac, ETH_ALEN); + os_memcpy(params.WfdSecondarySinkMac, p_wfd_data->WfdSecondarySinkMac, ETH_ALEN); + params.WfdAdvancedFlag = p_wfd_data->WfdAdvancedFlag; + + params.WfdSessionAvailable = p_wfd_data->WfdSessionAvailable; + params.WfdSigmaMode = p_wfd_data->WfdSigmaMode; + os_memcpy(params.WfdLocalIp, p_wfd_data->WfdLocalIp, sizeof(p_wfd_data->WfdLocalIp)); + + return wpa_drv_set_test_mode(wpa_s, (u8 *)¶ms, sizeof(struct wpa_driver_wfd_data_s)); + +} + +#endif + +#ifdef CONFIG_MEDIATEK_WIFI_BEAM +u32 wpas_driver_get_beamplus_go_ready(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_set_beamplus_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = 0x12; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_set_beamplus_params); + + params.value = 0; + + wpa_drv_set_test_mode(wpa_s, (u8 *)¶ms, sizeof(struct wpa_driver_set_beamplus_params)); + wpa_printf(MSG_DEBUG, "P2P: Beamplus polling GO ready value = %d",params.value); + return params.value; +} +int wpas_driver_set_beamplus(struct wpa_supplicant *wpa_s, u32 value) +{ + struct wpa_driver_set_beamplus_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = 0x11; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_set_beamplus_params); + + params.value = (u32)value; + + return wpa_drv_set_test_mode(wpa_s, (u8 *)¶ms, + sizeof(struct wpa_driver_set_beamplus_params)); +} +#endif +/************************************************************* +OVERLAPPED functins, previous defination is in driver_nl80211.c, +it will be modified +**************************************************************/ + +/**************************************************************************/ +extern int wpa_config_write(const char *name, struct wpa_config *config); + +static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + int ioctl_sock=-1; + struct iwreq iwr; + int ret=-1; + char buf[11]; + +#ifdef MTK_TC1_FEATURE + char replace_ifname[IFNAMSIZ+1]; + + memset( replace_ifname, 0, IFNAMSIZ+1 ); + os_strlcpy( replace_ifname, "wlan0", os_strlen("wlan0")+1 ); +#endif + + wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_set_country"); + ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctl_sock < 0) { + wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__); + return -1; + } + os_memset(&iwr, 0, sizeof(iwr)); +#ifdef MTK_TC1_FEATURE + // convert 'p2p0' -> 'wlan0' : + // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution. + if( os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0") ) == 0 ) { + wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0"); + os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ ); + } else { + os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); + } +#else + os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ); +#endif + sprintf(buf,"COUNTRY %s",alpha2_arg); + iwr.u.data.pointer = buf; + iwr.u.data.length = strlen(buf); + if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) {//SIOCSIWPRIV + wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s",buf); + close(ioctl_sock); + return ret; + } + else { + close(ioctl_sock); + return 0; + } + +} +/* Move GET_STA_STATISTICS to "DRIVER GET_STA_STATISTICS", implement in 3rd part lib */ +/* [ALPS00618361] [WFD Quality Enhancement] */ +int wpas_get_sta_statistics(struct wpa_supplicant *wpa_s, char *sta_addr, u8 *buf) +{ + struct wpa_driver_get_sta_statistics_params params; + + os_memset(¶ms, 0, sizeof(params)); + + if(sta_addr) + os_memcpy(params.addr, sta_addr, ETH_ALEN); + + wpa_printf(MSG_DEBUG, "get_sta_statistics ["MACSTR"]", MAC2STR(params.addr)); + + params.hdr.index = NL80211_TESTMODE_STATISTICS; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_get_sta_statistics_params); + + /* buffer for return structure */ + params.buf = buf; + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)¶ms, + sizeof(struct wpa_driver_get_sta_statistics_params)); +} + +/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */ +static int print_sta_statistics(struct wpa_supplicant *wpa_s, struct wpa_driver_sta_statistics_s *sta_stats, + unsigned long mask, char *buf, size_t buflen) +{ + size_t i; + int ret; + char *pos, *end; + + pos = buf; + end = buf + buflen; + + ret = os_snprintf(pos, end - pos, "sta_addr="MACSTR"\n", MAC2STR(sta_stats->addr)); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "link_score=%d\n", sta_stats->link_score); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "per=%d\n", sta_stats->per); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "rssi=%d\n", sta_stats->rssi); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "phy=0x%08X\n", sta_stats->phy_mode); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "rate=%.1f\n", sta_stats->tx_rate); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "total_cnt=%d\n", sta_stats->tx_total_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "threshold_cnt=%d\n", sta_stats->tx_exc_threshold_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "fail_cnt=%d\n", sta_stats->tx_fail_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "timeout_cnt=%d\n", sta_stats->tx_timeout_cnt); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "apt=%d\n", sta_stats->tx_avg_process_time); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "aat=%d\n", sta_stats->tx_avg_air_time); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_buf_full_cnt=%d:%d:%d:%d\n", + sta_stats->tc_buf_full_cnt[TC0_INDEX], + sta_stats->tc_buf_full_cnt[TC1_INDEX], + sta_stats->tc_buf_full_cnt[TC2_INDEX], + sta_stats->tc_buf_full_cnt[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_sta_que_len=%d:%d:%d:%d\n", + sta_stats->tc_que_len[TC0_INDEX], + sta_stats->tc_que_len[TC1_INDEX], + sta_stats->tc_que_len[TC2_INDEX], + sta_stats->tc_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_avg_que_len=%d:%d:%d:%d\n", + sta_stats->tc_avg_que_len[TC0_INDEX], + sta_stats->tc_avg_que_len[TC1_INDEX], + sta_stats->tc_avg_que_len[TC2_INDEX], + sta_stats->tc_avg_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "TC_cur_que_len=%d:%d:%d:%d\n", + sta_stats->tc_cur_que_len[TC0_INDEX], + sta_stats->tc_cur_que_len[TC1_INDEX], + sta_stats->tc_cur_que_len[TC2_INDEX], + sta_stats->tc_cur_que_len[TC3_INDEX]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "flag=0x%08X\n", sta_stats->flag); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "reserved0="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + for(i = 0; i < 16; i++) { + ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + if(((i + 1) % 4) == 0) { + ret = os_snprintf(pos, end - pos, " ", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + } + ret = os_snprintf(pos, end - pos, "\n", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "reserved1="); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + for(i = 16; i < 32; i++) { + ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + if(((i + 1) % 4) == 0) { + ret = os_snprintf(pos, end - pos, " ", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + } + } + ret = os_snprintf(pos, end - pos, "\n", sta_stats->reserved[i]); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + ret = os_snprintf(pos, end - pos, "====\n"); + if (ret < 0 || ret >= end - pos) + return 0; + pos += ret; + + return pos - buf; +} + +#ifdef CONFIG_MTK_POOR_LINK_DETECT +int wpas_get_sta_link_detect(struct wpa_supplicant *wpa_s, u8 *buf) +{ + struct wpa_driver_get_sta_link_detect_params params; + + os_memset(¶ms, 0, sizeof(params)); + wpa_printf(MSG_DEBUG, "get_sta_link_detect"); + params.hdr.index = NL80211_TESTMODE_LINK_DETECT; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_get_sta_link_detect_params); + + /* buffer for return structure */ + params.buf = buf; + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)¶ms, + sizeof(struct wpa_driver_get_sta_link_detect_params)); +} +#endif +/* +#ifdef CONFIG_MTK_LTE_COEX +int wpas_get_available_channel(struct wpa_supplicant *wpa_s, u8 *buf) +{ + struct wpa_driver_get_available_channel_params params; + + os_memset(¶ms, 0, sizeof(params)); + wpa_printf(MSG_DEBUG, "wpas_get_available_channel"); + params.hdr.index = 0x30; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_get_available_channel_params); + + // buffer for return structure // + params.buf = buf; + + return wpa_drv_set_test_mode(wpa_s, (u8 *)¶ms, + sizeof(struct wpa_driver_get_available_channel_params)); +} + + +#endif +*/ +/* [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */ +int wpa_driver_get_sta_statistics(struct wpa_supplicant *wpa_s, char *addr, + char *buf, size_t buflen) +{ + char *str = NULL; + int len = 0; + u8 sta_addr[ETH_ALEN]; + + struct wpa_driver_sta_statistics_s sta_statistics; + + + if (hwaddr_aton(addr, sta_addr)) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: invalid " + "address '%s'", addr); + return -1; + } + + if (wpas_get_sta_statistics(wpa_s, sta_addr, (u8 *)&sta_statistics) < 0) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: command failed"); + return -1; + } + len = print_sta_statistics(wpa_s, &sta_statistics, 0x00, buf, buflen); + + return len; + +} + +#ifdef CONFIG_MTK_POOR_LINK_DETECT +static int wpa_driver_get_sta_link_detect(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + int ret; + char *pos, *end; + struct wpa_driver_sta_link_detect_s sta_link_detect; + + //wpa_printf(MSG_DEBUG, "Get sta(%s) statistics", addr); + + pos = buf; + end = buf + buflen; + if (wpas_get_sta_link_detect(wpa_s, (u8 *)&sta_link_detect) < 0) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_LINK_DETECT: command failed"); + return -1; + } + + ret = os_snprintf(pos, end - pos, "rFailedCount=%llu\n", sta_link_detect.tx_fail_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "rRetryCount=%llu\n", sta_link_detect.tx_retry_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "rMultipleRetryCount=%llu\n", sta_link_detect.tx_multi_retry_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + ret = os_snprintf(pos, end - pos, "rACKFailureCount=%llu\n", sta_link_detect.ack_fail_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "rFCSErrorCount=%llu\n", sta_link_detect.fcs_err_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "tx_total=%llu\n", sta_link_detect.tx_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "tx_ok=%llu\n", sta_link_detect.tx_ok_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + ret = os_snprintf(pos, end - pos, "tx_os=%llu\n", sta_link_detect.tx_os_cnt); + if (ret < 0 || ret >= end - pos) + return (pos - buf); + pos += ret; + + return (pos - buf); + +} +#endif + +#ifdef CONFIG_MTK_P2P_SIGMA +static int wpas_p2p_sigma_test_mode(struct wpa_supplicant *wpa_s, + int index, int value) +{ + struct wpa_driver_p2p_sigma_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.hdr.index = 1; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params); + + params.idx = (u32)index; + params.value = (u32)value; + + return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)¶ms, + sizeof(struct wpa_driver_p2p_sigma_params)); +} +static int p2p_ctrl_iface_set_opps( + struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int len = 0; + size_t ssid_len = 0; + char *ssid; + int CTWin; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps cmd=%s\n", cmd); + + CTWin = atoi(cmd); + + str = os_strchr(cmd, ' '); + *str ++ = '\0'; + + if (hwaddr_aton(str, addr)) + return -1; + + str = os_strchr(str, ' '); + *str ++ = '\0'; + + ssid = wpa_config_parse_string(str, &ssid_len); + if (ssid) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%d)%s\n", + CTWin, MAC2STR(addr), ssid_len, ssid); + os_free(ssid); + } + else { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%d)\n", + CTWin, MAC2STR(addr), ssid_len); + } + + wpas_p2p_sigma_test_mode(wpa_s, 107, (int)CTWin); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; + +} +static int p2p_ctrl_iface_set_power_save( + struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + int len = 0; + int value = 0; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save cmd=%s\n", cmd); + + value = atoi(cmd); + + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save value=%d\n", value); + + wpas_p2p_sigma_test_mode(wpa_s, 108, (int)value); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; + +} +static int p2p_ctrl_iface_set_sleep( + struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) +{ + char *str = NULL; + u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + int len = 0; + size_t ssid_len = 0; + char *ssid; + + if (hwaddr_aton(cmd, addr)) + return -1; + + str = os_strchr(cmd, ' '); + *str ++ = '\0'; + + ssid = wpa_config_parse_string(str, &ssid_len); + if (ssid) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%d)%s\n", + MAC2STR(addr), ssid_len, ssid); + os_free(ssid); + } + else { + wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%d)\n", + MAC2STR(addr), ssid_len); + } + + wpas_p2p_sigma_test_mode(wpa_s, 106, 0); + + //len = os_snprintf(buf, buflen, "return OK"); + + return len; + +} +#endif +#ifdef CONFIG_MTK_WFD_SINK +static int p2p_get_capability(struct wpa_supplicant *wpa_s, + char *cmd, char *buf, size_t buflen) +{ + int ret = 0; + struct p2p_data *p2p = wpa_s->global->p2p; + wpa_printf(MSG_DEBUG, "%s %d, %d", __func__, __LINE__, p2p->dev_capab); + if (os_strncmp(cmd, "p2p_dev_capa", os_strlen("p2p_dev_capa")) == 0) { + ret = snprintf(buf, buflen, "p2p_dev_capa=%d\n", p2p->dev_capab); + wpa_printf(MSG_DEBUG, "%s %d %d, %s", __func__, __LINE__, p2p->dev_capab, buf); + } else if (os_strncmp(cmd, "p2p_group_capa", + os_strlen("p2p_group_capa")) == 0){ + wpa_printf(MSG_DEBUG, "%s not implement", __func__); + ret = -1; + } + return ret; +} + +static int p2p_set_capability(struct wpa_supplicant *wpa_s, + char *cmd, char *buf, size_t buflen) +{ + int ret = 0; + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + struct p2p_data *p2p = wpa_s->global->p2p; + if (os_strncmp(cmd, "p2p_dev_capa ", os_strlen("p2p_dev_capa ")) == 0){ + int old_cap = p2p->dev_capab; + int dev_cap = atoi(cmd + os_strlen("p2p_dev_capa ")); + p2p->dev_capab = dev_cap & 0xff; + wpa_printf(MSG_DEBUG, "%s %d %d, %d", __func__, __LINE__, p2p->dev_capab, + old_cap); + } else if (os_strncmp(cmd, "p2p_group_capa ", + os_strlen("p2p_group_capa ")) == 0){ + wpa_printf(MSG_DEBUG, "%s group not implement", __func__); + ret = -1; + } + return ret; +} + +/** + * priv_p2p_freq_to_channel - Convert frequency into channel info + * @op_class: Buffer for returning operating class + * @channel: Buffer for returning channel number + * Returns: 0 on success, -1 if the specified frequency is unknown + */ +static int priv_p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel) +{ + /* TODO: more operating classes */ + if (freq >= 2412 && freq <= 2472) { + if ((freq - 2407) % 5) + return -1; + + *op_class = 81; /* 2.407 GHz, channels 1..13 */ + *channel = (freq - 2407) / 5; + return 0; + } + + if (freq == 2484) { + *op_class = 82; /* channel 14 */ + *channel = 14; + return 0; + } + + if (freq >= 5180 && freq <= 5240) { + if ((freq - 5000) % 5) + return -1; + + *op_class = 115; /* 5 GHz, channels 36..48 */ + *channel = (freq - 5000) / 5; + return 0; + } +#ifdef CONFIG_MTK_P2P_5G + if (freq >= 5260 && freq <= 5320) { + *op_class = 118; /* 5 GHz, channels 52..64 */ + *channel = (freq - 5000) / 5; + return 0; + } + + if (freq >= 5500 && freq <= 5700) { + *op_class = 121; /* 5 GHz, channels 100..140 */ + *channel = (freq - 5000) / 5; + return 0; + } +#endif + if (freq >= 5745 && freq <= 5805) { + if ((freq - 5000) % 5) + return -1; + + *op_class = 124; /* 5 GHz, channels 149..161 */ + *channel = (freq - 5000) / 5; + return 0; + } +#ifdef CONFIG_MTK_P2P_5G + if (freq >= 5825 && freq <= 5845) { + *op_class = 125; /* 5 GHz, channels 149,153,157,161,165,169 */ + *channel = (freq - 5000) / 5; + return 0; + } +#endif + return -1; +} +static int p2p_wfd_sink_config_scc(struct wpa_supplicant *wpa_s, int scc, unsigned int oper_freq) +{ + int ret = 0; + u8 op_reg_class, op_channel; + unsigned int r; + struct wpa_supplicant *iface; + struct p2p_data *p2p = wpa_s->global->p2p; + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + if (!p2p) { + wpa_printf(MSG_DEBUG, "Not support p2p."); + return ret; + } + if (scc && oper_freq) { + priv_p2p_freq_to_channel(oper_freq, &op_reg_class, &op_channel); + p2p->op_channel = op_channel; + p2p->op_reg_class = op_reg_class; + p2p->channels.reg_classes = 1; + p2p->channels.reg_class[0].channels = 1; + p2p->channels.reg_class[0].reg_class = op_reg_class; + p2p->channels.reg_class[0].channel[0] = op_channel; + wpa_printf(MSG_DEBUG, "Enable SCC in WFD sink mode class %d, channel %d", + op_reg_class, op_channel); + return ret; + } + /* Get back to MCC */ + wpa_printf(MSG_DEBUG, "Config MCC"); + if (wpa_s->conf->p2p_oper_reg_class && + wpa_s->conf->p2p_oper_channel) { + p2p->op_reg_class = wpa_s->conf->p2p_oper_reg_class; + p2p->op_channel = wpa_s->conf->p2p_oper_channel; + p2p->cfg->cfg_op_channel = 1; + } else { + p2p->op_reg_class = 81; + os_get_random((u8 *)&r, sizeof(r)); + p2p->op_channel = 1 + (r % 3) * 5; + p2p->cfg->cfg_op_channel = 0; + } + os_memcpy(&p2p->channels, &p2p->cfg->channels, + sizeof(struct p2p_channels)); + return ret; +} +#endif +int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf, + size_t buf_len ) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct ifreq ifr; + android_wifi_priv_cmd priv_cmd; + struct wpa_supplicant *wpa_s; + struct hostapd_data *hapd; + int ret = -1; + int handled = 0; + union wpa_event_data event; + + if (drv == NULL) { + wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__); + return -1; + } + if (drv->ctx == NULL) { + wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__); + return -1; + } + + if (os_strcmp(bss->ifname, "ap0") == 0) { + hapd = (struct hostapd_data *)(drv->ctx); + } + else { + wpa_s = (struct wpa_supplicant *)(drv->ctx); + if (wpa_s->conf == NULL) { + wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__); + return -1; + } + } + + wpa_printf(MSG_DEBUG, "iface %s recv cmd %s", bss->ifname, cmd); + handled = 1; + + if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) { + int state; + state = atoi(cmd + 10); + wpa_printf(MSG_DEBUG, "POWERMODE=%d", state); + } else if (os_strncasecmp(cmd, "GET_STA_STATISTICS ", 19) == 0) { + ret = wpa_driver_get_sta_statistics(wpa_s, cmd + 19, buf, buf_len); +#ifdef CONFIG_MTK_POOR_LINK_DETECT + } else if (os_strncasecmp(cmd, "GET_STA_LINK_DETECT", 19) == 0) { + ret = wpa_driver_get_sta_link_detect(wpa_s, buf, buf_len); +#endif + } else if (os_strncmp(cmd, "MACADDR", os_strlen("MACADDR"))==0) { + u8 macaddr[ETH_ALEN] = {}; + os_memcpy(&macaddr, wpa_s->own_addr, ETH_ALEN); + ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr)); + wpa_printf(MSG_DEBUG, "%s", buf); + } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY"))==0) { + wpa_printf(MSG_INFO, "set country: %s", cmd+8); + //ret = wpa_drv_set_country(wpa_s, cmd+8); + ret = wpa_driver_mediatek_set_country(priv, cmd+8); + if(ret == 0) { + //os_memcpy(wpa_s->conf->country,cmd+8,2); + //ret = wpa_config_write(wpa_s->confname, wpa_s->conf); + #if 0 + os_memset(&event, 0, sizeof(event)); + event.channel_list_changed.initiator = REGDOM_SET_BY_USER; + event.channel_list_changed.type = REGDOM_TYPE_COUNTRY; + event.channel_list_changed.alpha2[0]= cmd[8]; + event.channel_list_changed.alpha2[1]= cmd[9]; + wpa_printf(MSG_INFO, "send EVENT_CHANNEL_LIST_CHANGED event to supplicant\n"); + wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &event); + #endif + } + } else if (os_strcasecmp(cmd, "start") == 0) { + if (ret = linux_set_iface_flags(drv->global->ioctl_sock, + drv->first_bss->ifname, 1)) { + wpa_printf(MSG_INFO, "nl80211: Could not set interface UP, ret=%d \n", ret); + } else { + wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STARTED"); + } + } else if (os_strcasecmp(cmd, "stop") == 0) { + if (drv->associated) { + ret = wpa_drv_deauthenticate(wpa_s, drv->bssid, WLAN_REASON_DEAUTH_LEAVING); + if (ret != 0) + wpa_printf(MSG_DEBUG,"DRIVER-STOP error, ret=%d", ret); + } else { + wpa_printf(MSG_INFO, "nl80211: not associated, no need to deauthenticate \n"); + } + + if (ret = linux_set_iface_flags(drv->global->ioctl_sock, + drv->first_bss->ifname, 0)) { + wpa_printf(MSG_INFO, "nl80211: Could not set interface Down, ret=%d \n", ret); + } else { + wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STOPPED"); + } + } else if (os_strncasecmp(cmd, "getpower", 8) == 0) { + u32 mode; +// ret = wpa_driver_wext_driver_get_power(drv, &mode); + if (ret == 0) { + ret = snprintf(buf, buf_len, "powermode = %u\n", mode); + wpa_printf(MSG_DEBUG, "%s", buf); + if (ret < (int)buf_len) { + return( ret ); + } + } + } else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) { + u32 thd; +// ret = wpa_driver_wext_driver_get_rts(drv, &thd); + if (ret == 0) { + ret = snprintf(buf, buf_len, "rts-threshold = %u\n", thd); + wpa_printf(MSG_DEBUG, "%s", buf); + if (ret < (int)buf_len) + return ret; + } + } else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) { + u32 thd = 0; + char *cp = cmd + 17; + char *endp; + if (*cp != '\0') { + thd = (u32)strtol(cp, &endp, 0); +// if (endp != cp) +// ret = wpa_driver_wext_driver_set_rts(drv, thd); + } + } else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0; + char *cp = cmd + 12; + char *endp; + + if (*cp != '\0') { + idx = (u32)strtol(cp, &endp, 0); + if (endp != cp) { + idx += 0x00900200; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } + } + } else if (os_strncasecmp(cmd, "rxfilter-remove", 15) == 0 ) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0; + char *cp = cmd + 15; + char *endp; + + if (*cp != '\0') { + idx = (u32)strtol(cp, &endp, 0); + if (endp != cp) { + idx += 0x00900300; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } + } + } else if (os_strncasecmp(cmd, "rxfilter-stop", 13) == 0 ) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0x00900000; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } else if (os_strncasecmp(cmd, "rxfilter-start", 14) == 0 ) { + u32 sw_cmd = 0x9F000000; + u32 idx = 0x00900100; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) { + ret = 0; /* mt5921 linux driver not implement yet */ + } else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) { + ret = 0; /* mt5921 linux driver not implement yet */ + } else if( os_strncasecmp(cmd, "btcoexmode", 10) == 0 ) { + ret = 0; /* mt5921 linux driver not implement yet */ + } else if (os_strncasecmp(cmd, "smt-rate", 8) == 0 ) { + u32 sw_cmd = 0xFFFF0123; + u32 idx = 0; + char *cp = cmd + 8; + char *endp; + + if (*cp != '\0') { + idx = (u32)strtol(cp, &endp, 0); + if (endp != cp) { + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } + } + } else if (os_strncasecmp(cmd, "smt-test-on", 11) == 0 ) { + u32 sw_cmd = 0xFFFF1234; + u32 idx = 0; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } else if (os_strncasecmp(cmd, "smt-test-off", 12) == 0 ) { + u32 sw_cmd = 0xFFFF1235; + u32 idx = 0; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; +#ifdef CONFIG_HOTSPOT_MGR_SUPPORT + } else if (os_strncmp(cmd, "STA-BLOCK ", 10) == 0) { + if (wpa_driver_sta_block(priv, cmd + 10)) { + ret = -1; + } else { + ret = 0; + } + } else if (os_strncmp(cmd, "STA-UNBLOCK ", 12) == 0) { + if (wpa_driver_sta_unblock(priv, cmd + 12)) { + ret = -1; + } else { + ret = 0; + } +#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */ +#ifdef CONFIG_WAPI_SUPPORT + } else if (os_strncasecmp(cmd, "set-wapi-key", 12) == 0) { + struct wapi_key_param_type{ + u8 *addr; + int key_idx; + int set_tx; + u8 *seq; + size_t seq_len; + u8 *key; + size_t key_len; + } *wapi_key_param; + wapi_key_param = (struct wapi_key_param_type*)buf; + + ret = wpa_driver_nl80211_set_wapi_key(priv, + (const u8*)wapi_key_param->addr, + wapi_key_param->key_idx, wapi_key_param->set_tx, + (const u8*)wapi_key_param->seq, wapi_key_param->seq_len, + (const u8*)wapi_key_param->key, wapi_key_param->key_len); + } else if (os_strncasecmp(cmd, "wapi-msg-send", 13) == 0) { + struct wapi_msg_send_param_type { + u8 *msg_in; + int msg_in_len; + u8 *msg_out; + int *msg_out_len; + } *wapi_msg_send_param; + wapi_msg_send_param = (struct wapi_msg_send_param_type*)buf; + ret = wpa_driver_nl80211_send_msg(priv, (const u8*)wapi_msg_send_param->msg_in, + wapi_msg_send_param->msg_in_len, wapi_msg_send_param->msg_out, + wapi_msg_send_param->msg_out_len); +#endif /* CONFIG_WAPI_SUPPORT */ +#ifdef CONFIG_MTK_WFD_SINK + } else if (os_strncmp(cmd, "p2p_get_cap ", os_strlen("p2p_get_cap ")) == 0) { + struct p2p_data *p2p = wpa_s->global->p2p; + if (p2p) { + wpa_printf(MSG_DEBUG, "%s %d, %d ", + __func__, __LINE__, p2p->dev_capab); + ret = p2p_get_capability(wpa_s, cmd + os_strlen("p2p_get_cap "), + buf, buf_len); + } + } else if (os_strncmp(cmd, "p2p_set_cap ", os_strlen("p2p_set_cap ")) == 0) { + struct p2p_data *p2p = wpa_s->global->p2p; + if (p2p) { + wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__); + ret = p2p_set_capability(wpa_s, cmd + os_strlen("p2p_set_cap "), + buf, buf_len); + } + } else if (os_strncmp(cmd, "MIRACAST ", os_strlen("MIRACAST ")) == 0) { + unsigned char miracast = atoi(cmd + os_strlen("MIRACAST ")); + char *pos = os_strstr(cmd, " freq="); + unsigned int freq = 0; + wpa_printf(MSG_DEBUG, "MIRACAST %d", miracast); + switch (miracast) { + case 0: + case 1: + freq = wpa_drv_shared_freq(wpa_s); + if (freq > 0) { + wpa_printf(MSG_DEBUG, "AIS connected %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + break; + case 2: + if (pos) { + pos += 6; + freq = atoi(pos); + wpa_printf(MSG_DEBUG, "MIRACAST freq %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + /* rebuild DRIVER MIRACAST 2 cmd */ + os_memset(cmd, 0, os_strlen(cmd)); + os_memcpy(cmd, "MIRACAST 2", os_strlen("MIRACAST 2")); + } else { + freq = wpa_drv_shared_freq(wpa_s); + if (freq > 0) { + wpa_printf(MSG_DEBUG, "AIS connected %d", freq); + p2p_wfd_sink_config_scc(wpa_s, 1, freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } + + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + + break; + default: + wpa_printf(MSG_DEBUG, "Unknown MIRACAST value %d", miracast); + handled = 0; /* DRIVER MIRACAST used as private cmd*/ + break; + } + +#endif +#ifdef CONFIG_MTK_SCC_MCC + } else if (os_strncasecmp(cmd, "p2p_use_mcc=", os_strlen("p2p_use_mcc=")) == 0) { + unsigned char use_mcc = atoi(cmd + os_strlen("p2p_use_mcc=")); + wpa_printf(MSG_DEBUG, "p2p_use_mcc %d", use_mcc); + wpa_s->global->p2p->p2p_use_mcc = use_mcc; + if (use_mcc) { + wpa_printf(MSG_DEBUG, "SCC_MCC, config MCC"); + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } else { + int shared_freq = wpa_drv_shared_freq(wpa_s); + wpa_printf(MSG_DEBUG, "use_mcc=0"); + shared_freq = wpa_drv_shared_freq(wpa_s); + if (shared_freq > 0) { + wpa_printf(MSG_DEBUG, "p2p disconnected, AIS connected %d", shared_freq); + p2p_wfd_sink_config_scc(wpa_s, 1, shared_freq); + } else + p2p_wfd_sink_config_scc(wpa_s, 0, 0); + } +#endif +#ifdef CONFIG_MTK_P2P_SIGMA + } else if (os_strncasecmp(cmd, "mcc", 3) == 0) { + if(wpa_s->drv_priv) { + int mcc = 0; + char *value = NULL; + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + struct wpa_supplicant *_wpa_s; + mcc = atoi(value); + if(mcc) { + + for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) { + _wpa_s->num_multichan_concurrent = 2; /* 2 is appropriate? just legacy wifi vs p2p wifi? */ + _wpa_s->drv_flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT; + if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg ) { + _wpa_s->global->p2p->cfg->concurrent_operations = 1; + } + } + } else { + + for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) { + _wpa_s->num_multichan_concurrent = 0; /* assign as 0 beacause our driver will + not report iface_combination to supplicant*/ + _wpa_s->drv_flags &= ~WPA_DRIVER_FLAGS_P2P_CONCURRENT; + if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg ) { + _wpa_s->global->p2p->cfg->concurrent_operations = 0; + } + } + + } + + wpa_printf(MSG_DEBUG, "mcc = %d wpa_s drv_flags 0x%x",mcc, wpa_s->drv_flags); + ret = 0; + } + } else if (os_strncmp(cmd, "p2p_set_opps ", 13) == 0) { + ret = p2p_ctrl_iface_set_opps(wpa_s, cmd + 13, + buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_power_save ", 19) == 0) { + ret = p2p_ctrl_iface_set_power_save(wpa_s, cmd + 19, + buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_sleep ", 14) == 0) { + ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd + 14, + buf, buf_len); + } else if (os_strncmp(cmd, "p2p_set_sleep", 13) == 0) { + char cmd2[] = {"ff:ff:ff:ff:ff:ff \"\""}; + ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd2, + buf, buf_len); + /* cmd used to on/off p2p scan results cache to file when do wfd sigma */ + } else if (os_strncmp(cmd, "set_p2p_scan_cache ", + os_strlen("set_p2p_scan_cache ")) == 0) { +#define P2P_CACHE_FILE "/data/misc/wifi/p2p_devices.cache" + int fd; + int onoff = atoi(cmd + 19); + wpa_printf(MSG_DEBUG, "p2p scan res cache on/off: %d", onoff); + if (onoff) { + /* create file: /data/misc/wifi/p2p_devices.cache to store the p2p scan res */ + wpa_printf(MSG_DEBUG, "Create file: p2p_devices.cache"); + fd = open(P2P_CACHE_FILE, O_CREAT|O_RDWR, 0660); + if (fd < 0) + wpa_printf(MSG_DEBUG, "Failed to create p2p_devices.cache"); + else { + close(fd); + wpa_s->p2p_scan_res_cache = 1; + } + } else { + /* delete file: /data/misc/wifi/p2p_devices.caches */ + wpa_printf(MSG_DEBUG, "remove file %s", P2P_CACHE_FILE); + if (remove(P2P_CACHE_FILE)) { + wpa_printf(MSG_DEBUG, "Failed to remove %s", P2P_CACHE_FILE); + } + wpa_s->p2p_scan_res_cache = 0; + } + ret = 0; +#endif +#ifdef CONFIG_MTK_P2P + } else if (os_strncmp(cmd, "wfd_data_update", os_strlen("wfd_data_update")) == 0) { + wpa_printf(MSG_DEBUG, "CONFIG_MTK_P2P: Update wfd_data"); + ret = wpas_wfd_data_update(wpa_s, (struct wfd_data_s *)buf); +#endif +#ifdef CONFIG_MEDIATEK_WIFI_BEAM + } else if (os_strncmp(cmd, "get_beamplus_go_ready", + os_strlen("get_beamplus_go_ready")) == 0) { + if (buf) { + *(int *)buf = wpas_driver_get_beamplus_go_ready(wpa_s); + wpa_printf(MSG_DEBUG, "wpas_driver_get_beamplus_go_ready %d", *(int *)buf); + } + } else if (os_strncmp(cmd, "set_beamplus", + os_strlen("set_beamplus")) == 0) { + if (buf) { + int value = *(int *)buf; + wpa_printf(MSG_DEBUG, "wpas_driver_set_beamplus %d", value); + wpas_driver_set_beamplus(wpa_s, value); + } +#endif + } +#ifdef CONFIG_MTK_STAGE_SCAN + /* use driver command */ + else if (os_strncasecmp(cmd, "set_band_dual", 13) == 0 ) { + u32 sw_cmd = 0xFFFF1250; + u32 idx = 0; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] Set Band = DUAL (sw_cmd: 0x%08X)", sw_cmd); + ret = 0; + } else if (os_strncasecmp(cmd, "set_band_2g4", 12) == 0 ) { + u32 sw_cmd = 0xFFFF1251; + u32 idx = 0; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] Set Band = 2G4 (sw_cmd: 0x%08X)", sw_cmd); + ret = 0; + } else if (os_strncasecmp(cmd, "set_band_5g", 11) == 0 ) { + u32 sw_cmd = 0xFFFF1252; + u32 idx = 0; + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] Set Band = 5G (sw_cmd: 0x%08X)", sw_cmd); + ret = 0; + } +#if 0 + else if (os_strncasecmp(cmd, "SETBAND", 7) == 0 ) { + u32 sw_cmd = 0xFFFF1250; + u32 idx = 0; + char *value; + int band = 0; + + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + + band = atoi(value); + switch(band) { + case 1: + sw_cmd = 0xFFFF1252; + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] WIFI_FREQUENCY_BAND_5GHZ (sw_cmd: 0x%08X)", sw_cmd); + break; + case 2: + sw_cmd = 0xFFFF1251; + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] WIFI_FREQUENCY_BAND_2GHZ (sw_cmd: 0x%08X)", sw_cmd); + break; + default: + sw_cmd = 0xFFFF1250; + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] WIFI_FREQUENCY_BAND_AUTO (sw_cmd: 0x%08X)", sw_cmd); + } + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + ret = 0; + } +#endif + else if (os_strncasecmp(cmd, "set_scan_loading", 16) == 0 ) { + u32 sw_cmd = 0xFFFF1253; + u32 idx = 0; + + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] Set scan loading"); + wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx); + + wpa_printf(MSG_DEBUG, "[STAGE_SCAN] Scan loading timeout= 1 second"); + eloop_cancel_timeout(wpa_driver_nl80211_scan_loading_timeout, drv, drv->ctx); + eloop_register_timeout(10, 0, wpa_driver_nl80211_scan_loading_timeout, + drv, drv->ctx); + ret = 0; + } +#endif + else if (os_strncasecmp(cmd, "SETSUSPENDMODE ", 15) == 0) { + struct wpa_driver_suspendmode_params params; + params.hdr.index = NL80211_TESTMODE_SUSPEND; + params.hdr.index = params.hdr.index | (0x01 << 24); + params.hdr.buflen = sizeof(params); + params.suspend = *(cmd+15)-'0'; + wpa_driver_nl80211_testmode(priv, ¶ms, sizeof(params)); + handled = 0; /* 6630 driver handled this command in driver, so give a chance to 6630 driver */ + } + else { + handled = 0; + wpa_printf(MSG_INFO,"Unsupported command"); + } + + if(handled == 0) { + + os_memcpy(buf, cmd, strlen(cmd) + 1); + memset(&ifr, 0, sizeof(ifr)); + memset(&priv_cmd, 0, sizeof(priv_cmd)); + strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ); + + priv_cmd.buf = buf; + priv_cmd.used_len = buf_len; + priv_cmd.total_len = buf_len; + ifr.ifr_data = &priv_cmd; + + if ((ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr)) < 0) { + wpa_printf(MSG_ERROR, "%s: failed to issue private commands\n", __func__); + wpa_driver_send_hang_msg(drv); + } else { + + wpa_printf(MSG_DEBUG, "%s: ret = %d used = %u total = %u", + __func__, ret , priv_cmd.used_len, priv_cmd.total_len); + + drv_errors = 0; + ret = 0; + ret = priv_cmd.used_len; + if ((os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0)) + ret = strlen(buf); + /* There no need to call wpa_supplicant_event func on which the cmd is SETBAND */ + if (os_strncasecmp(cmd, "SETBAND", 7) == 0) { + // wpa_supplicant_event(drv->ctx, + // EVENT_CHANNEL_LIST_CHANGED, NULL); + wpa_printf(MSG_INFO, "%s: Unsupported command SETBAND\n",__func__); + } + wpa_printf(MSG_INFO, "%s: buf = %s ret = %d used = %u total = %u", + __func__, buf, ret , priv_cmd.used_len, priv_cmd.total_len); + } + } /* handled == 0 */ + + return ret; +} + +int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d, ignored", bss->ifname, count, start, duration); + return -1; +} + +int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "iface %s P2P_GET_NOA, ignored", bss->ifname); + return -1; +} + +int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS, ignored", bss->ifname); + return -1; +} + +int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon, + const struct wpabuf *proberesp, + const struct wpabuf *assocresp) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, "iface %s set_ap_wps_p2p_ie, ignored", bss->ifname); + return 0; +} + diff --git a/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_nl80211.h b/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_nl80211.h new file mode 100644 index 0000000..39f2e18 --- /dev/null +++ b/MediaTek/lib_driver_cmd_mt66xx/mediatek_driver_nl80211.h @@ -0,0 +1,344 @@ +#ifndef _MTK_DRIVER_NL80211_H_ +#define _MTK_DRIVER_NL80211_H_ + +#ifndef BITS +/* Eddie */ +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + +struct iw_point +{ + void __user *pointer; /* Pointer to the data (in user space) */ + __u16 length; /* number of fields or size in bytes */ + __u16 flags; /* Optional params */ +}; +struct iw_param +{ + __s32 value; /* The value of the parameter itself */ + __u8 fixed; /* Hardware should not use auto select */ + __u8 disabled; /* Disable the feature */ + __u16 flags; /* Various specifc flags (if any) */ +}; +struct iw_freq +{ + __s32 m; /* Mantissa */ + __s16 e; /* Exponent */ + __u8 i; /* List index (when in range struct) */ + __u8 flags; /* Flags (fixed/auto) */ +}; +struct iw_quality +{ + __u8 qual; /* link quality (%retries, SNR, + %missed beacons or better...) */ + __u8 level; /* signal level (dBm) */ + __u8 noise; /* noise level (dBm) */ + __u8 updated; /* Flags to know if updated */ +}; + +union iwreq_data +{ + /* Config - generic */ + char name[IFNAMSIZ]; + /* Name : used to verify the presence of wireless extensions. + * Name of the protocol/provider... */ + + struct iw_point essid; /* Extended network name */ + struct iw_param nwid; /* network id (or domain - the cell) */ + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_param sens; /* signal level threshold */ + struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ + struct iw_param rts; /* RTS threshold threshold */ + struct iw_param frag; /* Fragmentation threshold */ + __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ + + struct iw_point encoding; /* Encoding stuff : tokens */ + struct iw_param power; /* PM duration/timeout */ + struct iw_quality qual; /* Quality part of statistics */ + + struct sockaddr ap_addr; /* Access point address */ + struct sockaddr addr; /* Destination address (hw/mac) */ + + struct iw_param param; /* Other small parameters */ + struct iw_point data; /* Other large parameters */ +}; +struct iwreq +{ + union + { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ + } ifr_ifrn; + + /* Data part (defined just above) */ + union iwreq_data u; +}; + +enum nl80211_testmode_sta_link_statistics_attr{ + __NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM, + NL80211_TESTMODE_STA_STATISTICS_MAX = NL80211_TESTMODE_STA_STATISTICS_NUM - 1 +}; + +enum nl80211_testmode_link_detect_attr{ + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + NL80211_TESTMODE_LINK_TX_CNT, + NL80211_TESTMODE_LINK_TX_OK_CNT, + NL80211_TESTMODE_LINK_TX_OS_CNT, + + NL80211_TESTMODE_LINK_DETECT_NUM, + NL80211_TESTMODE_LINK_DETECT_MAX = NL80211_TESTMODE_LINK_DETECT_NUM - 1 +}; + +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + TC0_INDEX = 0, + TC1_INDEX, + TC2_INDEX, + TC3_INDEX, + TC_DATA_NUM, + TC4_INDEX = TC_DATA_NUM, + TC5_INDEX, + TC_NUM +} ENUM_TRAFFIC_CLASS_INDEX_T; + +struct wpa_driver_sta_statistics_s { + u8 version; + u8 addr[ETH_ALEN]; + u32 flag; + + u8 link_score; + u8 per; + int rssi; + u32 phy_mode; + double tx_rate; + + u32 tx_total_cnt; + u32 tx_exc_threshold_cnt; + u32 tx_avg_process_time; + u32 tx_fail_cnt; + u32 tx_timeout_cnt; + u32 tx_avg_air_time; + + u32 tc_buf_full_cnt[TC_DATA_NUM]; + u32 tc_que_len[TC_DATA_NUM]; + + u32 tc_avg_que_len[TC_DATA_NUM]; + u32 tc_cur_que_len[TC_DATA_NUM]; + + u8 reserved[32]; +}; + +struct wpa_driver_sta_link_detect_s { + u64 tx_fail_cnt; + u64 tx_retry_cnt; + u64 tx_multi_retry_cnt; + u64 ack_fail_cnt; + u64 fcs_err_cnt; + u64 tx_cnt; + u64 tx_ok_cnt; + u64 tx_os_cnt; +}; + +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_SEQ_MAX_SIZE 8 +#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 +#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 +#define IW_ENCODE_ALG_SMS4 0x20 + + +/* WAPI */ +struct iw_encode_ext +{ + u32 ext_flags; /* IW_ENCODE_EXT_* */ + u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ + u8 addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + u16 alg; /* IW_ENCODE_ALG_* */ + u16 key_len; + u8 key[32]; +}; + +/* P2P Sigma*/ + +struct wpa_driver_test_mode_info { + u32 index; + u32 buflen; +}; + +struct wpa_driver_testmode_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; +struct wpa_driver_get_sta_statistics_params { + struct wpa_driver_test_mode_info hdr; + u32 version; + u32 flag; + u8 addr[ETH_ALEN]; + + u8 *buf; +}; +struct wpa_driver_p2p_sigma_params { + struct wpa_driver_test_mode_info hdr; + u32 idx; + u32 value; +}; + +struct wpa_driver_get_sta_link_detect_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; + +/* Hotspot Client Management */ +struct wpa_driver_hotspot_params { + struct wpa_driver_test_mode_info hdr; + u8 blocked; + u8 bssid[ETH_ALEN]; +}; + + +/* SW CMD */ +struct wpa_driver_sw_cmd_params { + struct wpa_driver_test_mode_info hdr; + u8 set; + u32 adr; + u32 data; +}; + +struct wpa_driver_suspendmode_params { + struct wpa_driver_test_mode_info hdr; + u8 suspend; +}; + +struct wpa_driver_wapi_key_params { + struct wpa_driver_test_mode_info hdr; + u8 key_index; + u8 key_len; + struct iw_encode_ext extparams; +}; + + +/* CONFIG_MTK_P2P */ +struct wpa_driver_wfd_data_s { + struct wpa_driver_test_mode_info hdr; + u32 WfdCmdType; + u8 WfdEnable; + u8 WfdCoupleSinkStatus; + u8 WfdSessionAvailable; + u8 WfdSigmaMode; + u16 WfdDevInfo; + u16 WfdControlPort; + u16 WfdMaximumTp; + u16 WfdExtendCap; + u8 WfdCoupleSinkAddress[ETH_ALEN]; + u8 WfdAssociatedBssid[ETH_ALEN]; + u8 WfdVideoIp[4]; + u8 WfdAudioIp[4]; + u16 WfdVideoPort; + u16 WfdAudioPort; + u32 WfdFlag; + u32 WfdPolicy; + u32 WfdState; + u8 WfdSessionInformationIE[24*8]; // Include Subelement ID, length + u16 WfdSessionInformationIELen; + u8 Reverved1[2]; + u8 WfdPrimarySinkMac[ETH_ALEN]; + u8 WfdSecondarySinkMac[ETH_ALEN]; + u32 WfdAdvancedFlag; + /* Group 1 64 bytes */ + u8 WfdLocalIp[4]; + u16 WfdLifetimeAc2; /* Unit is 2 TU */ + u16 WfdLifetimeAc3; /* Unit is 2 TU */ + u16 WfdCounterThreshold; /* Unit is ms */ + u8 Reverved2[54]; + /* Group 2 64 bytes */ + u8 Reverved3[64]; + /* Group 3 64 bytes */ + u8 Reverved4[64]; +}wfd_data; +struct wpa_driver_set_beamplus_params { + struct wpa_driver_test_mode_info hdr; + u32 value; +}; + +enum nl80211_testmode_params { + /* old test mode command id, compatible with exist testmode command */ + NL80211_TESTMODE_SW_CMD = 1, + NL80211_TESTMODE_WAPI = 2, + NL80211_TESTMODE_HS20 = 3, + NL80211_TESTMODE_POORLINK = 4, + NL80211_TESTMODE_STATISTICS = 0x10, + NL80211_TESTMODE_LINK_DETECT = 0x20, + /* old test mode command id, compatible with exist testmode command */ + + /* all new added test mode command should great than TESTMODE_CMD_ID_NEW_BEGIN */ + NL80211_TESTMODE_NEW_BEGIN = 100, + NL80211_TESTMODE_SUSPEND = 101, +}; + +#ifdef CONFIG_MTK_LTE_COEX +enum nl80211_testmode_available_chan_attr{ + NL80211_TESTMODE_AVAILABLE_CHAN_INVALID = 0, + NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_100, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, + + NL80211_TESTMODE_AVAILABLE_CHAN_NUM, + NL80211_TESTMODE_AVAILABLE_CHAN_MAX = NL80211_TESTMODE_AVAILABLE_CHAN_NUM - 1 +}; +struct wpa_driver_get_available_channel_params { + struct wpa_driver_test_mode_info hdr; + u8 *buf; +}; +struct wpa_driver_available_chan_s { + u32 ch_2g_base1; + u32 ch_5g_base34; + u32 ch_5g_base100; + u32 ch_5g_base149; + u32 ch_5g_base184; +}; +#endif + + +#endif |
