最近我在研究MT7688的闭源WIFI源码,发现默认开启了AP和AP-Client模式,但STA模式默认没选中,估计要支持的话得修改代码。
MT7688我以及在用LEDE了,新的系统很流畅,所有顺便也把WIFI移植了,修改了几个不兼容的地方基本OK了。本来是想公开的,但这个是MTK闭源驱动-_-!!!,不能公开。
涉及到的MT7688.dat里的驱动参数是这么几个:
ApCliEnable ApCliSsid ApCliBssid // 这个不是必须,如果不提供,wifi驱动会自己去查找 ApCliAuthMode ApCliEncrypType ApCliWPAPSK
但是OpenWRT里默认的uci2dat支持这些参数有BUG,因为uci2dat默认只支持一个wifi-iface,但AP-Client模式必须有两个wifi-iface,一个做AP,一个做Client。修改uci2data:
@@ -1061,23 +1064,69 @@ void hooker(FILE * fp, param * p, const char * devname) #endif else if (0 == strmatch(p->dat_key, "ApCliEnable")) { - FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_enable.value); + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_enable.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_enable.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_enable.value); } else if (0 == strmatch(p->dat_key, "ApCliSsid")) { - FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_ssid.value); + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_ssid.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_ssid.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_ssid.value); + } + else if (0 == strmatch(p->dat_key, "ApCliBssid")) + { + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_bssid.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_bssid.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_bssid.value); } else if (0 == strmatch(p->dat_key, "ApCliAuthMode")) { - FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_authmode.value); + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_authmode.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_authmode.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_authmode.value); } else if (0 == strmatch(p->dat_key, "ApCliEncrypType")) { - FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_encryptype.value); + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_encryptype.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_encryptype.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_encryptype.value); } else if (0 == strmatch(p->dat_key, "ApCliWPAPSK")) { - FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_password.value); + int j; + for(j=0; j<wifi_cfg[N].vifnum; j++) + { + if (strlen(wifi_cfg[N].vifs[j].apcli_password.value) > 0) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[j].apcli_password.value); + } + if (j < wifi_cfg[N].vifnum) + FPRINT(fp, p, "%s", wifi_cfg[N].vifs[i].apcli_password.value); } /* the rest part is quite simple! */ else
编辑/etc/config/wireless:
config wifi-device 'mt7628' option type 'mt7628' option vendor 'ralink' option band '2.4G' option channel '11' // 这个必须是你要连接路由器的信道一致,否则会连不上的 option country 'CN' option region '1' config wifi-iface 'ap' option device 'mt7628' option ifname 'ra0' option network 'lan' option mode 'ap' option ssid 'AP名' option key 'AP密码' option encryption 'psk2' option wpa_crypto 'TKIP+AES' option hidden '1' config wifi-iface 'sta' option device 'mt7628' option ifname 'apcli0' option network 'wan' // 作为外网接口 option mode 'sta' // 这个没用,uci2dat根本不解析 option ApCliEnable '1' option ApCliSsid '路由器名' option ApCliAuthMode 'WPA2PSK' option encryption 'psk2' // 这个必须,如果省略这个会导致WIFI驱动错误的认证协议 option ApCliEncrypType 'TKIP' option ApCliWPAPSK '路由器密码'
在/etc/config/network里修改wan:
config interface 'wan' option ifname 'apcli0' option force_link '1' option proto dhcp
一开始调试死活连不上,逼得只能看WIFI驱动代码发现底层的认证协议需要加上option encryption,还有就是如果是AP-Client模式的话就不能自动选择信道了,必须跟着路由器的信道来,其实把AP和Client做个桥接就是一个信号中继了,不过WIFI驱动底层好像支持MAC层上的中继,这个没空研究了。
在LEDE的iwinfo没法查看WIFI的Link Quality,而且iw也输出为空,原因就是WIFI驱动还没启用CFG80211支持。但是MT7688的WIFI驱动比较老,导致CFG80211的代码跟最新的内核不兼容,所以我疯狂的在github上一遍查找补丁,一遍修改代码。最后总算是能运行iw了,但是iwinfo输出的信息不全,估计是通过ioctl的方式与驱动打交道,驱动不支持,这个后面再修复。