在树莓派2上使用MT7601芯片USB网卡搭建AP 作者: rin 时间: March 16, 2016 分类: RPi,Linux 12 条评论 在某东入手了一块Tenda W311M USB无线网卡准备给RPi使用。插上之后lsusb查看 ```sh pi@raspberrypi:~ $ lsusb Bus 001 Device 004: ID 148f:7601 Ralink Technology, Corp. Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub ``` 识别为148f:7601,搜索得知是MT7601,小米wifi2 小度wifi 360wifi等也使用同样的芯片。 普通的STA模式即接收模式现在(4.1.19-v7+)应该免驱了,ifconfig后也确实出现了wlan0,但似乎没有AP的驱动。 经搜索发现[一篇文章](http://blog.csdn.net/sumang_87/article/details/38168877 "一篇文章"),按照其中的步骤做 ```sh pi@raspberrypi:~/Downloads/mi $ git clone https://github.com/eywalink/mt7601u.git .... pi@raspberrypi:~/Downloads/mi $ cd mt7601u/ pi@raspberrypi:~/Downloads/mi/mt7601u $ sudo ./miwifi_build.sh ``` make时出现错误 ```sh Makefile:387: recipe for target 'LINUX' failed ``` 原因是没有linux-headers,而apt源中只有3.x.x版本的。当前版本的可以从[https://github.com/raspberrypi/](https://github.com/raspberrypi/ "https://github.com/raspberrypi/")或者使用[rpi-source](https://github.com/notro/rpi-source/wiki "rpi-source")获得。 ```sh sudo wget https://raw.githubusercontent.com/notro/rpi-source/master/rpi-source -O /usr/bin/rpi-source && sudo chmod +x /usr/bin/rpi-source && /usr/bin/rpi-source -q --tag-update sudo rpi-source ``` 这时应该可以make成功了。~~我已经忘了还遇到了哪些问题。~~> 此处略去dhcpd的安装和配置 ```sh pi@raspberrypi:~/Downloads/mi/mt7601u $ sudo ./miwifi_work.sh #或者手动卸载sta和加载ap驱动 pi@raspberrypi:~ $sudo ifconfig wlan0 down pi@raspberrypi:~ $sudo rmmod mt7601u pi@raspberrypi:~ $sudo sudo modprobe rtnet7601Uap pi@raspberrypi:~ $sudo modprobe mt7601Uap pi@raspberrypi:~ $sudo modprobe rtutil7601Uap pi@raspberrypi:~ $sudo ifconfig ra0 up pi@raspberrypi:~ $iwconfig ``` iwconfig看了一下就懵逼了,一共ra0-ra15有16个interface,essid为HT_AP0、HT_AP1、HT_AP2…,并且其他设备并搜不到,打开日志一看有如下之类的错误 ```sh Qidx(0), not enough space in MgmtRing, MgmtRingFullCount=1! Qidx(0), not enough space in MgmtRing, MgmtRingFullCount=2! Qidx(0), not enough space in MgmtRing, MgmtRingFullCount=3! Qidx(0), not enough space in MgmtRing, MgmtRingFullCount=4! #或是 kernel: [47203.620633] no file read method kernel: [47203.620657] Read file “/etc/Wireless/RT2870AP/RT2870AP.dat” failed(errCode=-1)! kernel: [47203.620670] 1. Phy Mode = 6 kernel: [47203.620678] 2. Phy Mode = 6 kernel: [47203.620687] NVM is Efuse and its size =1d[1e0-1fc] kernel: [47203.630202] ERROR!!! MT7601 E2PROM: WRONG VERSION 0xd, should be 12 kernel: [47203.645531] 3. Phy Mode = 6 kernel: [47203.645545] AntCfgInit: primary/secondary ant 0/1 kernel: [47203.849695] RTMPSetPhyMode: channel is out of range, use first channel=0 ``` 第一种错误的我没验证过的方法是[这个](http://blog.csdn.net/bbandxq521/article/details/5997419 "这个") 第二种错误就是没有成功读取配置文件,这时候驱动就使用默认的配置如ssid为HT_APx,相关源码如下 ```c //ap.c Line 164 for (apidx=0; apidxApCfg.BssidNum; apidx++) { MULTISSID_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx]; if ((pMbss->SsidLen <= 0) || (pMbss->SsidLen > MAX_LEN_OF_SSID)) { NdisMoveMemory(pMbss->Ssid, "HT_AP", 5); pMbss->Ssid[5] = '0'+apidx; pMbss->SsidLen = 6; } //....................................... ``` 哦那就看看怎么让它读配置。Read file failed的错误来自于这 ```c //rt_profile.c Line 181 if (src && *src) { RtmpOSFSInfoChange(&osFSInfo, TRUE); srcf = RtmpOSFileOpen(src, O_RDONLY, 0); if (IS_FILE_OPEN_ERR(srcf)) { DBGPRINT(RT_DEBUG_ERROR, ("Open file \"%s\" failed!\n", src)); } else { retval =RtmpOSFileRead(srcf, buffer, MAX_INI_BUFFER_SIZE); if (retval > 0) { RTMPSetProfileParameters(pAd, buffer); retval = NDIS_STATUS_SUCCESS; } else DBGPRINT(RT_DEBUG_ERROR, ("Read file \"%s\" failed(errCode=%d)!\n", src, retval)); retval = RtmpOSFileClose(srcf); if ( retval != 0) { retval = NDIS_STATUS_FAILURE; DBGPRINT(RT_DEBUG_ERROR, ("Close file \"%s\" failed(errCode=%d)!\n", src, retval)); } } RtmpOSFSInfoChange(&osFSInfo, FALSE); } #ifdef HOSTAPD_SUPPORT for (i = 0; i < pAd->ApCfg.BssidNum; i++) { pAd->ApCfg.MBSSID[i].Hostapd=FALSE; DBGPRINT(RT_DEBUG_TRACE, ("Reset ra%d hostapd support=FLASE", i)); } #endif /*HOSTAPD_SUPPORT */ ``` 那就是RtmpOSFileRead()没有读取到文件,这个函数在/src/os/linux/rt_linux.c里 ```c //rt_linux.c Line 1162 int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen) { /* The object must have a read method */ if (osfd->f_op && osfd->f_op->read) { return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); } else { DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); return -1; } } ``` 也正是这里报的no file read method错误。检查 osfd->f_op 和 osfd->f_op->read 发现后者为空,即没有read函数来读取文件。 在[这里](http://lkml.iu.edu/hypermail/linux/kernel/1506.3/02378.html "这里")和[这里](http://stackoverflow.com/questions/33183923/ "这里")看到用`ssize_t vfs_read(struct file* filp, char __user* buffer, size_t len, loff_t* pos);`替换`ssize_t read()`: ```c int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen) { DBGPRINT(RT_DEBUG_ERROR, ("add: %p %p\n", osfd->f_op, osfd->f_op->read)); /* The object must have a read method */ if (osfd->f_op /*&& osfd->f_op->read*/) { //return osfd->f_op->read(osfd, pDataPtr, readLen, &osfd->f_pos); return vfs_read(osfd, pDataPtr, readLen, &osfd->f_pos); } else { DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n")); return -1; } } ``` 重新编译和加载后 ```sh pi@raspberrypi:~/Downloads/mi/mt7601u $ iwconfig ppp0 no wireless extensions. ra0 RTWIFI SoftAP ESSID:"FREE-WIFI" Mode:Managed Channel=11 Access Point: C8:3A:35:CC:ED:B2 Bit Rate=150 Mb/s lo no wireless extensions. eth0 no wireless extensions. ``` [![](http://lo-li.net/wp-content/uploads/2016/03/1361093046-169x300.jpg)](http://lo-li.net/wp-content/uploads/2016/03/1361093046-169x300.jpg)