RTL9182EU为双天线最大速率为300Mb/s,需要将其强制将为150Mb/s,即将2T2R改为1T1R。首先想到是修改hostapd的配置文件hostapd.conf,但是通过查看此文件的配置样例发现并没有这一配置选项,只好把目光转向驱动源码。RTL9182EU驱动加载时可以手动选择一些加载配置 ,具体可以查看 ./os_dep/linux/os_intfs.c文件,我们找到疑似配置选项:
int rtw_rf_config = RF_MAX_TYPE;
其中RF_MAX_TYPE枚举为
typedef enum _RT_RF_TYPE_DEFINITION
{
RF_1T2R = 0,
RF_2T4R = 1,
RF_2T2R = 2,
RF_1T1R = 3,
RF_2T2R_GREEN = 4,
RF_2T3R = 5,
RF_3T3R = 6,
RF_3T4R = 7,
RF_4T4R = 8,
RF_MAX_TYPE = 0xF, /* u1Byte */
}RT_RF_TYPE_DEF_E;
然后我在加载驱动时添加了这一选项如下:
insmod rtl8192eu.ko rtw_rf_config =3
结果AP还是2T2R。
不得不开始从驱动源码来找相关信息,发现文件./os_dep/linux/ioctl_cfg80211.c中有一个函数
static void rtw_cfg80211_init_ht_capab(_adapter *padapter, struct ieee80211_sta_ht_cap *ht_cap, enum ieee80211_band band, u8 rf_type)
{
#define MAX_BIT_RATE_40MHZ_MCS23 450 /* Mbps */
#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
ht_cap->ht_supported = _TRUE;
ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
rtw_cfg80211_init_ht_capab_ex(padapter, ht_cap, band, rf_type);
/*
*Maximum length of AMPDU that the STA can receive.
*Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
*/
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
/*Minimum MPDU start spacing , */
ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
/*
*hw->wiphy->bands[IEEE80211_BAND_2GHZ]
*base on ant_num
*rx_mask: RX mask
*if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7
*if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15
*if rx_ant >=3 rx_mask[2]=0xff;
*if BW_40 rx_mask[4]=0x01;
*highest supported RX rate
*/
if (rf_type == RF_1T1R) {
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
} else if ((rf_type == RF_1T2R) || (rf_type == RF_2T2R) || (rf_type == RF_2T2R_GREEN)) {
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0xFF;
ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
} else if ((rf_type == RF_2T3R) || (rf_type == RF_3T3R)) {
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0xFF;
ht_cap->mcs.rx_mask[2] = 0xFF;
ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS23;
} else {
rtw_warn_on(1);
DBG_8192C("%s, error rf_type=%d\n", __func__, rf_type);
}
}
我试着将rf_type的值修改为3,不加参数加载驱动发现成功实现1T1R。
那为什么加参数加载不行呢,结果发现./os_dep/linux/os_intfs.c文件中loadparam函数
初始化参数都赋值给padapter->registrypriv结构体,那rf_type的值是在哪里赋值的呢?我找到了./hal/hal_com.c文件如下函数
void rtw_hal_config_rftype(PADAPTER padapter)
{
HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
if (IS_1T1R(pHalData->VersionID)) {
pHalData->rf_type = RF_1T1R;
pHalData->NumTotalRFPath = 1;
}
else if (IS_2T2R(pHalData->VersionID)) {
pHalData->rf_type = RF_2T2R;
pHalData->NumTotalRFPath = 2;
}
else if (IS_1T2R(pHalData->VersionID)) {
pHalData->rf_type = RF_1T2R;
pHalData->NumTotalRFPath = 2;
}
else if(IS_3T3R(pHalData->VersionID)) {
pHalData->rf_type = RF_3T3R;
pHalData->NumTotalRFPath = 3;
}
else if(IS_4T4R(pHalData->VersionID)) {
pHalData->rf_type = RF_4T4R;
pHalData->NumTotalRFPath = 4;
}
else {
pHalData->rf_type = RF_1T1R;
pHalData->NumTotalRFPath = 1;
}
DBG_871X("%s RF_Type is %d TotalTxPath is %d \n", __FUNCTION__, pHalData->rf_type, pHalData->NumTotalRFPath);
}
通过查看调用发现./hal/rtl8192e/rtl8192_hal_init.c文件如下函数
static void read_chip_version_8192e(PADAPTER Adapter)
{
u32 value32;
HAL_DATA_TYPE *pHalData;
u8 tmpvdr;
pHalData = GET_HAL_DATA(Adapter);
value32 = rtw_read32(Adapter, REG_SYS_CFG1_8192E);
DBG_871X("%s 0xF0 = 0x%x \n", __FUNCTION__, value32);
pHalData->VersionID.ICType = CHIP_8192E;
pHalData->VersionID.RFType = (value32 & RF_TYPE_ID)?RF_2T2R :RF_1T1R;
pHalData->VersionID.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
tmpvdr = (value32 & EXT_VENDOR_ID) >> EXT_VENDOR_ID_SHIFT;
if(tmpvdr == 0x00)
pHalData->VersionID.VendorType = CHIP_VENDOR_TSMC;
else if(tmpvdr == 0x01)
pHalData->VersionID.VendorType = CHIP_VENDOR_SMIC;
else if(tmpvdr == 0x02)
pHalData->VersionID.VendorType = CHIP_VENDOR_UMC;
pHalData->VersionID.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; // IC version (CUT)
pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
rtw_hal_config_rftype(Adapter);
#if 1
dump_chip_info(pHalData->VersionID);
#endif
}
发现rf_type的值是由pHalData->VersionID.RFType决定的,而pHalData->VersionID.RFType的值是通过读取相关的地址的寄存器获得,由于暂时未找到写入相关地址寄存器的代码段,故只能暂时在此函数加了一段代码来实现需求,修改后的函数如下:
static void read_chip_version_8192e(PADAPTER Adapter)
{
u32 value32;
HAL_DATA_TYPE *pHalData;
u8 tmpvdr;
pHalData = GET_HAL_DATA(Adapter);
value32 = rtw_read32(Adapter, REG_SYS_CFG1_8192E);
DBG_871X("%s 0xF0 = 0x%x \n", __FUNCTION__, value32);
pHalData->VersionID.ICType = CHIP_8192E;
pHalData->VersionID.RFType = (value32 & RF_TYPE_ID)?RF_2T2R :RF_1T1R;
if (Adapter->registrypriv.rf_config != RF_MAX_TYPE)
{
switch(Adapter->registrypriv.rf_config)
{
case RF_1T1R:
pHalData->VersionID.RFType = RF_TYPE_1T1R;
break;
case RF_1T2R:
pHalData->VersionID.RFType = RF_TYPE_1T2R;
break;
case RF_2T2R:
pHalData->VersionID.RFType = RF_TYPE_2T2R;
break;
case RF_3T3R:
pHalData->VersionID.RFType = RF_TYPE_3T3R;
break;
case RF_4T4R:
pHalData->VersionID.RFType = RF_TYPE_4T4R;
break;
default: break;
}
}
pHalData->VersionID.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
tmpvdr = (value32 & EXT_VENDOR_ID) >> EXT_VENDOR_ID_SHIFT;
if(tmpvdr == 0x00)
pHalData->VersionID.VendorType = CHIP_VENDOR_TSMC;
else if(tmpvdr == 0x01)
pHalData->VersionID.VendorType = CHIP_VENDOR_SMIC;
else if(tmpvdr == 0x02)
pHalData->VersionID.VendorType = CHIP_VENDOR_UMC;
pHalData->VersionID.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; // IC version (CUT)
pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
rtw_hal_config_rftype(Adapter);
#if 1
dump_chip_info(pHalData->VersionID);
#endif
}
重新编译后,实测即可通过加载参数的改变来实现1T1R和2T2R的切换