/****************************************************************************** * * Copyright(c) 2007 - 2019 Realtek Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * *****************************************************************************/ #if defined(CONFIG_MP_INCLUDED) #include #include #define RTW_IWD_MAX_LEN 128 /* * Input Format: %s,%d,%d * %s is width, could be * "b" for 1 byte * "w" for WORD (2 bytes) * "dw" for DWORD (4 bytes) * 1st %d is address(offset) * 2st %d is data to write */ int rtw_mp_write_reg(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { char *pch, *pnext; char *width_str; char width; u32 addr, data; int ret; _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); char input[RTW_IWD_MAX_LEN]; struct rtw_mp_reg_arg reg_arg; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; _rtw_memset(extra, 0, wrqu->length); pch = input; pnext = strpbrk(pch, " ,.-"); if (pnext == NULL) return -EINVAL; *pnext = 0; width_str = pch; pch = pnext + 1; pnext = strpbrk(pch, " ,.-"); if (pnext == NULL) return -EINVAL; *pnext = 0; ret = sscanf(pch, "%x", &addr); pch = pnext + 1; pnext = strpbrk(pch, " ,.-"); if ((pch - input) >= wrqu->length) return -EINVAL; ret = sscanf(pch, "%x", &data); RTW_INFO("data=%x,addr=%x\n", (u32)data, (u32)addr); ret = 0; width = width_str[0]; switch (width) { case 'b': /* 1 byte*/ if (data > 0xFF) { ret = -EINVAL; break; } reg_arg.io_offset = addr; reg_arg.io_type = 1; reg_arg.io_value = (u8)data; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_WRITE_BB)) RTW_INFO("write data=%x,addr=%x OK\n", (u8)data, addr); else RTW_INFO("write data=%x,addr=%x fail\n", (u8)data, addr); break; case 'w': /* 2 bytes*/ if (data > 0xFFFF) { ret = -EINVAL; break; } reg_arg.io_offset = addr; reg_arg.io_type = 2; reg_arg.io_value = (u16)data; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_WRITE_BB)) RTW_INFO("write data=%x,addr=%x OK\n", (u16)data, addr); else RTW_INFO("write data=%x,addr=%x fail\n", (u16)data, addr); break; case 'd': /* 4 bytes*/ reg_arg.io_offset = addr; reg_arg.io_type = 4; reg_arg.io_value = data; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_WRITE_BB)) RTW_INFO("write data=%x,addr=%x OK\n", data, addr); else RTW_INFO("write data=%x,addr=%x fail\n", data, addr); break; default: ret = -EINVAL; break; } return ret; } /* * Input Format: %s,%d * %s is width, could be * "b" for 1 byte * "w" for WORD (2 bytes) * "dw" for DWORD (4 bytes) * %d is address(offset) * * Return: * %d for data readed */ int rtw_mp_read_reg(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { char input[RTW_IWD_MAX_LEN]; char *pch, *pnext; char *width_str; char width; char data[20], tmp[20]; u32 addr = 0, strtout = 0; u32 i = 0, j = 0, ret = 0, data32 = 0; _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct rtw_mp_reg_arg reg_arg; char *pextra = extra; if (wrqu->length > 128) return -EFAULT; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; _rtw_memset(extra, 0, wrqu->length); _rtw_memset(data, '\0', sizeof(data)); _rtw_memset(tmp, '\0', sizeof(tmp)); pch = input; pnext = strpbrk(pch, " ,.-"); if (pnext == NULL) return -EINVAL; *pnext = 0; width_str = pch; pch = pnext + 1; ret = sscanf(pch, "%x", &addr); ret = 0; width = width_str[0]; switch (width) { case 'b': reg_arg.io_offset = addr; reg_arg.io_type = 1; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_READ_BB)) { data32 = reg_arg.io_value; //rtw_phl_read8(dvobj->phl, addr); RTW_INFO("reg=%x\n", data32); sprintf(extra, "%d", data32); } else sprintf(extra, "reg io fail\n"); wrqu->length = strlen(extra); break; case 'w': /* 2 bytes*/ reg_arg.io_offset = addr; reg_arg.io_type = 2; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_READ_BB)) { sprintf(data, "%04x", reg_arg.io_value); RTW_INFO("reg=%s\n", data); } else sprintf(extra, "reg io fail\n"); for (i = 0 ; i <= strlen(data) ; i++) { if (i % 2 == 0) { tmp[j] = ' '; j++; } if (data[i] != '\0') tmp[j] = data[i]; j++; } tmp[j]='\0'; pch = tmp; RTW_INFO("pch=%s", pch); while (*pch != '\0') { pnext = strpbrk(pch, " "); if (!pnext || ((pnext - tmp) > 4)) break; pnext++; if (*pnext != '\0') { /*strtout = simple_strtoul(pnext , &ptmp, 16);*/ ret = sscanf(pnext, "%x", &strtout); pextra += sprintf(pextra, " %d", strtout); } else break; pch = pnext; } wrqu->length = strlen(extra); break; case 'd': /* 4 bytes */ reg_arg.io_offset = addr; reg_arg.io_type = 4; if (rtw_mp_phl_reg(padapter, ®_arg, RTW_MP_REG_CMD_READ_BB)) { sprintf(data, "%08x", reg_arg.io_value); RTW_INFO("reg=%s\n", data); } else sprintf(extra, "reg io fail\n"); /*add read data format blank*/ for (i = 0 ; i <= strlen(data) ; i++) { if (i % 2 == 0) { tmp[j] = ' '; j++; } if (data[i] != '\0') tmp[j] = data[i]; j++; } pch = tmp; RTW_INFO("pch=%s", pch); while (*pch != '\0') { pnext = strpbrk(pch, " "); if (!pnext) break; pnext++; if (*pnext != '\0') { ret = sscanf(pnext, "%x", &strtout); pextra += sprintf(pextra, " %d", strtout); } else break; pch = pnext; } wrqu->length = strlen(extra); break; default: wrqu->length = 0; ret = -EINVAL; break; } return ret; } /* * Input Format: %d,%x,%x * %d is RF path, should be smaller than MAX_RF_PATH_NUMS * 1st %x is address(offset) * 2st %x is data to write */ int rtw_mp_write_rf(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u32 path, addr, data; int ret; _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); char input[RTW_IWD_MAX_LEN]; _rtw_memset(input, 0, wrqu->length); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; ret = sscanf(input, "%d,%x,%x", &path, &addr, &data); if (ret < 3) return -EINVAL; if (path >= GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter))) return -EINVAL; if (addr > 0xFF) return -EINVAL; if (data > 0xFFFFF) return -EINVAL; _rtw_memset(extra, 0, wrqu->length); rtw_phl_write_rfreg(GET_PHL_INFO(dvobj), path, addr, 0xFFFFF, data); sprintf(extra, "write_rf completed\n"); wrqu->length = strlen(extra); return 0; } /* * Input Format: %d,%x * %d is RF path, should be smaller than MAX_RF_PATH_NUMS * %x is address(offset) * * Return: * %d for data readed */ int rtw_mp_read_rf(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { char input[RTW_IWD_MAX_LEN]; char *pch, *pnext; char data[20], tmp[20]; u32 path, addr, strtou; u32 ret, i = 0 , j = 0; _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); char *pextra = extra; if (wrqu->length > 128) return -EFAULT; _rtw_memset(input, 0, wrqu->length); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; ret = sscanf(input, "%d,%x", &path, &addr); if (ret < 2) return -EINVAL; if (path >= GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter))) return -EINVAL; _rtw_memset(extra, 0, wrqu->length); sprintf(data, "%08x", rtw_phl_read_rfreg(GET_PHL_INFO(dvobj), path, addr , 0xFFFFF)); /*add read data format blank*/ for (i = 0 ; i <= strlen(data) ; i++) { if (i % 2 == 0) { tmp[j] = ' '; j++; } tmp[j] = data[i]; j++; } pch = tmp; RTW_INFO("pch=%s", pch); while (*pch != '\0') { pnext = strpbrk(pch, " "); if (!pnext) break; pnext++; if (*pnext != '\0') { /*strtou =simple_strtoul(pnext , &ptmp, 16);*/ ret = sscanf(pnext, "%x", &strtou); pextra += sprintf(pextra, " %d", strtou); } else break; pch = pnext; } wrqu->length = strlen(extra); return 0; } int rtw_mp_start(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { int ret = 0; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmppriv = &padapter->mppriv; char *pextra = NULL; pmppriv->bprocess_mp_mode = _TRUE; if (pmppriv->mode == MP_ON) { sprintf(extra, "Already mp_start\n"); wrqu->length = strlen(extra); return ret; } rtw_set_scan_deny(padapter, 5000); rtw_mi_scan_abort(padapter, _TRUE); if (rtw_mp_cmd(padapter, MP_START, RTW_CMDF_WAIT_ACK) != _SUCCESS) ret = -EPERM; _rtw_memset(extra, 0, wrqu->length); pextra = extra; pextra += sprintf(extra, "mp_start %s\n", ret == 0 ? "ok" : "fail"); pextra += sprintf(pextra, "EFUSE:%s\n", RTW_EFUSE_FROM2STR(rtw_efuse_get_map_from(padapter))); wrqu->length = strlen(extra); return ret; } int rtw_mp_stop(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { int ret = 0; u8 status = 0; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmppriv = &padapter->mppriv; if (rtw_mp_cmd(padapter, MP_STOP, RTW_CMDF_WAIT_ACK) != _SUCCESS) ret = -EPERM; if (pmppriv->mode != MP_OFF) return -EPERM; _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "mp_stop ok\n"); wrqu->length = strlen(extra); pmppriv->bprocess_mp_mode = _FALSE; return ret; } int rtw_mp_rate(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u16 rate = MPT_RATE_1M; u8 input[RTW_IWD_MAX_LEN]; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; PMPT_CONTEXT pMptCtx = &(padapter->mppriv.mpt_ctx); u8 tx_nss = get_phy_tx_nss(padapter); char *pextra = extra; u8 path_i = 0, i = 0; u16 pwr_dbm = 0; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; rate = rtw_mp_rate_parse(padapter, input); padapter->mppriv.rateidx = rate; if (rate == 0 && strcmp(input, "1M") != 0) { rate = rtw_atoi(input); #ifndef CONFIG_80211AX_HE padapter->mppriv.rateidx = mrate_to_hwrate(rate); #endif /*if (rate <= 0x7f) rate = wifirate2_ratetbl_inx((u8)rate); else if (rate < 0xC8) rate = (rate - 0x79 + MPT_RATE_MCS0); HT rate 0x80(MCS0) ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159 VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179 VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199 else VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153 rate =(rate - MPT_RATE_VHT1SS_MCS0); */ } _rtw_memset(extra, 0, wrqu->length); pextra += sprintf(pextra, "Set data rate to %s index %d\n" , input, padapter->mppriv.rateidx); RTW_INFO("%s: %s rate index=%d\n", __func__, input, padapter->mppriv.rateidx); pextra += sprintf(pextra, "PPDU Type %s\n", PPDU_TYPE_STR(pmp_priv->rtw_mp_pmact_ppdu_type)); pextra += sprintf(pextra, "CMD: [mp_plcp_datappdu=%%d]\nPLCP (PPDU Type):\n"); for (i = pmp_priv->rtw_mp_pmact_ppdu_type; i <= RTW_MP_TYPE_HE_TB; i++) pextra += sprintf(pextra, "%d:%s\n", i,PPDU_TYPE_STR(i)); SetDataRate(padapter); #if 0 for (path_i = 0 ; path_i < tx_nss; path_i++) { pwr_dbm = rtw_mp_get_pwrtab_dbm(padapter, path_i); pextra += sprintf(pextra, "Path%d Pwrdbm:%d" , path_i, pwr_dbm); } #endif wrqu->length = strlen(extra); return 0; } int rtw_mp_channel(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 input[RTW_IWD_MAX_LEN]; u32 channel = 1; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; channel = rtw_atoi(input); _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "Change channel %d to channel %d", pmp_priv->channel, channel); pmp_priv->channel = channel; //pHalData->current_channel = channel; //aka struct rtw_phl_com_t SetChannel(padapter); wrqu->length = strlen(extra); return 0; } static void rtw_mp_update_trxsc(_adapter *padapter) { struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 trxsc_offset = pmp_priv->rtw_mp_trxsc; switch (trxsc_offset) { case 0: pmp_priv->rtw_mp_data_bandwidth = pmp_priv->bandwidth; RTW_INFO("%s:TRXSC %d, MP bandwidth = %d\n", __func__, trxsc_offset, pmp_priv->bandwidth); break; case 1: case 2: case 3: case 4: pmp_priv->rtw_mp_data_bandwidth = CHANNEL_WIDTH_20; RTW_INFO("%s:TRXSC %d, MP bandwidth = %d\n", __func__, trxsc_offset, pmp_priv->bandwidth); break; case 9: case 10: case 11: case 12: pmp_priv->rtw_mp_data_bandwidth = CHANNEL_WIDTH_40; RTW_INFO("%s:TRXSC %d, MP bandwidth = %d\n", __func__, trxsc_offset, pmp_priv->bandwidth); break; case 13: case 14: pmp_priv->rtw_mp_data_bandwidth = CHANNEL_WIDTH_40; RTW_INFO("%s:TRXSC %d, MP bandwidth = %d\n", __func__, trxsc_offset, pmp_priv->bandwidth); break; } } int rtw_mp_trxsc_offset(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 input[RTW_IWD_MAX_LEN]; u32 trxsc_offset = 0; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; trxsc_offset = rtw_atoi(input); RTW_INFO("%s: ch offset = %d\n", __func__, trxsc_offset); pmp_priv->rtw_mp_trxsc = trxsc_offset; rtw_mp_update_trxsc(padapter); _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "change TRXSC to %d, current Bandwidth=%d\n", pmp_priv->rtw_mp_trxsc, pmp_priv->bandwidth); wrqu->length = strlen(extra); return 0; } int rtw_mp_bandwidth(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u8 bandwidth = 0, sg = 0; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 input[RTW_IWD_MAX_LEN]; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; if (sscanf(input, "40M=%hhd,shortGI=%hhd", &bandwidth, &sg) > 0) RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth , sg); #if 0 if (bandwidth == 1 && rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_40M)) bandwidth = CHANNEL_WIDTH_40; else if (bandwidth == 2 && rtw_hw_chk_bw_cap(adapter_to_dvobj(padapter), BW_CAP_80M)) bandwidth = CHANNEL_WIDTH_80; else bandwidth = CHANNEL_WIDTH_20; #else rtw_adjust_chbw(padapter, pmp_priv->channel, &bandwidth, &pmp_priv->prime_channel_offset); pmp_priv->bandwidth = (u8)bandwidth; pmp_priv->preamble = sg; _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "Change BW %d to BW %d\n", pmp_priv->bandwidth , bandwidth); SetBandwidth(padapter); rtw_mp_update_trxsc(padapter); #endif wrqu->length = strlen(extra); return 0; } int rtw_mp_txpower_index(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); char input[RTW_IWD_MAX_LEN]; u32 rfpath = 0 ; u32 txpower_inx = 0, tarpowerdbm = 0; char *pextra = extra; u8 rf_type = GET_HAL_RFPATH(adapter_to_dvobj(padapter)); if (wrqu->length > 128) return -EFAULT; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; _rtw_memset(extra, 0, strlen(extra)); if (wrqu->length == 2) { #ifndef CONFIG_80211AX_HE if (input[0] != '\0' ) { rfpath = rtw_atoi(input); txpower_inx = mpt_ProQueryCalTxPower(padapter, rfpath); } #endif pextra += sprintf(pextra, " %d\n", txpower_inx); tarpowerdbm = mpt_get_tx_power_finalabs_val(padapter, rfpath); if (tarpowerdbm > 0) pextra += sprintf(pextra, "\t\t dBm:%d", tarpowerdbm); } else { #ifndef CONFIG_80211AX_HE txpower_inx = mpt_ProQueryCalTxPower(padapter, 0); pextra += sprintf(pextra, "patha=%d", txpower_inx); if (rf_type > RF_1T2R) { txpower_inx = mpt_ProQueryCalTxPower(padapter, 1); pextra += sprintf(pextra, ",pathb=%d", txpower_inx); } if (rf_type > RF_2T4R) { txpower_inx = mpt_ProQueryCalTxPower(padapter, 2); pextra += sprintf(pextra, ",pathc=%d", txpower_inx); } if (rf_type > RF_3T4R) { txpower_inx = mpt_ProQueryCalTxPower(padapter, 3); pextra += sprintf(pextra, ",pathd=%d", txpower_inx); } #endif tarpowerdbm = mpt_get_tx_power_finalabs_val(padapter, 0); pextra += sprintf(pextra, "\n\t\t\tpatha dBm=%d", tarpowerdbm); if (rf_type > RF_1T2R) { tarpowerdbm = mpt_get_tx_power_finalabs_val(padapter, 1); pextra += sprintf(pextra, ",pathb dBm=%d", tarpowerdbm); } if (rf_type > RF_2T4R) { tarpowerdbm = mpt_get_tx_power_finalabs_val(padapter, 2); pextra += sprintf(pextra, ",pathc dBm=%d", tarpowerdbm); } if (rf_type > RF_3T4R) { tarpowerdbm = mpt_get_tx_power_finalabs_val(padapter, 3); pextra += sprintf(pextra, ",pathd dBm=%d", tarpowerdbm); } } wrqu->length = strlen(extra); return 0; } int rtw_mp_txpower(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u32 idx_a = 0, idx_b = 0, idx_c = 0, idx_d = 0; int MsetPower = 1; char pout_str_buf[7]; u8 input[RTW_IWD_MAX_LEN]; u8 rfpath_i = 0; u16 agc_cw_val = 0; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmppriv = &padapter ->mppriv; u8 tx_nss = get_phy_tx_nss(padapter); char *pextra = extra; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; MsetPower = strncmp(input, "off", 3); if (MsetPower == 0) { pmppriv->bSetTxPower = 0; sprintf(pextra, "MP Set power off"); } else { if (sscanf(input, "patha=%d,pathb=%d,pathc=%d,pathd=%d", &idx_a, &idx_b, &idx_c, &idx_d) >= 1) { pextra += sprintf(pextra, "Set power offset path_A:%d path_B:%d path_C:%d path_D:%d\n", idx_a , idx_b , idx_c , idx_d); pmppriv->path_pwr_offset[RF_PATH_A] = (u8)idx_a; pmppriv->path_pwr_offset[RF_PATH_B] = (u8)idx_b; pmppriv->path_pwr_offset[RF_PATH_C] = (u8)idx_c; pmppriv->path_pwr_offset[RF_PATH_D] = (u8)idx_d; pmppriv->bSetTxPower = 1; } else if (strncmp(input, "dbm", 3) == 0) { u8 signed_flag = 0; u8 ret = 0xff; int int_num = 0; u32 dec_num = 0; s16 pout = 0; int i; u32 poutdbm = 0; s32 db_temp = 0; s16 pset = 0; u8 rfpath; if (sscanf(input, "dbm=%7s", pout_str_buf) == 1) { ret = 0; } else { sprintf(extra, "[dbm = -30 ~ 30.00]"); goto invalid_param_format; } if(pout_str_buf[0] == '-') signed_flag = 1; i = sscanf(pout_str_buf, "%d.%3u", &int_num, &dec_num); RTW_INFO("%s: pars input =%d.%d\n", __func__, int_num, dec_num); if(i == 2) dec_num = (dec_num < 10) ? dec_num * 10 : dec_num; if (int_num >= 30 || ret == 0xff || dec_num > 99 || (dec_num % 25 != 0)) { sprintf(extra, "CMD Format:[dbm= -30.00 ~ 30.00]\n" " each scale step value must 0.25 or -0.25\n"); goto invalid_param_format; } pset = int_num * TX_POWER_BASE + ((dec_num * TX_POWER_BASE) / 100); RTW_INFO("%s: pset=%d\n", __func__, pset); pset = ((pset < 0 || signed_flag == 1) ? -pset : pset); pextra += sprintf(pextra, "Set power dbm :%d.%d\n", int_num, dec_num); pmppriv->txpowerdbm = pset; pmppriv->bSetTxPower = 1; } else { pextra += sprintf(pextra, "Invalid format on line %s\n", input); RTW_INFO("Invalid format on line %s\n", input ); wrqu->length = strlen(extra); return 0; } for (rfpath_i = 0 ; rfpath_i < tx_nss; rfpath_i ++) { agc_cw_val = rtw_mp_txpower_dbm(padapter, rfpath_i); pextra += sprintf(pextra, "Path:%d PwrAGC:%d\n", rfpath_i,agc_cw_val); } } invalid_param_format: wrqu->length = strlen(extra); return 0; } int rtw_mp_ant_tx(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u8 i; u8 input[RTW_IWD_MAX_LEN]; u8 antenna = 0; u16 pwr_dbm = 0; _adapter *padapter = rtw_netdev_priv(dev); char *pextra = extra; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; pextra += sprintf(pextra, "switch Tx antenna to %s\n", input); for (i = 0; i < strlen(input); i++) { switch (input[i]) { case 'a': antenna |= MP_ANTENNA_A; break; case 'b': antenna |= MP_ANTENNA_B; break; case 'c': antenna |= MP_ANTENNA_C; break; case 'd': antenna |= MP_ANTENNA_D; break; } } /*antenna |= BIT(extra[i]-'a');*/ RTW_INFO("%s: antenna=0x%x\n", __func__, antenna); padapter->mppriv.antenna_trx = antenna; SetAntenna(padapter); pwr_dbm = rtw_mp_get_pwrtab_dbm(padapter, antenna); pextra += sprintf(pextra, "read pwr dbm:%d", pwr_dbm); wrqu->length = strlen(extra); return 0; } int rtw_mp_ant_rx(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u8 i; u16 antenna = 0; u8 input[RTW_IWD_MAX_LEN]; _adapter *padapter = rtw_netdev_priv(dev); _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; /*RTW_INFO("%s: input=%s\n", __func__, input);*/ _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "switch Rx antenna to %s", input); for (i = 0; i < strlen(input); i++) { switch (input[i]) { case 'a': antenna |= MP_ANTENNA_A; break; case 'b': antenna |= MP_ANTENNA_B; break; case 'c': antenna |= MP_ANTENNA_C; break; case 'd': antenna |= MP_ANTENNA_D; break; } } RTW_INFO("%s: antenna=0x%x\n", __func__, antenna); padapter->mppriv.antenna_trx = antenna; SetAntenna(padapter); wrqu->length = strlen(extra); return 0; } int rtw_set_ctx_destAddr(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { int jj, kk = 0; struct pkt_attrib *pattrib; struct mp_priv *pmp_priv; _adapter *padapter = rtw_netdev_priv(dev); pmp_priv = &padapter->mppriv; pattrib = &pmp_priv->tx.attrib; if (strlen(extra) < 5) return _FAIL; RTW_INFO("%s: in=%s\n", __func__, extra); for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3) pattrib->dst[jj] = key_2char2num(extra[kk], extra[kk + 1]); RTW_INFO("pattrib->dst:%x %x %x %x %x %x\n", pattrib->dst[0], pattrib->dst[1], pattrib->dst[2], pattrib->dst[3], pattrib->dst[4], pattrib->dst[5]); return 0; } int rtw_mp_ctx(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u32 pkTx = 1; int countPkTx = 1, cotuTx = 1, CarrSprTx = 1, scTx = 1, sgleTx = 1, stop = 1, payload = 1; u32 bStartTest = 1; u32 count = 0, pktinterval = 0, pktlen = 0; u8 status; struct mp_priv *pmp_priv; struct pkt_attrib *pattrib; _adapter *padapter = rtw_netdev_priv(dev); pmp_priv = &padapter->mppriv; pattrib = &pmp_priv->tx.attrib; if (padapter->registrypriv.mp_mode != 1 ) { sprintf(extra, "Error: can't tx ,not in MP mode. \n"); wrqu->length = strlen(extra); return 0; } if (copy_from_user(extra, wrqu->pointer, wrqu->length)) return -EFAULT; *(extra + wrqu->length) = '\0'; RTW_INFO("%s: in=%s\n", __func__, extra); #ifdef CONFIG_CONCURRENT_MODE if (!is_primary_adapter(padapter)) { sprintf(extra, "Error: MP mode can't support Virtual adapter, Please to use main adapter.\n"); wrqu->length = strlen(extra); return 0; } #endif countPkTx = strncmp(extra, "count=", 5); /* strncmp TRUE is 0*/ cotuTx = strncmp(extra, "background", 20); CarrSprTx = strncmp(extra, "background,cs", 20); scTx = strncmp(extra, "background,sc", 20); sgleTx = strncmp(extra, "background,stone", 20); pkTx = strncmp(extra, "background,pkt", 20); stop = strncmp(extra, "stop", 4); payload = strncmp(extra, "payload=", 8); if (sscanf(extra, "count=%d,pkt", &count) > 0) RTW_INFO("count= %d\n", count); if (sscanf(extra, "pktinterval=%d", &pktinterval) > 0) RTW_INFO("pktinterval= %d\n", pktinterval); if (sscanf(extra, "pktlen=%d", &pktlen) > 0) RTW_INFO("pktlen= %d\n", pktlen); if (payload == 0) { payload = MP_TX_Payload_default_random; if (strncmp(extra, "payload=prbs9", 14) == 0) { payload = MP_TX_Payload_prbs9; sprintf(extra, "config payload PRBS9\n"); } else { if (sscanf(extra, "payload=%x", &payload) > 0){ RTW_INFO("payload= %x\n", payload); sprintf(extra, "config payload setting = %x\n" "1. input payload=[]:\n " "[0]: 00, [1]: A5, [2]: 5A, [3]: FF, [4]: PRBS-9, [5]: Random\n" "2. specified a hex payload: payload=0xee\n", payload); } } pmp_priv->tx.payload = payload; wrqu->length = strlen(extra); return 0; } if (_rtw_memcmp(extra, "destmac=", 8)) { wrqu->length -= 8; rtw_set_ctx_destAddr(dev, info, wrqu, &extra[8]); sprintf(extra, "Set dest mac OK !\n"); return 0; } /*RTW_INFO("%s: count=%d countPkTx=%d cotuTx=%d CarrSprTx=%d scTx=%d sgleTx=%d pkTx=%d stop=%d\n", __func__, count, countPkTx, cotuTx, CarrSprTx, pkTx, sgleTx, scTx, stop);*/ _rtw_memset(extra, '\0', strlen(extra)); if (pktinterval != 0) { sprintf(extra, "Pkt Interval = %d", pktinterval); padapter->mppriv.pktInterval = pktinterval; wrqu->length = strlen(extra); return 0; } else if (pktlen != 0) { sprintf(extra, "Pkt len = %d", pktlen); pattrib->pktlen = pktlen; wrqu->length = strlen(extra); return 0; } else if (stop == 0) { bStartTest = 0; /* To set Stop*/ pmp_priv->tx.stop = 1; sprintf(extra, "Stop continuous Tx"); } else { bStartTest = 1; if (pmp_priv->mode != MP_ON) { if (pmp_priv->tx.stop != 1) { RTW_INFO("%s:Error MP_MODE %d != ON\n", __func__, pmp_priv->mode); return -EFAULT; } } } pmp_priv->tx.count = count; if (pkTx == 0 || countPkTx == 0) pmp_priv->mode = MP_PACKET_TX; if (sgleTx == 0) pmp_priv->mode = MP_SINGLE_TONE_TX; if (cotuTx == 0) pmp_priv->mode = MP_CONTINUOUS_TX; if (CarrSprTx == 0) pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX; if (scTx == 0) pmp_priv->mode = MP_SINGLE_CARRIER_TX; status = rtw_mp_pretx_proc(padapter, bStartTest, extra); if (stop == 0) pmp_priv->mode = MP_ON; wrqu->length = strlen(extra); return status; } int rtw_mp_disable_bt_coexist(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { #ifdef CONFIG_BTC _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); #endif u8 input[RTW_IWD_MAX_LEN]; u32 bt_coexist; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; input[wrqu->data.length] = '\0'; bt_coexist = rtw_atoi(input); #if 0 if (bt_coexist == 0) { RTW_INFO("Set OID_RT_SET_DISABLE_BT_COEXIST: disable BT_COEXIST\n"); #ifdef CONFIG_BTC rtw_btcoex_HaltNotify(padapter); rtw_btcoex_SetManualControl(padapter, _TRUE); /* Force to switch Antenna to WiFi*/ rtw_write16(padapter, 0x870, 0x300); rtw_write16(padapter, 0x860, 0x110); #endif /* CONFIG_BTC */ } else { #ifdef CONFIG_BTC rtw_btcoex_SetManualControl(padapter, _FALSE); #endif } #endif return 0; } int rtw_mp_arx(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmppriv = &padapter->mppriv; struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); u8 input[RTW_IWD_MAX_LEN]; u32 ret; char *pch, *token, *tmp[2] = {0x00, 0x00}; u32 i = 0, jj = 0, kk = 0, cnts = 0; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; RTW_INFO("%s: %s\n", __func__, input); if (strncmp(input, "setbssid=", 8) == 0) { pch = input; while ((token = strsep(&pch, "=")) != NULL) { if (i > 1) break; tmp[i] = token; i++; } if ((tmp[0] != NULL) && (tmp[1] != NULL)) { cnts = strlen(tmp[1]) / 2; if (cnts < 1) return -EFAULT; RTW_INFO("%s: cnts=%d\n", __func__, cnts); RTW_INFO("%s: data=%s\n", __func__, tmp[1]); for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) { pmppriv->network_macaddr[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]); RTW_INFO("network_macaddr[%d]=%x\n", jj, pmppriv->network_macaddr[jj]); } } else return -EFAULT; pmppriv->bSetRxBssid = _TRUE; } else if (strncmp(input, "frametype", 9) == 0) { if (strncmp(input, "frametype beacon", 16) == 0) pmppriv->brx_filter_beacon = _TRUE; else pmppriv->brx_filter_beacon = _FALSE; } else if (strncmp(input, "accept_mac", 10) == 0) { pmppriv->bmac_filter = _TRUE; pch = input; while ((token = strsep(&pch, "=")) != NULL) { if (i > 1) break; tmp[i] = token; i++; } if ((tmp[0] != NULL) && (tmp[1] != NULL)) { cnts = strlen(tmp[1]) / 2; if (cnts < 1) return -EFAULT; RTW_INFO("%s: cnts=%d\n", __func__, cnts); RTW_INFO("%s: data=%s\n", __func__, tmp[1]); for (jj = 0, kk = 0; jj < cnts ; jj++, kk += 2) { pmppriv->mac_filter[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]); RTW_INFO("%s mac_filter[%d]=%x\n", __func__, jj, pmppriv->mac_filter[jj]); } } else return -EFAULT; } else if (strncmp(input, "start", 5) == 0) { sprintf(extra, "start"); } else if (strncmp(input, "stop", 5) == 0) { struct rtw_mp_rx_arg rx_arg; _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); rtw_mp_phl_query_rx(padapter, &rx_arg, 2); if (rx_arg.cmd_ok) { pmppriv->rx_pktcount = rx_arg.rx_ok; pmppriv->rx_crcerrpktcount = rx_arg.rx_err; RTW_INFO("phl_query_rx rx_ok=%d rx_err=%d\n", pmppriv->rx_pktcount, pmppriv->rx_crcerrpktcount); } else RTW_WARN("phl_query_rx Fail !!!"); pmppriv->bmac_filter = _FALSE; pmppriv->bSetRxBssid = _FALSE; sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", pmppriv->rx_pktcount, pmppriv->rx_crcerrpktcount, pmppriv->rx_pktcount_filter_out); } else if (strncmp(input, "phy", 3) == 0) { struct rtw_mp_rx_arg rx_arg; _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); rtw_mp_phl_query_rx(padapter, &rx_arg, 0); if (rx_arg.cmd_ok) sprintf(extra, "Phy Received packet OK:%d CRC error:%d", rx_arg.rx_ok, rx_arg.rx_err); else sprintf(extra, "PHL Phy Query Fail !!!"); } else if (strncmp(input, "mac", 3) == 0) { struct rtw_mp_rx_arg rx_arg; _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); rtw_mp_phl_query_rx(padapter, &rx_arg, 1); if (rx_arg.cmd_ok) sprintf(extra, "Mac Received packet OK:%d CRC error:%d", rx_arg.rx_ok, rx_arg.rx_err); else sprintf(extra, "Mac Phy Query Fail !!!"); } else if (strncmp(input, "mon=", 4) == 0) { int bmon = 0; ret = sscanf(input, "mon=%d", &bmon); if (bmon == 1) { pmppriv->rx_bindicatePkt = _TRUE; sprintf(extra, "Indicating Receive Packet to network start\n"); } else { pmppriv->rx_bindicatePkt = _FALSE; sprintf(extra, "Indicating Receive Packet to network Stop\n"); } } else if (strncmp(input, "loopbk", 6) == 0) { u32 val32 = rtw_phl_read32(dvobj->phl, 0xCC20); val32 |= BIT0; rtw_phl_write32(dvobj->phl, 0xCC20 , val32); pmppriv->bloopback = _TRUE; sprintf(extra , "Enter MAC LoopBack mode\n"); } else if (strncmp(input, "gain", 4) == 0) { struct rtw_mp_rx_arg rx_arg; u32 gain_val = 0xff; u8 path_num = 0; u8 rf_path = 0xff; u8 iscck = 0xff; u8 *pch = extra; switch (input[4]) { case 'a': rf_path = RF_PATH_A; break; case 'b': rf_path = RF_PATH_B; break; case 'c': rf_path = RF_PATH_C; break; case 'd': rf_path = RF_PATH_D; break; } if ((sscanf(input + 5, "=0x%x,iscck=%hhd", &gain_val, &iscck) == 2) || (sscanf(input + 5, "=%d,iscck=%hhd", &gain_val, &iscck) == 2)) RTW_INFO("%s: read gain = %d , is cck =%d\n", __func__, gain_val, iscck); else if ((sscanf(input + 4, "=0x%x", &gain_val) == 1) || (sscanf(input + 4, "=%d", &gain_val) == 1)) iscck = (u8)rtw_mp_is_cck_rate(pmppriv->rateidx); else { sprintf(pch, "error format: gain=[Dec/Hex]\n" "\t\tgaina or gainb=[Dec/Hex],iscck=0/1\n"); wrqu->length = strlen(pch) + 1; return 0; } if (rf_path == 0xff) { rf_path = RF_PATH_A; path_num = GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter)) - 1; } else path_num = rf_path; if (gain_val == 0xff || iscck == 0xff) { sprintf(extra, "error format: gaina or gainb=%d,iscck=%d\n", gain_val, iscck); wrqu->length = strlen(extra) + 1; return 0; } for (; rf_path <= path_num ; rf_path++) { RTW_INFO("%s:set Path:%d gain_offset=%d iscck=%d\n", __func__, rf_path, gain_val, iscck); _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); rx_arg.offset = (s8)gain_val; rx_arg.iscck = iscck; rtw_mp_phl_rx_gain_offset(padapter, &rx_arg, rf_path); if (rx_arg.cmd_ok) pch += sprintf(pch, "Path %s: 0x%hhx Rx Gain offset OK\n\t\t", (rf_path == RF_PATH_A) ? "A":(rf_path == RF_PATH_B) ? "B": (rf_path == RF_PATH_C) ? "C":"D", gain_val); } } else if (strncmp(input, "rssi", 4) == 0) { struct rtw_mp_rx_arg rx_arg; u8 rssi_path = 0, all_path_num = 0; char *pcar = extra; u8 i = 0; if (strncmp(input, "rssi a", 6) == 0) rssi_path = 0; else if (strncmp(input, "rssi b", 6) == 0) rssi_path = 1; else all_path_num = GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter)); if (all_path_num > 1) { rssi_path = 0; all_path_num = all_path_num - 1; } else all_path_num = rssi_path; RTW_INFO("%s:Query RSSI Path:%d to %d\n", __func__, rssi_path, all_path_num); _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); for (i = rssi_path ; i <= all_path_num; i++) { rx_arg.rf_path = i; rtw_mp_phl_rx_rssi(padapter, &rx_arg); if (rx_arg.cmd_ok) { int result_int = 0; int result_dec = 0; result_int = (rx_arg.rssi / 2) -110; result_dec = (rx_arg.rssi % 2); if (result_dec == 1) { result_dec = (result_dec * 10) / 2; result_int += 1; } pcar += sprintf(pcar, "Path%d RSSI=%d.%d ", i, result_int, result_dec); } else pcar += sprintf(pcar, "Path%d RSSI Fail\n", i); } } else if (strncmp(input, "physts", 6) == 0) { struct rtw_mp_rx_arg rx_arg; bool bon; if (strncmp(input, "physts on", 9) == 0) bon = true; else bon = false; _rtw_memset((void *)&rx_arg, 0, sizeof(struct rtw_mp_rx_arg)); rtw_mp_phl_rx_physts(padapter, &rx_arg, bon); if (rx_arg.cmd_ok) sprintf(extra, "start OK" ); else sprintf(extra, "start Fail"); } wrqu->length = strlen(extra) + 1; return 0; } int rtw_mp_trx_query(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u32 txok, txfail, rxok, rxfail, rxfilterout; _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; if (pmp_priv->rtw_mp_tx_method == RTW_MP_PMACT_TX) rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_CMD_PHY_OK, pmp_priv->rtw_mp_tx_method, _FALSE); txok = padapter->mppriv.tx.sended; txfail = 0; rxok = padapter->mppriv.rx_pktcount; rxfail = padapter->mppriv.rx_crcerrpktcount; rxfilterout = padapter->mppriv.rx_pktcount_filter_out; _rtw_memset(extra, '\0', 128); sprintf(extra, "Tx OK:%d, Tx Fail:%d, Rx OK:%d, CRC error:%d ,Rx Filter out:%d\n", txok, txfail, rxok, rxfail, rxfilterout); wrqu->length = strlen(extra) + 1; return 0; } int rtw_mp_pwrtrk(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u8 enable; u32 thermal; s32 ret = 0; _adapter *padapter = rtw_netdev_priv(dev); u8 input[RTW_IWD_MAX_LEN]; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; _rtw_memset(extra, 0, wrqu->length); enable = RTW_MP_TSSI_OFF; if (wrqu->length > 1) { /* not empty string*/ if (strncmp(input, "off", 3) == 0) { enable = RTW_MP_TSSI_OFF; sprintf(extra, "TSSI power tracking off"); } else if (strncmp(input, "on", 2) == 0) { enable = RTW_MP_TSSI_ON; sprintf(extra, "TSSI power tracking on"); } else if (strncmp(input, "cal", 3) == 0) { enable = RTW_MP_TSSI_CAL; sprintf(extra, "TSSI cal"); } else { input[wrqu->length] = '\0'; enable = rtw_atoi(input); sprintf(extra, "TSSI power tracking %d", enable); } if (enable <= RTW_MP_TSSI_CAL) ret = rtw_mp_set_tssi_pwrtrk(padapter, enable); if (ret == false) sprintf(extra, "set TSSI power tracking fail"); } else { enable = rtw_mp_get_tssi_pwrtrk(padapter); sprintf(extra, "Get TSSI state: %d\n\ incput (int/str): [0]:off / [1]:on / [2]:cal for TSSI Tracking", enable); } wrqu->length = strlen(extra); return 0; } int rtw_mp_psd(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); u8 input[RTW_IWD_MAX_LEN]; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; strcpy(extra, input); wrqu->length = mp_query_psd(padapter, extra); return 0; } int rtw_mp_thermal(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u8 val[4] = {0}; u8 ret = 0; u16 ther_path_addr[4] = {0}; u16 cnt = 1; _adapter *padapter = rtw_netdev_priv(dev); int rfpath = RF_PATH_A; if (copy_from_user(extra, wrqu->pointer, wrqu->length)) return -EFAULT; if ((strncmp(extra, "write", 6) == 0)) { #if 0 int i; u16 raw_cursize = 0, raw_maxsize = 0; raw_maxsize = efuse_GetavailableSize(padapter); RTW_INFO("[eFuse available raw size]= %d bytes\n", raw_maxsize - raw_cursize); if (2 > raw_maxsize - raw_cursize) { RTW_INFO("no available efuse!\n"); return -EFAULT; } for (i = 0; i < GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter)); i++) { GetThermalMeter(padapter, i , &val[i]); if (ther_path_addr[i] != 0 && val[i] != 0) { if (rtw_efuse_map_write(padapter, ther_path_addr[i], cnt, &val[i]) == _FAIL) { RTW_INFO("Error efuse write thermal addr 0x%x ,val = 0x%x\n", ther_path_addr[i], val[i]); return -EFAULT; } } else { RTW_INFO("Error efuse write thermal Null addr,val \n"); return -EFAULT; } } #endif _rtw_memset(extra, 0, wrqu->length); sprintf(extra, " efuse write ok :%d", val[0]); } else { ret = sscanf(extra, "%d", &rfpath); if (ret < 1) { rfpath = RF_PATH_A; RTW_INFO("default thermal of path(%d)\n", rfpath); } if (rfpath >= GET_HAL_RFPATH_NUM(adapter_to_dvobj(padapter))) return -EINVAL; RTW_INFO("read thermal of path(%d)\n", rfpath); GetThermalMeter(padapter, rfpath, &val[0]); _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "%d [0x%hhx]", val[0], val[0]); } wrqu->length = strlen(extra); return 0; } int rtw_mp_reset_stats(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { struct mp_priv *pmp_priv; _adapter *padapter = rtw_netdev_priv(dev); pmp_priv = &padapter->mppriv; pmp_priv->tx.sended = 0; pmp_priv->tx_pktcount = 0; pmp_priv->rx_pktcount = 0; pmp_priv->rx_pktcount_filter_out = 0; pmp_priv->rx_crcerrpktcount = 0; rtw_mp_reset_phy_count(padapter); _rtw_memset(extra, 0, wrqu->length); sprintf(extra, "mp_reset_stats ok\n"); wrqu->length = strlen(extra); return 0; } int rtw_mp_dump(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { struct mp_priv *pmp_priv; u8 input[RTW_IWD_MAX_LEN]; _adapter *padapter = rtw_netdev_priv(dev); pmp_priv = &padapter->mppriv; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; if (strncmp(input, "all", 4) == 0) { //mac_reg_dump(RTW_DBGDUMP, padapter); //bb_reg_dump(RTW_DBGDUMP, padapter); //rf_reg_dump(RTW_DBGDUMP, padapter); } return 0; } int rtw_mp_phypara(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); char input[RTW_IWD_MAX_LEN]; u32 invalxcap = 0, ret = 0; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; RTW_INFO("%s:priv in=%s\n", __func__, input); if (strncmp(input, "xcap=", 5) == 0) { if ((sscanf(input+4, "=0x%x", &invalxcap) == 1) || (sscanf(input+4, "=%d", &invalxcap) == 1)) { if (invalxcap < 255) { rtw_mp_set_crystal_cap(padapter, invalxcap); sprintf(extra, "Set xcap = %d [0x%hhx]", invalxcap, invalxcap); } else sprintf(extra, "Error formats , inpunt value over 255 !\n"); wrqu->length = strlen(extra); return ret; } } sprintf(extra, "Error formats , inpunt [xcap=%%d/0x%%x]\n"); wrqu->length = strlen(extra); return ret; } int rtw_mp_SetRFPath(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); char input[RTW_IWD_MAX_LEN]; int bMain = 1, bTurnoff = 1; #ifdef CONFIG_ANTENNA_DIVERSITY u8 ret = _TRUE; #endif RTW_INFO("%s:iwpriv in=%s\n", __func__, input); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; #if 0 bMain = strncmp(input, "1", 2); /* strncmp TRUE is 0*/ bTurnoff = strncmp(input, "0", 3); /* strncmp TRUE is 0*/ _rtw_memset(extra, 0, wrqu->length); #ifdef CONFIG_ANTENNA_DIVERSITY if (bMain == 0) ret = rtw_mp_set_antdiv(padapter, _TRUE); else ret = rtw_mp_set_antdiv(padapter, _FALSE); if (ret == _FALSE) RTW_INFO("%s:ANTENNA_DIVERSITY FAIL\n", __func__); #endif if (bMain == 0) { MP_PHY_SetRFPathSwitch(padapter, _TRUE); RTW_INFO("%s:PHY_SetRFPathSwitch=TRUE\n", __func__); sprintf(extra, "mp_setrfpath Main\n"); } else if (bTurnoff == 0) { MP_PHY_SetRFPathSwitch(padapter, _FALSE); RTW_INFO("%s:PHY_SetRFPathSwitch=FALSE\n", __func__); sprintf(extra, "mp_setrfpath Aux\n"); } else { bMain = MP_PHY_QueryRFPathSwitch(padapter); RTW_INFO("%s:Query RF Path = %s\n", __func__, (bMain ? "Main":"Aux")); sprintf(extra, "RF Path %s\n" , (bMain ? "1":"0")); } #endif wrqu->length = strlen(extra); return 0; } int rtw_mp_switch_rf_path(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv; char input[RTW_IWD_MAX_LEN]; int bwlg = 1, bwla = 1, btg = 1, bbt=1; u8 ret = 0; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; pmp_priv = &padapter->mppriv; RTW_INFO("%s: in=%s\n", __func__, input); #ifdef CONFIG_RTL8821C /* only support for 8821c wlg/wla/btg/bt RF switch path */ if ((strncmp(input, "WLG", 3) == 0) || (strncmp(input, "1", 1) == 0)) { pmp_priv->rf_path_cfg = SWITCH_TO_WLG; sprintf(extra, "switch rf path WLG\n"); } else if ((strncmp(input, "WLA", 3) == 0) || (strncmp(input, "2", 1) == 0)) { pmp_priv->rf_path_cfg = SWITCH_TO_WLA; sprintf(extra, "switch rf path WLA\n"); } else if ((strncmp(input, "BTG", 3) == 0) || (strncmp(input, "0", 1) == 0)) { pmp_priv->rf_path_cfg = SWITCH_TO_BTG; sprintf(extra, "switch rf path BTG\n"); } else if ((strncmp(input, "BT", 3) == 0) || (strncmp(input, "3", 1) == 0)) { pmp_priv->rf_path_cfg = SWITCH_TO_BT; sprintf(extra, "switch rf path BT\n"); } else { pmp_priv->rf_path_cfg = SWITCH_TO_WLG; sprintf(extra, "Error input, default set WLG\n"); return -EFAULT; } mp_phy_switch_rf_path_set(padapter, &pmp_priv->rf_path_cfg); #endif wrqu->length = strlen(extra); return ret; } int rtw_mp_QueryDrv(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); char input[RTW_IWD_MAX_LEN]; int qAutoLoad = 1; //struct efuse_info *efuse = adapter_to_efuse(padapter); if (copy_from_user(input, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; RTW_INFO("%s:iwpriv in=%s\n", __func__, input); qAutoLoad = strncmp(input, "autoload", 8); /* strncmp TRUE is 0*/ if (qAutoLoad == 0) { RTW_INFO("%s:qAutoLoad\n", __func__); //if (efuse->is_autoload_fail) // sprintf(extra, "fail"); //else // sprintf(extra, "ok"); } wrqu->data.length = strlen(extra) + 1; return 0; } int rtw_mp_PwrCtlDM(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); u8 input[RTW_IWD_MAX_LEN]; u8 pwrtrk_state = 0; u8 pwtk_type[5][25] = {"Thermal tracking off","Thermal tracking on", "TSSI tracking off","TSSI tracking on","TSSI calibration"}; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; RTW_INFO("%s: in=%s\n", __func__, input); if (wrqu->length == 2) { if(input[0] >= '0' && input[0] <= '4') { pwrtrk_state = rtw_atoi(input); /*MPT_PwrCtlDM(padapter, pwrtrk_state);*/ sprintf(extra, "PwrCtlDM start %s\n" , pwtk_type[pwrtrk_state]); } else { sprintf(extra, "Error unknown number ! Please check your input number\n" " 0 : Thermal tracking off\n 1 : Thermal tracking on\n 2 : TSSI tracking off\n" " 3 : TSSI tracking on\n 4 : TSSI calibration\n"); } wrqu->length = strlen(extra); return 0; } if (strncmp(input, "start", 5) == 0 || strncmp(input, "thertrk on", 10) == 0) {/* strncmp TRUE is 0*/ pwrtrk_state = 1; sprintf(extra, "PwrCtlDM start %s\n" , pwtk_type[pwrtrk_state]); } else if (strncmp(input, "thertrk off", 11) == 0 || strncmp(input, "stop", 5) == 0) { pwrtrk_state = 0; sprintf(extra, "PwrCtlDM stop %s\n" , pwtk_type[pwrtrk_state]); } else if (strncmp(input, "tssitrk off", 11) == 0){ pwrtrk_state = 2; sprintf(extra, "PwrCtlDM stop %s\n" , pwtk_type[pwrtrk_state]); } else if (strncmp(input, "tssitrk on", 10) == 0){ pwrtrk_state = 3; sprintf(extra, "PwrCtlDM start %s\n" , pwtk_type[pwrtrk_state]); } else if (strncmp(input, "tssik", 5) == 0){ pwrtrk_state = 4; sprintf(extra, "PwrCtlDM start %s\n" , pwtk_type[pwrtrk_state]); } else { pwrtrk_state = 0; sprintf(extra, "Error input, default PwrCtlDM stop\n" " thertrk off : Thermal tracking off\n thertrk on : Thermal tracking on\n" " tssitrk off : TSSI tracking off\n tssitrk on : TSSI tracking on\n tssik : TSSI calibration\n\n" " 0 : Thermal tracking off\n 1 : Thermal tracking on\n 2 : TSSI tracking off\n" " 3 : TSSI tracking on\n 4 : TSSI calibration\n"); } /*MPT_PwrCtlDM(padapter, pwrtrk_state);*/ wrqu->length = strlen(extra); return 0; } int rtw_mp_iqk(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); rtw_mp_trigger_iqk(padapter); return 0; } int rtw_mp_lck(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); rtw_mp_trigger_lck(padapter); return 0; } int rtw_mp_dpk(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); //struct dm_struct *phydm = adapter_to_phydm(padapter); struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter); u8 ips_mode = IPS_NUM; /* init invalid value */ u8 lps_mode = PM_PS_MODE_NUM; /* init invalid value */ if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; *(extra + wrqu->data.length) = '\0'; if (strncmp(extra, "off", 3) == 0 && strlen(extra) < 4) { //phydm->dpk_info.is_dpk_enable = 0; //halrf_dpk_enable_disable(phydm); sprintf(extra, "set dpk off\n"); } else if (strncmp(extra, "on", 2) == 0 && strlen(extra) < 3) { //phydm->dpk_info.is_dpk_enable = 1; //halrf_dpk_enable_disable(phydm); sprintf(extra, "set dpk on\n"); } else { #ifdef CONFIG_LPS lps_mode = pwrctrlpriv->power_mgnt;/* keep org value */ rtw_pm_set_lps(padapter, PM_PS_MODE_ACTIVE); #endif #ifdef CONFIG_IPS ips_mode = pwrctrlpriv->ips_mode;/* keep org value */ rtw_pm_set_ips(padapter, IPS_NONE); #endif rtw_mp_trigger_dpk(padapter); if (padapter->registrypriv.mp_mode == 0) { #ifdef CONFIG_IPS rtw_pm_set_ips(padapter, ips_mode); #endif /* CONFIG_IPS */ #ifdef CONFIG_LPS rtw_pm_set_lps(padapter, lps_mode); #endif /* CONFIG_LPS */ } sprintf(extra, "set dpk trigger\n"); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_get_tsside(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); char input[RTW_IWD_MAX_LEN]; u8 rfpath = 0xff; s8 tssi_de = 0; char pout_str_buf[7]; char tgr_str_buf[7]; u8 pout_signed_flag = 0 , tgrpwr_signed_flag = 0; int int_num = 0; u32 dec_num = 0; s32 pout = 0; s32 tgrpwr = 0; int i; if (wrqu->length > 128) return -EFAULT; _rtw_memset(input, 0, sizeof(input)); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; input[wrqu->length] = '\0'; if (wrqu->length == 2) { rfpath = rtw_atoi(input); if (rfpath >= 0 && rfpath <= 3) { tssi_de = rtw_mp_get_tssi_de(padapter, rfpath); } else sprintf(extra, "Invalid command format, please indicate RF path 0/1/2/3"); } else if (sscanf(input + 1, "dbm=%7s pwr=%7s", tgr_str_buf , pout_str_buf) == 2) { /* * rtwpriv wlan0 mp_get_tsside adbm=12 pwr=12 * [adbm] target power [pwr] output power * rf_path : 0 = adbm , 1 = bdbm * dbm : -15.00 ~ 25.00 * pwr : -15.00 ~ 25.00 * ex : rtwpriv wlan0 mp_get_tsside adbm=16 pwr=14.25 */ RTW_INFO("%s: in=tgr_str %s pout_str %s\n", __func__, tgr_str_buf , pout_str_buf); switch (input[0]) { case 'a': rfpath = RF_PATH_A; break; case 'b': rfpath = RF_PATH_B; break; case 'c': rfpath = RF_PATH_C; break; case 'd': rfpath = RF_PATH_D; break; default: goto error; break; } if(pout_str_buf[0] == '-') pout_signed_flag = 1; i = sscanf(pout_str_buf, "%d.%2u", &int_num, &dec_num); pout = int_num * 100; RTW_DBG("%s:pout %d int %d dec %d\n", __func__, pout, int_num , dec_num); if (i == 2) { /* Convert decimal number * ex : 0.1 => 100, -0.1 => 100*/ dec_num = (dec_num < 1) ? dec_num * 10 : dec_num; dec_num = (dec_num < 10) ? dec_num * 1 : dec_num; pout += ((pout < 0 || pout_signed_flag == 1) ? -dec_num : dec_num); } if (pout < -1500 || 2500 < pout) goto error; RTW_INFO("%s:pout %d\n", __func__, pout); if (tgr_str_buf[0] == '-') tgrpwr_signed_flag = 1; int_num = 0; dec_num = 0; i = sscanf(tgr_str_buf, "%d.%2u", &int_num, &dec_num); tgrpwr = int_num * 100; RTW_DBG("%s:tgrpwr %d int %d dec %d\n", __func__, tgrpwr, int_num , dec_num); if (i == 2) { /* Convert decimal number * ex : 0.1 => 100, -0.1 => 100*/ dec_num = (dec_num < 1) ? dec_num * 10 : dec_num; dec_num = (dec_num < 10) ? dec_num * 1 : dec_num; tgrpwr += ((tgrpwr < 0 || tgrpwr_signed_flag == 1) ? -dec_num : dec_num); } if (tgrpwr < -1500 || 2500 < tgrpwr) goto error; RTW_INFO("%s:tgrpwr %d\n", __func__, tgrpwr); tssi_de = (s8)rtw_mp_get_online_tssi_de(padapter, pout, tgrpwr, rfpath); } if (rfpath == 0) sprintf(extra, "patha=%d hex:%x", tssi_de, (u8)tssi_de); else if (rfpath == 1) sprintf(extra, "pathb=%d hex:%x", tssi_de, (u8)tssi_de); else if (rfpath == 2) sprintf(extra, "pathc=%d hex:%x", tssi_de, (u8)tssi_de); else if (rfpath == 3) sprintf(extra, "pathd=%d hex:%x", tssi_de, (u8)tssi_de); else goto error; wrqu->length = strlen(extra); return 0; error: sprintf(extra, "Invalid command format, please indicate RF path mp_get_tsside [0/1/2/3]\n\ GET ONLINE TSSI DE:\n\ mp_get_tsside adbm=-15.00 ~ 25.00 pwr=-15.00 ~ 25.00\n\ mp_get_tsside bdbm=-15.00 ~ 25.00 pwr=-15.00 ~ 25.00\n"); wrqu->length = strlen(extra); return 0; } int rtw_mp_set_tsside(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { u32 tsside_val = 0; u8 rf_path = RF_PATH_A; char input[RTW_IWD_MAX_LEN]; _adapter *padapter = rtw_netdev_priv(dev); if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; RTW_INFO("%s:input =[%s]\n", __func__, input); switch (input[4]) { case 'a': rf_path = RF_PATH_A; break; case 'b': rf_path = RF_PATH_B; break; case 'c': rf_path = RF_PATH_C; break; case 'd': rf_path = RF_PATH_D; break; default: goto exit_err; } if ((sscanf(input+5, "=0x%x", &tsside_val) == 1) || (sscanf(input+5, "=%d", &tsside_val) == 1)) { if (tsside_val > 255) sprintf(extra, "Error TSSI DE value: %d over 255" , tsside_val); else { sprintf(extra, "Set TSSI DE path_%s: %d", rf_path == RF_PATH_A ? "A" : rf_path == RF_PATH_B ? "B" : rf_path == RF_PATH_C ? "C":"D", tsside_val); rtw_mp_set_tsside2verify(padapter, tsside_val, rf_path); } } else goto exit_err; wrqu->length = strlen(extra); return 0; exit_err: sprintf(extra, "Invalid command format,\n\t\t" "please input TSSI DE value within patha/b/c/d=[decimal] or [hex:0xXX]"); wrqu->length = strlen(extra); return 0; } int rtw_mp_getver(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv; pmp_priv = &padapter->mppriv; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; sprintf(extra, "rtwpriv=%d\n", RTWPRIV_VER_INFO); wrqu->data.length = strlen(extra); return 0; } int rtw_mp_mon(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = &padapter->mppriv; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; //struct hal_ops *pHalFunc = &hal->hal_func; NDIS_802_11_NETWORK_INFRASTRUCTURE networkType; int bstart = 1, bstop = 1; networkType = Ndis802_11Infrastructure; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; *(extra + wrqu->data.length) = '\0'; rtw_pm_set_ips(padapter, IPS_NONE); LeaveAllPowerSaveMode(padapter); #if 0 //def CONFIG_MP_INCLUDED if (init_mp_priv(padapter) == _FAIL) RTW_INFO("%s: initialize MP private data Fail!\n", __func__); padapter->mppriv.channel = 6; bstart = strncmp(extra, "start", 5); /* strncmp TRUE is 0*/ bstop = strncmp(extra, "stop", 4); /* strncmp TRUE is 0*/ if (bstart == 0) { mp_join(padapter, WIFI_FW_ADHOC_STATE); SetPacketRx(padapter, _TRUE, _FALSE); SetChannel(padapter); pmp_priv->rx_bindicatePkt = _TRUE; pmp_priv->bRTWSmbCfg = _TRUE; sprintf(extra, "monitor mode start\n"); } else if (bstop == 0) { SetPacketRx(padapter, _FALSE, _FALSE); pmp_priv->rx_bindicatePkt = _FALSE; pmp_priv->bRTWSmbCfg = _FALSE; padapter->registrypriv.mp_mode = 1; pHalFunc->hal_deinit(padapter); padapter->registrypriv.mp_mode = 0; pHalFunc->hal_init(padapter); /*rtw_disassoc_cmd(padapter, 0, 0);*/ if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) { rtw_disassoc_cmd(padapter, 500, 0); rtw_indicate_disconnect(padapter, 0, _FALSE); /*rtw_free_assoc_resources_cmd(padapter, _TRUE, 0);*/ } rtw_pm_set_ips(padapter, IPS_NORMAL); sprintf(extra, "monitor mode Stop\n"); } #endif wrqu->data.length = strlen(extra); return 0; } int rtw_mp_pretx_proc(_adapter *padapter, u8 bstart, char *extra) { struct mp_priv *pmp_priv = &padapter->mppriv; char *pextra = extra; switch (pmp_priv->mode) { case MP_PACKET_TX: if (bstart == 0) { pmp_priv->tx.stop = 1; pmp_priv->mode = MP_ON; sprintf(extra, "Stop continuous Tx"); } else if (pmp_priv->tx.stop == 1) { pextra = extra + strlen(extra); pextra += sprintf(pextra, "\nStart continuous DA=ffffffffffff len=1500 count=%u\n", pmp_priv->tx.count); pmp_priv->tx.stop = 0; /*SetPacketTx(padapter);*/ } else return -EFAULT; rtw_set_phl_packet_tx(padapter, bstart); return 0; case MP_SINGLE_TONE_TX: if (bstart != 0) strcat(extra, "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes."); rtw_mp_singletone_tx(padapter, (u8)bstart); break; case MP_CONTINUOUS_TX: if (bstart != 0) strcat(extra, "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes."); rtw_mp_continuous_tx(padapter, (u8)bstart); break; case MP_CARRIER_SUPPRISSION_TX: if (bstart != 0) { if (rtw_mp_hwrate2mptrate(pmp_priv->rateidx) <= MPT_RATE_11M) strcat(extra, "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes."); else strcat(extra, "\nSpecify carrier suppression but not CCK rate"); } rtw_mp_carriersuppr_tx(padapter, (u8)bstart); break; case MP_SINGLE_CARRIER_TX: if (bstart != 0) strcat(extra, "\nStart continuous DA=ffffffffffff len=1500\n infinite=yes."); rtw_mp_singlecarrier_tx(padapter, (u8)bstart); break; default: sprintf(extra, "Error! Continuous-Tx is not on-going."); return -EFAULT; } if (bstart == 1 && pmp_priv->mode != MP_ON) { struct mp_priv *pmp_priv = &padapter->mppriv; if (pmp_priv->tx.stop == 0) { pmp_priv->tx.stop = 1; rtw_msleep_os(5); } #ifdef CONFIG_80211N_HT if(padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode)) pmp_priv->tx.attrib.ht_en = 1; #endif pmp_priv->tx.stop = 0; pmp_priv->tx.count = 1; if (pmp_priv->rtw_mp_tx_method == RTW_MP_PMACT_TX) { pmp_priv->rtw_mp_tx_method = RTW_MP_TMACT_TX; rtw_set_phl_packet_tx(padapter, bstart); /* send 1 pkt for trigger HW non-pkt Tx*/ pmp_priv->rtw_mp_tx_method = RTW_MP_PMACT_TX; } /*SetPacketTx(padapter);*/ } else pmp_priv->mode = MP_ON; return 0; } int rtw_mp_tx(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = &padapter->mppriv; PMPT_CONTEXT pMptCtx = &(padapter->mppriv.mpt_ctx); char *pextra = extra; u32 bandwidth = 0, sg = 0, channel = 6, txpower = 40, rate = 108, ant = 0, txmode = 1, count = 0; u8 bStartTest = 1, status = 0; #ifdef CONFIG_MP_VHT_HW_TX_MODE u8 Idx = 0, tmpU1B; #endif u16 antenna = 0; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; RTW_INFO("extra = %s\n", extra); #if 0 #ifdef CONFIG_CONCURRENT_MODE if (!is_primary_adapter(padapter)) { sprintf(extra, "Error: MP mode can't support Virtual adapter, Please to use main adapter.\n"); wrqu->data.length = strlen(extra); return 0; } #endif if (strncmp(extra, "stop", 3) == 0) { bStartTest = 0; /* To set Stop*/ pmp_priv->tx.stop = 1; sprintf(extra, "Stop continuous Tx"); status = rtw_mp_pretx_proc(padapter, bStartTest, extra); wrqu->data.length = strlen(extra); return status; } else if (strncmp(extra, "count", 5) == 0) { if (sscanf(extra, "count=%d", &count) < 1) RTW_INFO("Got Count=%d]\n", count); pmp_priv->tx.count = count; return 0; } else if (strncmp(extra, "setting", 7) == 0) { _rtw_memset(extra, 0, wrqu->data.length); pextra += sprintf(pextra, "Current Setting :\n Channel:%d", pmp_priv->channel); pextra += sprintf(pextra, "\n Bandwidth:%d", pmp_priv->bandwidth); pextra += sprintf(pextra, "\n Rate index:%d", pmp_priv->rateidx); pextra += sprintf(pextra, "\n TxPower index:%d", pmp_priv->txpoweridx); pextra += sprintf(pextra, "\n Antenna TxPath:%d", pmp_priv->antenna_tx); pextra += sprintf(pextra, "\n Antenna RxPath:%d", pmp_priv->antenna_rx); pextra += sprintf(pextra, "\n MP Mode:%d", pmp_priv->mode); wrqu->data.length = strlen(extra); return 0; #ifdef CONFIG_MP_VHT_HW_TX_MODE } else if (strncmp(extra, "pmact", 5) == 0) { if (strncmp(extra, "pmact=", 6) == 0) { _rtw_memset(&pMptCtx->PMacTxInfo, 0, sizeof(pMptCtx->PMacTxInfo)); if (strncmp(extra, "pmact=start", 11) == 0) { pMptCtx->PMacTxInfo.bEnPMacTx = _TRUE; sprintf(extra, "Set PMac Tx Mode start\n"); } else { pMptCtx->PMacTxInfo.bEnPMacTx = _FALSE; sprintf(extra, "Set PMac Tx Mode Stop\n"); } if (pMptCtx->bldpc == TRUE) pMptCtx->PMacTxInfo.bLDPC = _TRUE; if (pMptCtx->bstbc == TRUE) pMptCtx->PMacTxInfo.bSTBC = _TRUE; pMptCtx->PMacTxInfo.bSPreamble = pmp_priv->preamble; pMptCtx->PMacTxInfo.bSGI = pmp_priv->preamble; pMptCtx->PMacTxInfo.BandWidth = pmp_priv->bandwidth; pMptCtx->PMacTxInfo.TX_RATE = HwRateToMPTRate(pmp_priv->rateidx); pMptCtx->PMacTxInfo.Mode = pMptCtx->HWTxmode; pMptCtx->PMacTxInfo.NDP_sound = FALSE;/*(adapter.PacketType == NDP_PKT)?TRUE:FALSE;*/ if (padapter->mppriv.pktInterval == 0) pMptCtx->PMacTxInfo.PacketPeriod = 100; else pMptCtx->PMacTxInfo.PacketPeriod = padapter->mppriv.pktInterval; if (padapter->mppriv.pktLength < 1000) pMptCtx->PMacTxInfo.PacketLength = 1000; else pMptCtx->PMacTxInfo.PacketLength = padapter->mppriv.pktLength; pMptCtx->PMacTxInfo.PacketPattern = rtw_random32() % 0xFF; if (padapter->mppriv.tx_pktcount != 0) pMptCtx->PMacTxInfo.PacketCount = padapter->mppriv.tx_pktcount; pMptCtx->PMacTxInfo.Ntx = 0; for (Idx = 16; Idx < 20; Idx++) { tmpU1B = (padapter->mppriv.antenna_tx >> Idx) & 1; if (tmpU1B) pMptCtx->PMacTxInfo.Ntx++; } _rtw_memset(pMptCtx->PMacTxInfo.MacAddress, 0xFF, ETH_ALEN); PMAC_Get_Pkt_Param(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); if (MPT_IS_CCK_RATE(pMptCtx->PMacTxInfo.TX_RATE)) CCK_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); else { PMAC_Nsym_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); /* 24 BIT*/ L_SIG_generator(pMptCtx->PMacPktInfo.N_sym, &pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); } /* 48BIT*/ if (MPT_IS_HT_RATE(pMptCtx->PMacTxInfo.TX_RATE)) HT_SIG_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); else if (MPT_IS_VHT_RATE(pMptCtx->PMacTxInfo.TX_RATE)) { /* 48BIT*/ VHT_SIG_A_generator(&pMptCtx->PMacTxInfo, &pMptCtx->PMacPktInfo); /* 26/27/29 BIT & CRC 8 BIT*/ VHT_SIG_B_generator(&pMptCtx->PMacTxInfo); /* 32 BIT*/ VHT_Delimiter_generator(&pMptCtx->PMacTxInfo); } mpt_ProSetPMacTx(padapter); } else if (strncmp(extra, "pmact,mode=", 11) == 0) { int txmode = 0; if (sscanf(extra, "pmact,mode=%d", &txmode) > 0) { if (txmode == 1) { pMptCtx->HWTxmode = CONTINUOUS_TX; sprintf(extra, "\t Config HW Tx mode = CONTINUOUS_TX\n"); } else if (txmode == 2) { pMptCtx->HWTxmode = OFDM_Single_Tone_TX; sprintf(extra, "\t Config HW Tx mode = OFDM_Single_Tone_TX\n"); } else { pMptCtx->HWTxmode = PACKETS_TX; sprintf(extra, "\t Config HW Tx mode = PACKETS_TX\n"); } } else { pMptCtx->HWTxmode = PACKETS_TX; sprintf(extra, "\t Config HW Tx mode=\n 0 = PACKETS_TX\n 1 = CONTINUOUS_TX\n 2 = OFDM_Single_Tone_TX"); } } else if (strncmp(extra, "pmact,", 6) == 0) { int PacketPeriod = 0, PacketLength = 0, PacketCout = 0; int bldpc = 0, bstbc = 0; if (sscanf(extra, "pmact,period=%d", &PacketPeriod) > 0) { padapter->mppriv.pktInterval = PacketPeriod; RTW_INFO("PacketPeriod=%d\n", padapter->mppriv.pktInterval); sprintf(extra, "PacketPeriod [1~255]= %d\n", padapter->mppriv.pktInterval); } else if (sscanf(extra, "pmact,length=%d", &PacketLength) > 0) { padapter->mppriv.pktLength = PacketLength; RTW_INFO("PacketPeriod=%d\n", padapter->mppriv.pktLength); sprintf(extra, "PacketLength[~65535]=%d\n", padapter->mppriv.pktLength); } else if (sscanf(extra, "pmact,count=%d", &PacketCout) > 0) { padapter->mppriv.tx_pktcount = PacketCout; RTW_INFO("Packet Cout =%d\n", padapter->mppriv.tx_pktcount); sprintf(extra, "Packet Cout =%d\n", padapter->mppriv.tx_pktcount); } else if (sscanf(extra, "pmact,ldpc=%d", &bldpc) > 0) { pMptCtx->bldpc = bldpc; RTW_INFO("Set LDPC =%d\n", pMptCtx->bldpc); sprintf(extra, "Set LDPC =%d\n", pMptCtx->bldpc); } else if (sscanf(extra, "pmact,stbc=%d", &bstbc) > 0) { pMptCtx->bstbc = bstbc; RTW_INFO("Set STBC =%d\n", pMptCtx->bstbc); sprintf(extra, "Set STBC =%d\n", pMptCtx->bstbc); } else sprintf(extra, "\n period={1~255}\n length={1000~65535}\n count={0~}\n ldpc={0/1}\n stbc={0/1}"); } wrqu->data.length = strlen(extra); return 0; #endif } else { if (sscanf(extra, "ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d", &channel, &bandwidth, &rate, &txpower, &ant, &txmode) < 6) { RTW_INFO("Invalid format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode); _rtw_memset(extra, 0, wrqu->data.length); pextra += sprintf(pextra, "\n Please input correct format as bleow:\n"); pextra += sprintf(pextra, "\t ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d\n", channel, bandwidth, rate, txpower, ant, txmode); pextra += sprintf(pextra, "\n [ ch : BGN = <1~14> , A or AC = <36~165> ]"); pextra += sprintf(pextra, "\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]"); pextra += sprintf(pextra, "\n [ rate : CCK: 1 2 5.5 11M X 2 = < 2 4 11 22 >]"); pextra += sprintf(pextra, "\n [ OFDM: 6 9 12 18 24 36 48 54M X 2 = < 12 18 24 36 48 72 96 108>"); pextra += sprintf(pextra, "\n [ HT 1S2SS MCS0 ~ MCS15 : < [MCS0]=128 ~ [MCS7]=135 ~ [MCS15]=143 >"); pextra += sprintf(pextra, "\n [ HT 3SS MCS16 ~ MCS32 : < [MCS16]=144 ~ [MCS23]=151 ~ [MCS32]=159 >"); pextra += sprintf(pextra, "\n [ VHT 1SS MCS0 ~ MCS9 : < [MCS0]=160 ~ [MCS9]=169 >"); pextra += sprintf(pextra, "\n [ txpower : 1~63 power index"); pextra += sprintf(pextra, "\n [ ant : ,2T ex: AB=3 BC=6 CD=12"); pextra += sprintf(pextra, "\n [ txmode : < 0 = CONTINUOUS_TX, 1 = PACKET_TX, 2 = SINGLE_TONE_TX, 3 = CARRIER_SUPPRISSION_TX, 4 = SINGLE_CARRIER_TX>\n"); wrqu->data.length = strlen(extra); return status; } else { char *pextra = extra; RTW_INFO("Got format [ch=%d,bw=%d,rate=%d,pwr=%d,ant=%d,tx=%d]\n", channel, bandwidth, rate, txpower, ant, txmode); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel); padapter->mppriv.channel = channel; SetChannel(padapter); pHalData->current_channel = channel; if (bandwidth == 1) bandwidth = CHANNEL_WIDTH_40; else if (bandwidth == 2) bandwidth = CHANNEL_WIDTH_80; pextra = extra + strlen(pextra); pextra += sprintf(pextra, "\nChange Current Bandwidth %d to Bandwidth %d", padapter->mppriv.bandwidth, bandwidth); padapter->mppriv.bandwidth = (u8)bandwidth; padapter->mppriv.preamble = sg; SetBandwidth(padapter); pHalData->current_channel_bw = bandwidth; pextra += sprintf(pextra, "\nSet power level :%d", txpower); padapter->mppriv.txpoweridx = (u8)txpower; pMptCtx->TxPwrLevel[RF_PATH_A] = (u8)txpower; pMptCtx->TxPwrLevel[RF_PATH_B] = (u8)txpower; pMptCtx->TxPwrLevel[RF_PATH_C] = (u8)txpower; pMptCtx->TxPwrLevel[RF_PATH_D] = (u8)txpower; SetTxPower(padapter); RTW_INFO("%s: bw=%d sg=%d\n", __func__, bandwidth, sg); if (rate <= 0x7f) rate = wifirate2_ratetbl_inx((u8)rate); else if (rate < 0xC8) rate = (rate - 0x80 + MPT_RATE_MCS0); /*HT rate 0x80(MCS0) ~ 0x8F(MCS15) ~ 0x9F(MCS31) 128~159 VHT1SS~2SS rate 0xA0 (VHT1SS_MCS0 44) ~ 0xB3 (VHT2SS_MCS9 #63) 160~179 VHT rate 0xB4 (VHT3SS_MCS0 64) ~ 0xC7 (VHT2SS_MCS9 #83) 180~199 else VHT rate 0x90(VHT1SS_MCS0) ~ 0x99(VHT1SS_MCS9) 144~153 rate =(rate - MPT_RATE_VHT1SS_MCS0); */ RTW_INFO("%s: rate index=%d\n", __func__, rate); if (rate >= MPT_RATE_LAST) return -EINVAL; pextra += sprintf(pextra, "\nSet data rate to %d index %d", padapter->mppriv.rateidx, rate); padapter->mppriv.rateidx = rate; pMptCtx->mpt_rate_index = rate; SetDataRate(padapter); pextra += sprintf(pextra, "\nSet Antenna Path :%d", ant); switch (ant) { case 1: antenna = ANTENNA_A; break; case 2: antenna = ANTENNA_B; break; case 4: antenna = ANTENNA_C; break; case 8: antenna = ANTENNA_D; break; case 3: antenna = ANTENNA_AB; break; case 5: antenna = ANTENNA_AC; break; case 9: antenna = ANTENNA_AD; break; case 6: antenna = ANTENNA_BC; break; case 10: antenna = ANTENNA_BD; break; case 12: antenna = ANTENNA_CD; break; case 7: antenna = ANTENNA_ABC; break; case 14: antenna = ANTENNA_BCD; break; case 11: antenna = ANTENNA_ABD; break; case 15: antenna = ANTENNA_ABCD; break; } RTW_INFO("%s: antenna=0x%x\n", __func__, antenna); padapter->mppriv.antenna_tx = antenna; padapter->mppriv.antenna_rx = antenna; pHalData->antenna_tx_path = antenna; SetAntenna(padapter); if (txmode == 0) pmp_priv->mode = MP_CONTINUOUS_TX; else if (txmode == 1) { pmp_priv->mode = MP_PACKET_TX; pmp_priv->tx.count = count; } else if (txmode == 2) pmp_priv->mode = MP_SINGLE_TONE_TX; else if (txmode == 3) pmp_priv->mode = MP_CARRIER_SUPPRISSION_TX; else if (txmode == 4) pmp_priv->mode = MP_SINGLE_CARRIER_TX; status = rtw_mp_pretx_proc(padapter, bStartTest, extra); } } #endif wrqu->data.length = strlen(extra); return status; } int rtw_mp_rx(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = &padapter->mppriv; char *pextra = extra; u32 bandwidth = 0, sg = 0, channel = 6, ant = 0; u16 antenna = 0; u8 bStartRx = 0; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; #if 0 #ifdef CONFIG_CONCURRENT_MODE if (!is_primary_adapter(padapter)) { sprintf(extra, "Error: MP mode can't support Virtual adapter, Please to use main adapter.\n"); wrqu->data.length = strlen(extra); return 0; } #endif if (strncmp(extra, "stop", 4) == 0) { _rtw_memset(extra, 0, wrqu->data.length); SetPacketRx(padapter, bStartRx, _FALSE); pmp_priv->bmac_filter = _FALSE; sprintf(extra, "Received packet OK:%d CRC error:%d ,Filter out:%d", padapter->mppriv.rx_pktcount, padapter->mppriv.rx_crcerrpktcount, padapter->mppriv.rx_pktcount_filter_out); wrqu->data.length = strlen(extra); return 0; } else if (sscanf(extra, "ch=%d,bw=%d,ant=%d", &channel, &bandwidth, &ant) < 3) { RTW_INFO("Invalid format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant); _rtw_memset(extra, 0, wrqu->data.length); pextra += sprintf(pextra, "\n Please input correct format as bleow:\n"); pextra += sprintf(pextra, "\t ch=%d,bw=%d,ant=%d\n", channel, bandwidth, ant); pextra += sprintf(pextra, "\n [ ch : BGN = <1~14> , A or AC = <36~165> ]"); pextra += sprintf(pextra, "\n [ bw : Bandwidth: 0 = 20M, 1 = 40M, 2 = 80M ]"); pextra += sprintf(pextra, "\n [ ant : ,2T ex: AB=3 BC=6 CD=12"); wrqu->data.length = strlen(extra); return 0; } else { char *pextra = extra; bStartRx = 1; RTW_INFO("Got format [ch=%d,bw=%d,ant=%d]\n", channel, bandwidth, ant); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Change Current channel %d to channel %d", padapter->mppriv.channel , channel); padapter->mppriv.channel = channel; SetChannel(padapter); pHalData->current_channel = channel; if (bandwidth == 1) bandwidth = CHANNEL_WIDTH_40; else if (bandwidth == 2) bandwidth = CHANNEL_WIDTH_80; pextra = extra + strlen(extra); pextra += sprintf(pextra, "\nChange Current Bandwidth %d to Bandwidth %d", padapter->mppriv.bandwidth, bandwidth); padapter->mppriv.bandwidth = (u8)bandwidth; padapter->mppriv.preamble = sg; SetBandwidth(padapter); pHalData->current_channel_bw = bandwidth; pextra += sprintf(pextra, "\nSet Antenna Path :%d", ant); switch (ant) { case 1: antenna = ANTENNA_A; break; case 2: antenna = ANTENNA_B; break; case 4: antenna = ANTENNA_C; break; case 8: antenna = ANTENNA_D; break; case 3: antenna = ANTENNA_AB; break; case 5: antenna = ANTENNA_AC; break; case 9: antenna = ANTENNA_AD; break; case 6: antenna = ANTENNA_BC; break; case 10: antenna = ANTENNA_BD; break; case 12: antenna = ANTENNA_CD; break; case 7: antenna = ANTENNA_ABC; break; case 14: antenna = ANTENNA_BCD; break; case 11: antenna = ANTENNA_ABD; break; case 15: antenna = ANTENNA_ABCD; break; } RTW_INFO("%s: antenna=0x%x\n", __func__, antenna); padapter->mppriv.antenna_tx = antenna; padapter->mppriv.antenna_rx = antenna; pHalData->antenna_tx_path = antenna; SetAntenna(padapter); strcat(extra, "\nstart Rx"); SetPacketRx(padapter, bStartRx, _FALSE); } #endif wrqu->data.length = strlen(extra); return 0; } int rtw_mp_hwtx(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = &padapter->mppriv; PMPT_CONTEXT mpt_ctx = &(padapter->mppriv.mpt_ctx); #if defined(CONFIG_RTL8821B) || defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; *(extra + wrqu->data.length) = '\0'; _rtw_memset(&mpt_ctx->PMacTxInfo, 0, sizeof(RT_PMAC_TX_INFO)); _rtw_memcpy((void *)&mpt_ctx->PMacTxInfo, (void *)extra, sizeof(RT_PMAC_TX_INFO)); _rtw_memset(extra, 0, wrqu->data.length); if (mpt_ctx->PMacTxInfo.bEnPMacTx == 1 && pmp_priv->mode != MP_ON) { sprintf(extra, "MP Tx Running, Please Set PMac Tx Mode Stop\n"); RTW_INFO("Error !!! MP Tx Running, Please Set PMac Tx Mode Stop\n"); } else { RTW_INFO("To set MAC Tx mode\n"); mpt_ProSetPMacTx(padapter); sprintf(extra, "Set PMac Tx Mode OK\n"); } wrqu->data.length = strlen(extra); #endif return 0; } int rtw_mp_pwrlmt(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct registry_priv *registry_par = &padapter->registrypriv; u8 pwrlimtstat = 0; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; *(extra + wrqu->data.length) = '\0'; #if CONFIG_TXPWR_LIMIT if (strncmp(extra, "off", 3) == 0 && strlen(extra) < 4) { if (rtw_mpt_set_power_limit_en(padapter, _FALSE)) sprintf(extra, "Turn off Power Limit\n"); else sprintf(extra, "Turn off Power Limit Fail\n"); } else if (strncmp(extra, "on", 2) == 0 && strlen(extra) < 3) { if (rtw_mpt_set_power_limit_en(padapter, _TRUE)) sprintf(extra, "Turn on Power Limit\n"); else sprintf(extra, "Turn on Power Limit Fail\n"); } else #endif { sprintf(extra, "PHL PWRLMT:%s\n", (rtw_mpt_get_power_limit_en(padapter) == _TRUE) ?"ON" :"OFF"); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_dpk_track(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); //struct dm_struct *phydm = adapter_to_phydm(padapter); if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; *(extra + wrqu->data.length) = '\0'; if (strncmp(extra, "off", 3) == 0 && strlen(extra) < 4) { //halrf_set_dpk_track(phydm, FALSE); sprintf(extra, "set dpk track off\n"); } else if (strncmp(extra, "on", 2) == 0 && strlen(extra) < 3) { //halrf_set_dpk_track(phydm, TRUE); sprintf(extra, "set dpk track on\n"); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_set_phl_io(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct phl_info_t *phl_info = (struct phl_info_t *)(dvobj->phl); struct rtw_mp_cmd_arg *cmd_arg = NULL; struct rtw_mp_test_cmdbuf *pcmdbuf = NULL; u16 i = 0; if (copy_from_user(extra, wrqu->pointer, wrqu->length)) return -EFAULT; RTW_INFO("%s, wrqu->length %d !!!\n", __func__, wrqu->length); rtw_phl_test_submodule_cmd_process(rtw_phl_get_com(phl_info), (void*)extra, wrqu->length); pcmdbuf = (struct rtw_mp_test_cmdbuf *)extra; while (1) { if (pcmdbuf) { cmd_arg = (struct rtw_mp_cmd_arg *)pcmdbuf->buf; rtw_phl_test_submodule_get_rpt(rtw_phl_get_com(phl_info), (void *)extra, wrqu->length); } if (cmd_arg != NULL && cmd_arg->cmd_ok) { RTW_INFO("%s,GET CMD OK !!!\n", __func__); break; } else { i++; rtw_msleep_os(100); if (i == 3) { RTW_INFO("%s,GET CMD FAIL !!!\n", __func__); break; } } } if (copy_to_user(wrqu->pointer, extra, wrqu->length)) return -EFAULT; return 0; } int rtw_mp_get_phl_io(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); struct phl_info_t *phl_info = (struct phl_info_t *)(padapter->dvobj->phl); if (copy_from_user(extra, wrqu->pointer, wrqu->length)) return -EFAULT; *(extra + wrqu->length) = '\0'; rtw_phl_test_submodule_get_rpt(rtw_phl_get_com(phl_info), (void *)&extra, wrqu->length); wrqu->length = strlen(extra); return 0; } int rtw_mp_tx_pattern_idx(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u32 tx_patt_idx = 0; u32 ppdu_type = 0; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; if (sscanf(extra, "index=%d,type=%d", &tx_patt_idx, &ppdu_type) > 0) { RTW_INFO("%s: tx_patt_idx=%d ,ppdu_type=%d\n", __func__, tx_patt_idx , ppdu_type); pmp_priv->rtw_mp_pmact_patt_idx = tx_patt_idx; pmp_priv->rtw_mp_pmact_ppdu_type = ppdu_type; rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_CONFIG_PLCP_PATTERN, pmp_priv->rtw_mp_tx_method, _TRUE); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config Tx Pattern idx %d to %d", pmp_priv->rtw_mp_pmact_patt_idx, tx_patt_idx); } else if ((strncmp(extra, "stop", 4) == 0)) { rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_CONFIG_PLCP_PATTERN, pmp_priv->rtw_mp_tx_method, _FALSE); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config Tx Pattern Stop"); } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_tx_plcp_tx_data(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 user_idx = pmp_priv->mp_plcp_useridx; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; if ((strncmp(extra, "ppdu", 4) == 0)) { u32 ppdu_type = 0; if (sscanf(extra, "ppdu=%d", &ppdu_type) > 0) { u8 *pextra = extra; RTW_INFO("%s: ppdu_type=%d\n", __func__, ppdu_type); _rtw_memset(extra, 0, wrqu->data.length); pextra += sprintf(pextra, "Config PPDU Type %s to %s\n", PPDU_TYPE_STR(pmp_priv->rtw_mp_pmact_ppdu_type), PPDU_TYPE_STR(ppdu_type)); pmp_priv->rtw_mp_pmact_ppdu_type = ppdu_type; rtw_update_giltf(padapter); rtw_mp_update_coding(padapter); if (ppdu_type >= RTW_MP_TYPE_HE_MU_OFDMA) { u8 ru_num = 0 , rualloc_num = 0 ,i = 0; ru_num = rtw_mp_update_ru_tone(padapter); rualloc_num = rtw_mp_update_ru_alloc(padapter); pextra += sprintf(pextra, "\nCurrent [%s] RU Alloc index:%d\n", RU_TONE_STR(pmp_priv->rtw_mp_ru_tone), pmp_priv->mp_plcp_user[user_idx].ru_alloc); pextra += sprintf(pextra, "RU Alloc list:["); for (i = 0;i <= rualloc_num - 1; i++) pextra += sprintf(pextra, "%d ", pmp_priv->ru_alloc_list[i]); pextra += sprintf(pextra, "]\n"); pextra += sprintf(pextra, "\nRU Tone support list(Refer Coding:%s):\n", (pmp_priv->mp_plcp_user[user_idx].coding ? "LDPC":"BCC")); for (i = 0;i <= ru_num; i++) pextra += sprintf(pextra, "%d : [%s]\n", pmp_priv->ru_tone_sel_list[i], RU_TONE_STR(pmp_priv->ru_tone_sel_list[i])); pextra += sprintf(pextra, "\n\nCodingCMD:[mp_plcp_user coding=%%d] (0:BCC 1:LDPC )"); pextra += sprintf(pextra, "\nRU Tone CMD:[ mp_plcp_user ru_tone=%%d ]"); pextra += sprintf(pextra, "\nRU Alloc CMD:[ mp_plcp_user ru_alloc=%%d ]"); } } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); pstr += sprintf(pstr, "CMD: [mp_plcp_datappdu=%%d]\nPLCP (PPDU Type):\n\ 0:CCK\n1:LEGACY\n2:HT_MF\n3:HT_GF\n4:VHT\n5:HE_SU\n6:HE_ER_SU\n7:HE_MU_OFDMA\n8:HE_TB\n"); } }else if ((strncmp(extra, "preamble", 8) == 0)) { u8 preamble = 0; if (sscanf(extra, "preamble=%hhd", &preamble) > 0) { RTW_INFO("%s: preamble=%d\n", __func__, preamble); _rtw_memset(extra, 0, wrqu->data.length); if (rtw_mp_is_cck_rate(pmp_priv->rateidx)) { pmp_priv->preamble = preamble; sprintf(extra, "Config Preamble %d to %d", pmp_priv->preamble, preamble); } else sprintf(extra, "Error !!! only B mode Rate for Preamble!\n"); } else sprintf(extra, "Error format ! input 'preamble=[num]'\n"); } else if ((strncmp(extra, "stbc", 4) == 0)) { u8 stbc = 0; if (sscanf(extra, "stbc=%hhd", &stbc) > 0) { RTW_INFO("%s: stbc=%d\n", __func__, stbc); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config STBC enable: %d to %d", pmp_priv->rtw_mp_stbc, stbc); pmp_priv->rtw_mp_stbc = stbc; if (pmp_priv->rtw_mp_stbc) pmp_priv->mp_plcp_user[user_idx].dcm = 0; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "input [stbc=0/1]"); } } else if ((strncmp(extra, "giltf", 5) == 0)) { u8 idx = 0; u8 giltf_num = rtw_update_giltf(padapter); if (sscanf(extra, "giltf=%hhd", &idx) > 0) { u8 gi = 0, ltf = 0; RTW_INFO("%s: gi+ltf=%d\n", __func__, idx); _rtw_memset(extra, 0, wrqu->data.length); if (giltf_num != 0 && idx <= giltf_num) { gi = pmp_priv->st_giltf[idx].gi; ltf = pmp_priv->st_giltf[idx].ltf; sprintf(extra, "Config GI+LTF to %s ", pmp_priv->st_giltf[idx].type_str); pmp_priv->rtw_mp_plcp_gi = gi; pmp_priv->rtw_mp_plcp_ltf = ltf; RTW_INFO("%s: gi=%d ltf=%d\n", __func__, gi, ltf); } else sprintf(extra, "Not support GI+LTF index\n"); } else { u8 *pextra = extra; u8 i = 0; if (giltf_num > 0) { pextra += sprintf(pextra, "GI + LTF list:\n"); for (i = 0;i <= giltf_num; i++) pextra += sprintf(pextra, "%d:[%s]\n", i, pmp_priv->st_giltf[i].type_str); } sprintf(pextra, "PPDU Type Not support GI+LTF."); } } else if ((strncmp(extra, "tx_time", 7) == 0)) { u32 tx_time = 0; if (sscanf(extra, "tx_time=%d", &tx_time) > 0) { u32 tmp_tx_time = (tx_time * 10) / 4; pmp_priv->rtw_mp_plcp_tx_time = tmp_tx_time; pmp_priv->rtw_mp_plcp_tx_mode = 1; sprintf(extra, "Config Tx Time:%d us", pmp_priv->rtw_mp_plcp_tx_time); } } else if ((strncmp(extra, "tx_len", 6) == 0)) { u32 tx_len = 0; if (sscanf(extra, "tx_len=%d", &tx_len) > 0) { pmp_priv->mp_plcp_user[user_idx].plcp_txlen = tx_len; pmp_priv->rtw_mp_plcp_tx_mode = 0; sprintf(extra, "Config Tx Len:%d", pmp_priv->mp_plcp_user[user_idx].plcp_txlen); } } else if ((strncmp(extra, "he_sigb", 7) == 0)) { u32 he_sigb = 0; if (sscanf(extra, "he_sigb=%d", &he_sigb) > 0) { if (he_sigb <= 5) { pmp_priv->rtw_mp_he_sigb = he_sigb; sprintf(extra, "Config HE SIGB:%d", he_sigb); } else sprintf(extra, "Error Config HE SIGB:[%d] (0~5)", he_sigb); } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); pstr += sprintf(pstr, "invalid CMD Format! input: he_sigb=[Num]\n\ PLCP (HE SIGB):\n0\n\1\n2\n\3\n\4\n\5\n"); } } else if ((strncmp(extra, "he_sigb_dcm", 7) == 0)) { u32 he_sigb_dcm = 0; if (sscanf(extra, "he_sigb_dcm=%d", &he_sigb_dcm) > 0) { if (he_sigb_dcm <= 1) { pmp_priv->rtw_mp_he_sigb_dcm = he_sigb_dcm; sprintf(extra, "Config HE SIGB DCM:%d", he_sigb_dcm); } else sprintf(extra, "Error Config HE SIGB:[%d] (0:Disable 1:Enable)", he_sigb_dcm); } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); pstr += sprintf(pstr, "invalid CMD Format! input: he_sigb_dcm=[Num]\n\ PLCP (HE SIGB DCM):\n0:Disable\n1:Enable"); } } else if ((strncmp(extra, "er_su_ru106en", 7) == 0)) { u32 ru106en = 0; if (sscanf(extra, "er_su_ru106en=%d", &ru106en) > 0) { if (ru106en <= 1) { pmp_priv->rtw_mp_he_er_su_ru_106_en = ru106en; sprintf(extra, "Config he_er_su_ru106:%d", ru106en); } else sprintf(extra, "Error!!! Config HE ER SU RU106 Enable:[%d] (0:Disable 1:Enable)", ru106en); } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); pstr += sprintf(pstr, "Error!!! Config HE ER SU RU106 Enable: Input number[ 0:Disable 1:Enable ]"); } } else if ((strncmp(extra, "ru_tone", 7) == 0)) { u32 ru_tone = 0; if (sscanf(extra, "ru_tone=%d", &ru_tone) > 0) { RTW_INFO("%s: RU Tone=%d\n", __func__, ru_tone); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config RU tone %d to %d", pmp_priv->rtw_mp_ru_tone, ru_tone); pmp_priv->rtw_mp_ru_tone = ru_tone; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error!!!\tinput , [ru_tone= number]"); } } else { char *pstr = extra; u8 ppdu_idx = pmp_priv->rtw_mp_pmact_ppdu_type; if (ppdu_idx < RTW_MP_TYPE_HT_MF) { pstr += sprintf(pstr, "invalid PPDU Type ! input :ppdu=[Num] over the HT\n"); } else { u8 i = 0; u8 num = rtw_update_giltf(padapter); _rtw_memset(extra, 0, wrqu->data.length); pstr += sprintf(pstr, "invalid CMD Format !! please input: giltf=[Num]\n"); pstr += sprintf(pstr, "PPDU %s GI+LTF:\n", PPDU_TYPE_STR(ppdu_idx)); for (i = 0; i <= num; i++) pstr += sprintf(pstr, "[%d]: %s\n" ,i , pmp_priv->st_giltf[i].type_str); } } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_tx_plcp_tx_user(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *mpprv = (struct mp_priv *)&padapter->mppriv; u32 tx_mcs = 0; u8 user_idx = mpprv->mp_plcp_useridx; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; if (sscanf(extra, "mcs=%d", &tx_mcs) > 0) { RTW_INFO("%s: mcs=%d\n", __func__, tx_mcs); mpprv->mp_plcp_user[user_idx].plcp_mcs = tx_mcs; _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config PLCP MCS idx %d to %d", mpprv->mp_plcp_user[user_idx].plcp_mcs, tx_mcs); } else if ((strncmp(extra, "dcm", 3) == 0)) { u8 dcm = 0; if (sscanf(extra, "dcm=%hhd", &dcm) > 0) { RTW_INFO("%s: dcm=%d\n", __func__, dcm); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config DCM enable: %d to %d", mpprv->mp_plcp_user[user_idx].dcm, dcm); mpprv->mp_plcp_user[user_idx].dcm = dcm; if (mpprv->mp_plcp_user[user_idx].dcm) mpprv->rtw_mp_stbc = 0; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error !!! input [dcm=0/1]"); } } else if ((strncmp(extra, "coding", 6) == 0)) { u8 coding = 0; if (sscanf(extra, "coding=%hhd", &coding) > 0) { RTW_INFO("%s: coding=%d\n", __func__, coding); _rtw_memset(extra, 0, wrqu->data.length); mpprv->mp_plcp_user[user_idx].coding = coding; rtw_mp_update_coding(padapter); sprintf(extra, "Config coding to %s", (mpprv->mp_plcp_user[user_idx].coding?"LDPC":"BCC")); } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error !!!\n0:BCC 1:LDPC \t input Number [coding=0/1]"); } } else if ((strncmp(extra, "ru_alloc", 8) == 0)) { u32 ru_alloc = 0; if (sscanf(extra, "ru_alloc=%d", &ru_alloc) > 0) { RTW_INFO("%s: RU alloc=%d\n", __func__, ru_alloc); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Config RU alloc %d to %d", mpprv->mp_plcp_user[user_idx].ru_alloc, ru_alloc); mpprv->mp_plcp_user[user_idx].ru_alloc = ru_alloc; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error!!!\tinput , [ru_alloc= number]"); } } else if ((strncmp(extra, "txuser", 6) == 0)) { u32 txuser = 0; if (sscanf(extra, "txuser=%d", &txuser) > 0) { RTW_INFO("%s: Sel User idx=%d\n", __func__, txuser); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "config Tx User %d to %d", mpprv->rtw_mp_plcp_tx_user, txuser); mpprv->rtw_mp_plcp_tx_user = txuser; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error!!!\tinput , [txuser= number]"); } } else if ((strncmp(extra, "user", 4) == 0)) { u32 user_idx = 0; if (sscanf(extra, "user=%d", &user_idx) > 0) { RTW_INFO("%s: Sel User idx=%d\n", __func__, user_idx); _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "select User idx %d to %d", mpprv->mp_plcp_useridx, user_idx); mpprv->mp_plcp_useridx = user_idx; } else { _rtw_memset(extra, 0, wrqu->data.length); sprintf(extra, "Error!!!\tinput , [user= number]"); } } else if ((strncmp(extra, "tx_len", 6) == 0)) { u32 tx_len = 0; if (sscanf(extra, "tx_len=%d", &tx_len) > 0) { mpprv->mp_plcp_user[user_idx].plcp_txlen = tx_len; mpprv->rtw_mp_plcp_tx_mode = 0; sprintf(extra, "Config Tx Len:%d", mpprv->mp_plcp_user[user_idx].plcp_txlen); } } else { u8 *pstr = extra; _rtw_memset(pstr, 0, wrqu->data.length); pstr += sprintf(pstr, "invalid CMD Format!\n \ \t input :\n\ \t user=%%d\n\ \t mcs=%%d\n\ \t dcm=%%d,\n\ \t coding=%%d\n\ \t ru_alloc=%%d\n"); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_tx_method(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; if ((strncmp(extra, "PMACT", 5) == 0)) { pmp_priv->rtw_mp_tx_method = RTW_MP_PMACT_TX; sprintf(extra, "set PMACT OK"); } else if ((strncmp(extra, "TMACT", 5) == 0)) { pmp_priv->rtw_mp_tx_method = RTW_MP_TMACT_TX; rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_MODE_SWITCH, pmp_priv->rtw_mp_tx_method, _FALSE); sprintf(extra, "set TMACT OK"); } else if ((strncmp(extra, "FWPMACT", 7) == 0)) { pmp_priv->rtw_mp_tx_method = RTW_MP_FW_PMACT_TX; rtw_phl_mp_tx_cmd(padapter, RTW_MP_TX_MODE_SWITCH, pmp_priv->rtw_mp_tx_method, _FALSE); sprintf(extra, "set FWPMACT OK"); } wrqu->data.length = strlen(extra); return 0; } int rtw_mp_config_phy(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 set_phy = 0; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; extra[wrqu->data.length] = '\0'; set_phy = rtw_atoi(extra); if (set_phy < 2) { sprintf(extra, "set current phy %d to %d", pmp_priv->rtw_mp_cur_phy, set_phy); pmp_priv->rtw_mp_cur_phy = set_phy; rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SET_PHY_INDEX); } else sprintf(extra, "Not suuport phy %d", set_phy); wrqu->data.length = strlen(extra); return 0; } int rtw_mp_phl_rfk(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 k_type = RTW_MP_CAL_MAX; u8 k_cap_ctrl = false; u8 k_cap_on = false; if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) return -EFAULT; if (strncmp(extra, "iqk", 3) == 0) { k_type = RTW_MP_CAL_IQK; if (strncmp(extra, "iqk on", 6) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set iqk on"); } else if ((strncmp(extra, "iqk off", 7) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set iqk off"); } else sprintf(extra, "set iqk trigger"); } else if (strncmp(extra, "dpk", 3) == 0) { k_type = RTW_MP_CAL_DPK; if (strncmp(extra, "dpk on", 6) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set dpk on"); } else if ((strncmp(extra, "dpk off", 7) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set dpk off"); } else sprintf(extra, "set dpk trigger"); } else if (strncmp(extra, "chk", 3) == 0) { k_type = RTW_MP_CAL_CHL_RFK; if (strncmp(extra, "chk on", 6) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set chk on"); } else if ((strncmp(extra, "chk off", 7) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set chk off"); } else sprintf(extra, "set chk trigger"); } else if (strncmp(extra, "dack", 3) == 0) { k_type = RTW_MP_CAL_DACK; if (strncmp(extra, "dack on", 6) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set dack on"); } else if ((strncmp(extra, "dack off", 7) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set dack off"); } else sprintf(extra, "set dack trigger"); } else if (strncmp(extra, "lck", 3) == 0) { k_type = RTW_MP_CAL_LCK; if (strncmp(extra, "lck on", 6) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set lck on"); } else if ((strncmp(extra, "lck off", 7) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set lck off"); } else sprintf(extra, "set lck trigger"); } else if (strncmp(extra, "dpk_trk", 7) == 0) { k_type = RTW_MP_CAL_DPK_TRACK; if (strncmp(extra, "dpk_trk on", 10) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set dpk_trk on"); } else if ((strncmp(extra, "dpk_trk off", 11) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set dpk_trk off"); } } else if (strncmp(extra, "tssi", 4) == 0) { k_type = RTW_MP_CAL_TSSI; if (strncmp(extra, "tssi on", 7) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set tssi on"); } else if ((strncmp(extra, "tssi off", 8) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set tssi off"); } else sprintf(extra, "set tssi trigger"); } else if (strncmp(extra, "gapk", 4) == 0) { k_type = RTW_MP_CAL_GAPK; if (strncmp(extra, "gapk on", 7) == 0) { k_cap_ctrl = true; k_cap_on = true; sprintf(extra, "set gapk on"); } else if ((strncmp(extra, "gapk off", 8) == 0)) { k_cap_ctrl = true; k_cap_on = false; sprintf(extra, "set gapk off"); } else sprintf(extra, "set gapk trigger"); } else sprintf(extra, "Error! CMD Format:\n\ [trigger K] or Set K on/off\n\ chk\\chk on/off\n\ dack\\dack on/off\n\ iqk\\iqk on/off\n\ lck\\lck on/off\n\ dpk\\dpk on/off\n\ dpk_trk on/off\n\ tssi\\tssi on/off\n\ gapk\\gapk on/off\n"); if (k_cap_ctrl) { rtw_mp_cal_capab(padapter, k_type, k_cap_on); } else if (k_type < RTW_MP_CAL_MAX) rtw_mp_cal_trigger(padapter, k_type); wrqu->data.length = strlen(extra); return 0; } int rtw_mp_phl_btc_path(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv = (struct mp_priv *)&padapter->mppriv; u8 btc_mode = 0; if (strncmp(extra, "normal", 6) == 0) { btc_mode = BTC_MODE_NORMAL; RTW_INFO("set BTC Path Normal"); } else if (strncmp(extra, "wl", 2) == 0 || strncmp(extra, "WL", 2) == 0) { btc_mode = BTC_MODE_WL; RTW_INFO("set BTC Path WL"); } else if (strncmp(extra, "bt", 2) == 0 || strncmp(extra, "BT", 2) == 0) { btc_mode = BTC_MODE_BT; RTW_INFO("set BTC Path BT"); } else { btc_mode = BTC_MODE_WL; RTW_INFO("Default set BTC Path WL"); } pmp_priv->btc_path = btc_mode; if (rtw_mp_phl_config_arg(padapter, RTW_MP_CONFIG_CMD_SWITCH_BT_PATH)) { sprintf(extra, "set BTC Path %s", (btc_mode == 0)? "Normal":((btc_mode == 1)? "WL": ((btc_mode == 2)? "BT":"DEFAULT WL"))); } else sprintf(extra, "set BTC Path Fail"); wrqu->data.length = strlen(extra); return 0; } int rtw_mp_get_he(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct registry_priv *regsty = &padapter->registrypriv; #ifdef CONFIG_80211AX_HE if (!REGSTY_IS_11AX_ENABLE(regsty) || !is_supported_he(regsty->wireless_mode)) sprintf(extra, "false"); else sprintf(extra, "true"); #endif wrqu->data.length = strlen(extra); return 0; } static inline void dump_buf(u8 *buf, u32 len) { u32 i; RTW_INFO("-----------------Len %d----------------\n", len); for (i = 0; i < len; i++) RTW_INFO("%2.2x-", *(buf + i)); RTW_INFO("\n"); } int rtw_mp_link(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrqu, char *extra) { _adapter *padapter = rtw_netdev_priv(dev); struct mp_priv *pmp_priv; char input[RTW_IWD_MAX_LEN]; int bgetrxdata = 0, btxdata = 0, bsetbt = 0; int err = 0; u32 i = 0, datalen = 0,jj, kk, waittime = 0; u16 val = 0x00, ret = 0; char *pextra = NULL; u8 *setdata = NULL; char *pch, *ptmp, *token, *tmp[4] = {0x00, 0x00, 0x00}; pmp_priv = &padapter->mppriv; if (copy_from_user(input, wrqu->pointer, wrqu->length)) return -EFAULT; _rtw_memset(extra, 0, wrqu->length); RTW_INFO("%s: in=%s\n", __func__, input); bgetrxdata = (strncmp(input, "rxdata", 6) == 0) ? 1 : 0; /* strncmp TRUE is 0*/ btxdata = (strncmp(input, "txdata", 6) == 0) ? 1 : 0; /* strncmp TRUE is 0*/ bsetbt = (strncmp(input, "setbt", 5) == 0) ? 1 : 0; /* strncmp TRUE is 0*/ if (bgetrxdata) { RTW_INFO("%s: in= 1 \n", __func__); if (pmp_priv->mplink_brx == _TRUE) { while (waittime < 100 && pmp_priv->mplink_brx == _FALSE) { if (pmp_priv->mplink_brx == _FALSE) rtw_msleep_os(10); else break; waittime++; } if (pmp_priv->mplink_brx == _TRUE) { sprintf(extra, "\n"); pextra = extra + strlen(extra); for (i = 0; i < pmp_priv->mplink_rx_len; i ++) { pextra += sprintf(pextra, "%02x:", pmp_priv->mplink_buf[i]); } _rtw_memset(pmp_priv->mplink_buf, '\0' , sizeof(pmp_priv->mplink_buf)); pmp_priv->mplink_brx = _FALSE; } } } else if (btxdata) { struct pkt_attrib *pattrib; pch = input; setdata = rtw_zmalloc(1024); if (setdata == NULL) { err = -ENOMEM; goto exit; } i = 0; while ((token = strsep(&pch, ",")) != NULL) { if (i > 2) break; tmp[i] = token; i++; } /* tmp[0],[1],[2] */ /* txdata,00e04c871200........... */ if (strcmp(tmp[0], "txdata") == 0) { if (tmp[1] == NULL) { err = -EINVAL; goto exit; } } datalen = strlen(tmp[1]); if (datalen % 2) { err = -EINVAL; goto exit; } datalen /= 2; if (datalen == 0) { err = -EINVAL; goto exit; } RTW_INFO("%s: data len=%d\n", __FUNCTION__, datalen); RTW_INFO("%s: tx data=%s\n", __FUNCTION__, tmp[1]); for (jj = 0, kk = 0; jj < datalen; jj++, kk += 2) setdata[jj] = key_2char2num(tmp[1][kk], tmp[1][kk + 1]); dump_buf(setdata, datalen); _rtw_memset(pmp_priv->mplink_buf, '\0' , sizeof(pmp_priv->mplink_buf)); _rtw_memcpy(pmp_priv->mplink_buf, setdata, datalen); pattrib = &pmp_priv->tx.attrib; pattrib->pktlen = datalen; pmp_priv->tx.count = 1; pmp_priv->tx.stop = 0; pmp_priv->mplink_btx = _TRUE; rtw_mp_set_packet_tx(padapter); pmp_priv->mode = MP_PACKET_TX; } else if (bsetbt) { #if 0 #ifdef CONFIG_BTC pch = input; i = 0; while ((token = strsep(&pch, ",")) != NULL) { if (i > 3) break; tmp[i] = token; i++; } if (tmp[1] == NULL) { err = -EINVAL; goto exit; } if (strcmp(tmp[1], "scbd") == 0) { u16 org_val = 0x8002, pre_val, read_score_board_val; u8 state; pre_val = (rtw_read16(padapter,(0xaa))) & 0x7fff; if (tmp[2] != NULL) { state = simple_strtoul(tmp[2], &ptmp, 10); if (state) org_val = org_val | BIT6; else org_val = org_val & (~BIT6); if (org_val != pre_val) { pre_val = org_val; rtw_write16(padapter, 0xaa, org_val); RTW_INFO("%s,setbt scbd write org_val = 0x%x , pre_val = 0x%x\n", __func__, org_val, pre_val); } else { RTW_INFO("%s,setbt scbd org_val = 0x%x ,pre_val = 0x%x\n", __func__, org_val, pre_val); } } else { read_score_board_val = (rtw_read16(padapter,(0xaa))) & 0x7fff; RTW_INFO("%s,read_score_board_val = 0x%x\n", __func__, read_score_board_val); } goto exit; } else if (strcmp(tmp[1], "testmode") == 0) { if (tmp[2] == NULL) { err = -EINVAL; goto exit; } val = simple_strtoul(tmp[2], &ptmp, 16); RTW_INFO("get tmp, type %s, val =0x%x!\n", tmp[1], val); if (tmp[2] != NULL) { _rtw_memset(extra, 0, wrqu->length); ret = rtw_btcoex_btset_testmode(padapter, val); if (!CHECK_STATUS_CODE_FROM_BT_MP_OPER_RET(ret, BT_STATUS_BT_OP_SUCCESS)) { RTW_INFO("%s: BT_OP fail = 0x%x!\n", __FUNCTION__, val); sprintf(extra, "BT_OP fail 0x%x!\n", val); } else sprintf(extra, "Set BT_OP 0x%x done!\n", val); } } #endif /* CONFIG_BTC */ #endif } exit: if (setdata) rtw_mfree(setdata, 1024); wrqu->length = strlen(extra); return err; } int rtw_priv_mp_get(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wdata, char *extra) { struct iw_point *wrqu = (struct iw_point *)wdata; u32 subcmd = wrqu->flags; _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); struct dvobj_priv *dvobj = adapter_to_dvobj(padapter); int status = 0; u8 i = 0; char *pch = extra; if (!is_primary_adapter(padapter)) { RTW_INFO("MP mode only primary Adapter support, iface id = %d,\n", padapter->iface_id); RTW_INFO("***Please use Primary Adapter:["ADPT_FMT"]***\n", ADPT_ARG(GET_PRIMARY_ADAPTER(padapter))); pch +=sprintf(pch, "Only primary Adapter support MP CMD\n"); pch +=sprintf(pch, "Please use Primary Adapter:"ADPT_FMT"", ADPT_ARG(GET_PRIMARY_ADAPTER(padapter))); wrqu->length = strlen(extra); return status; } for (i = 0; i < dvobj->iface_nums; i++) { _adapter *iface = dvobj->padapters[i]; if (iface == NULL) continue; if (rtw_is_adapter_up(iface) == _FALSE) continue; if (MLME_IS_AP(iface)) { RTW_INFO("Adapter:["ADPT_FMT"], Please Leave AP mode or Down Interface\n", ADPT_ARG(iface)); pch += sprintf(pch, "Check Adapter:"ADPT_FMT",\n\ Please Leave AP mode or Down Interface\n", ADPT_ARG(iface)); wrqu->length = strlen(extra); return status; } } RTW_INFO("%s mutx in %d\n", __func__, subcmd); switch (subcmd) { case MP_START: RTW_INFO("set case mp_start\n"); status = rtw_mp_start(dev, info, wrqu, extra); break; case MP_STOP: RTW_INFO("set case mp_stop\n"); status = rtw_mp_stop(dev, info, wrqu, extra); break; case MP_BANDWIDTH: RTW_INFO("set case mp_bandwidth\n"); status = rtw_mp_bandwidth(dev, info, wrqu, extra); break; case MP_RESET_STATS: RTW_INFO("set case MP_RESET_STATS\n"); status = rtw_mp_reset_stats(dev, info, wrqu, extra); break; case MP_SetRFPathSwh: RTW_INFO("set MP_SetRFPathSwitch\n"); status = rtw_mp_SetRFPath(dev, info, wrqu, extra); break; case WRITE_REG: status = rtw_mp_write_reg(dev, info, wrqu, extra); break; case WRITE_RF: status = rtw_mp_write_rf(dev, info, wrqu, extra); break; case MP_PHYPARA: RTW_INFO("mp_get MP_PHYPARA\n"); status = rtw_mp_phypara(dev, info, wrqu, extra); break; case MP_CHANNEL: RTW_INFO("set case mp_channel\n"); status = rtw_mp_channel(dev , info, wrqu, extra); break; case MP_TRXSC_OFFSET: RTW_INFO("set case rtw_mp_trxsc_offset\n"); status = rtw_mp_trxsc_offset(dev , info, wrqu, extra); break; case READ_REG: RTW_INFO("mp_get READ_REG\n"); status = rtw_mp_read_reg(dev, info, wrqu, extra); break; case READ_RF: RTW_INFO("mp_get READ_RF\n"); status = rtw_mp_read_rf(dev, info, wrqu, extra); break; case MP_RATE: RTW_INFO("set case mp_rate\n"); status = rtw_mp_rate(dev, info, wrqu, extra); break; case MP_TXPOWER: RTW_INFO("set case MP_TXPOWER\n"); status = rtw_mp_txpower(dev, info, wrqu, extra); break; case MP_ANT_TX: RTW_INFO("set case MP_ANT_TX\n"); status = rtw_mp_ant_tx(dev, info, wrqu, extra); break; case MP_ANT_RX: RTW_INFO("set case MP_ANT_RX\n"); status = rtw_mp_ant_rx(dev, info, wrqu, extra); break; case MP_QUERY: status = rtw_mp_trx_query(dev, info, wrqu, extra); break; case MP_CTX: RTW_INFO("set case MP_CTX\n"); status = rtw_mp_ctx(dev, info, wrqu, extra); break; case MP_ARX: RTW_INFO("set case MP_ARX\n"); status = rtw_mp_arx(dev, info, wrqu, extra); break; case MP_DUMP: RTW_INFO("set case MP_DUMP\n"); status = rtw_mp_dump(dev, info, wrqu, extra); break; case MP_PSD: RTW_INFO("set case MP_PSD\n"); status = rtw_mp_psd(dev, info, wrqu, extra); break; case MP_THER: RTW_INFO("set case MP_THER\n"); status = rtw_mp_thermal(dev, info, wrqu, extra); break; case MP_PwrCtlDM: RTW_INFO("set MP_PwrCtlDM\n"); status = rtw_mp_PwrCtlDM(dev, info, wrqu, extra); break; case MP_QueryDrvStats: RTW_INFO("mp_get MP_QueryDrvStats\n"); status = rtw_mp_QueryDrv(dev, info, wdata, extra); break; case MP_PWRTRK: RTW_INFO("set case MP_PWRTRK\n"); status = rtw_mp_pwrtrk(dev, info, wrqu, extra); break; case MP_SET_TSSIDE: RTW_INFO("set case MP_TSSI_DE\n"); status = rtw_mp_set_tsside(dev, info, wrqu, extra); break; case EFUSE_SET: RTW_INFO("set case efuse set\n"); status = rtw_ioctl_efuse_set(dev, info, wdata, extra); break; case EFUSE_GET: RTW_INFO("efuse get EFUSE_GET\n"); status = rtw_ioctl_efuse_get(dev, info, wdata, extra); break; case MP_GET_TXPOWER_INX: RTW_INFO("mp_get MP_GET_TXPOWER_INX\n"); status = rtw_mp_txpower_index(dev, info, wrqu, extra); break; case MP_GETVER: RTW_INFO("mp_get MP_GETVER\n"); status = rtw_mp_getver(dev, info, wdata, extra); break; case MP_MON: RTW_INFO("mp_get MP_MON\n"); status = rtw_mp_mon(dev, info, wdata, extra); break; case EFUSE_BT_MASK: RTW_INFO("mp_get EFUSE_BT_MASK\n"); status = rtw_ioctl_efuse_bt_file_mask_load(dev, info, wdata, extra); break; case EFUSE_MASK: RTW_INFO("mp_get EFUSE_MASK\n"); status = rtw_ioctl_efuse_file_mask_load(dev, info, wdata, extra); break; case EFUSE_FILE: RTW_INFO("mp_get EFUSE_FILE\n"); status = rtw_ioctl_efuse_file_map_load(dev, info, wdata, extra); break; case EFUSE_FILE_STORE: RTW_INFO("mp_get EFUSE_FILE_STORE\n"); /*status = rtw_efuse_file_map_store(dev, info, wdata, extra);*/ break; case MP_TX: RTW_INFO("mp_get MP_TX\n"); status = rtw_mp_tx(dev, info, wdata, extra); break; case MP_RX: RTW_INFO("mp_get MP_RX\n"); status = rtw_mp_rx(dev, info, wdata, extra); break; case MP_HW_TX_MODE: RTW_INFO("mp_get MP_HW_TX_MODE\n"); status = rtw_mp_hwtx(dev, info, wdata, extra); break; case MP_GET_TSSIDE: RTW_INFO("mp_get TSSI_DE\n"); status = rtw_mp_get_tsside(dev, info, wrqu, extra); break; #ifdef CONFIG_RTW_CUSTOMER_STR case MP_CUSTOMER_STR: RTW_INFO("customer str\n"); status = rtw_mp_customer_str(dev, info, wdata, extra); break; #endif case MP_PWRLMT: RTW_INFO("mp_get MP_SETPWRLMT\n"); status = rtw_mp_pwrlmt(dev, info, wdata, extra); break; case BT_EFUSE_FILE: RTW_INFO("mp_get BT EFUSE_FILE\n"); status = rtw_ioctl_efuse_bt_file_map_load(dev, info, wdata, extra); break; case MP_SWRFPath: RTW_INFO("mp_get MP_SWRFPath\n"); status = rtw_mp_switch_rf_path(dev, info, wrqu, extra); break; case MP_LINK: RTW_INFO("mp_get MP_LINK\n"); status = rtw_mp_link(dev, info, wrqu, extra); break; case MP_DPK_TRK: RTW_INFO("mp_get MP_DPK_TRK\n"); status = rtw_mp_dpk_track(dev, info, wdata, extra); break; case MP_DPK: RTW_INFO("set MP_DPK\n"); status = rtw_mp_dpk(dev, info, wdata, extra); break; case MP_GET_PHL_TEST: RTW_INFO("mp_get MP_GET_PHL_TEST\n"); status = rtw_mp_get_phl_io(dev, info, wrqu, extra); break; case MP_SET_PHL_TEST: RTW_INFO("mp_get MP_SET_PHL_TEST\n"); status = rtw_mp_set_phl_io(dev, info, wrqu, extra); break; case MP_SET_PHL_TX_PATTERN: RTW_INFO("mp_get MP_SET_PHL_TEST\n"); status = rtw_mp_tx_pattern_idx(dev, info, wdata, extra); break; case MP_SET_PHL_PLCP_TX_DATA: RTW_INFO("mp_get MP_SET_PHL_PLCP_TX_DATA\n"); status = rtw_mp_tx_plcp_tx_data(dev, info, wdata, extra); break; case MP_SET_PHL_PLCP_TX_USER: RTW_INFO("mp_get MP_SET_PHL_PLCP_TX_USER\n"); status = rtw_mp_tx_plcp_tx_user(dev, info, wdata, extra); break; case MP_SET_PHL_TX_METHOD: RTW_INFO("mp_get MP_SET_PHL_TX_METHOD\n"); status = rtw_mp_tx_method(dev, info, wdata, extra); break; case MP_SET_PHL_CONIFG_PHY_NUM: RTW_INFO("mp_get MP_SET_PHL_CONIFG_PHY_NUM\n"); status = rtw_mp_config_phy(dev, info, wdata, extra); break; case MP_PHL_RFK: RTW_INFO("mp_get MP_PHL_RFK\n"); status = rtw_mp_phl_rfk(dev, info, wdata, extra); break; case MP_PHL_BTC_PATH: RTW_INFO("mp_get MP_PHL_BTC_PATH\n"); status = rtw_mp_phl_btc_path(dev, info, wdata, extra); break; case MP_GET_HE: RTW_INFO("mp_get MP_GET_HE\n"); status = rtw_mp_get_he(dev, info, wdata, extra); break; default: status = -EIO; } return status; } int rtw_priv_mp_set(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wdata, char *extra) { struct iw_point *wrqu = (struct iw_point *)wdata; u32 subcmd = wrqu->flags; _adapter *padapter = (_adapter *)rtw_netdev_priv(dev); int status = 0; #ifdef CONFIG_CONCURRENT_MODE if (!is_primary_adapter(padapter)) { RTW_INFO("MP mode only primary Adapter support\n"); return -EIO; } #endif RTW_INFO("%s mutx in %d\n", __func__, subcmd); //_enter_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL); switch (subcmd) { case MP_DISABLE_BT_COEXIST: RTW_INFO("set case MP_DISABLE_BT_COEXIST\n"); status = rtw_mp_disable_bt_coexist(dev, info, wdata, extra); break; case MP_IQK: RTW_INFO("set MP_IQK\n"); status = rtw_mp_iqk(dev, info, wrqu, extra); break; case MP_LCK: RTW_INFO("set MP_LCK\n"); status = rtw_mp_lck(dev, info, wrqu, extra); break; default: status = -EIO; } //_exit_critical_mutex(&(adapter_to_dvobj(padapter)->ioctrl_mutex), NULL); RTW_INFO("%s mutx done %d\n", __func__, subcmd); return status; } #endif