SSD_WLAN使用参考
1. 内核配置说明¶
1.1. 配置WEXT¶
Wext是Wireless Extension,是内核中WIFI驱动和用户态进程的标准接口,iwpriv命令依赖这个配置。

1.2. 配置CFG80211¶
CFG80211是内核中WIFI驱动和用户态进程的标准接口,在CFG80211出现之前是WEXT,现在越来越多的使用CFG80211。

1.3. SDIO WIFI (SSW102B)配置¶
不支持SDIO wifi热插拔。
infinity2m.dtsi dts配置:

如果是跳线验证,信号较差可以将clk改成12M来验证,改动如下:

额外注意一点:
如果有使用wifi reset脚,需要检查reset脚的配置情况。如果没有额外gpio控制reset脚,可以忽略如下内容。
在demo板上使用gpio0来控制sd的power enable脚位。 有可能在新的设计图纸上,将GPIO0用来控制reset。
需要在infinity2m-ssc011a-s01a-padmux-display.dtsi中屏蔽
//<PAD_GPIO0 PINMUX_FOR_GPIO_MODE MDRV_PUSE_SDIO0_PWR >,
然后再uboot上添加:gpio out 0 0 和 gpio out 0 1 来控制复位。
-
kernel里控制sd power 的gpio,其实是根据padmux里的MDRV_PUSE_SDIO0_PWR来找到对应哪个gpio口的,dts里的slot-pwr-gpios在padmux存在情况下,是没有作用的。

-
power不是硬件长供电的情况下,作为SDIO使用时候,如果发生初始化的时候发生错误,注意要修改如下时间为30

2. 工具使用¶
2.1. wap_supplicant使用¶
wpa_supplicant是一个独立运行的守护进程,用来启动无线网络后台服务,在消息循环中处理WPA状态机、控制命令、驱动事件、配置信息等。
常用命令参数如下:
-I <ifname> // 网络接口名称 -c <conf> // 配置文件名称 -C <ctrl_intf> // 控制接口名称 -D<driver> // 驱动类型名称 -p <driver_param> // 驱动参数 -b <br_ifname> // 桥接口名称 -d // 增加调试信息
使用样例:
/config/wifi/wpa_supplicant -Dnl80211 -i wlan0 -c /customer/wpa_supplicant.conf -d &
启动无线网络服务,驱动类型为nl80211,使用网络端口名称为wlan0,配置文件路径为/customer/wpa_supplicant.conf。若配置文件中有保存热点信息,则发起连接。
2.2. wpa_cli使用¶
wpa_cli是客户端程序,与wpa_supplicant通信,搜索、设置和连接网络。
常用命令参数如下(如当前网络接口为wlan0):
wpa_cli –i wlan0 scan // 扫描附近的热点 wpa_cli –i wlan0 scan_result // 显示扫描结果 wpa_cli –I wlan0 status // 查看当前连接信息 wpa_cli –I wlan0 add_network // 新建一个链接,返回network id wpa_cli –I wlan0 set_network <network id> <variable> <value> // 设置网络参数,如ssid,psk,keymgmt wpa_cli –I wlan0 select_network <network id> // 选择指定的网络(会断开其它的连接) wpa_cli –I wlan0 enable_network <network id> // 使能指定网络 wpa_cli –I wlan0 disable_network <network id> // 禁用指定网络 wpa_cli –I wlan0 save_config // 保持连接信息至wpa_supplicant.conf
2.3. iwlist使用¶
iwlist用于对/proc/net/wireless文件进行分析,得出无线网卡相关信息。
常用命令参数如下(如当前网络接口为wlan0):
iwlist wlan0 scanning // 扫描当前无线网络 iwlist wlan0 frequen // 显示频道信息 iwlist wlan0 rate // 显示连接速度 iwlist wlan0 power // 显示电源模式
2.4. udhcpc使用¶
udhcpc作为dhcp客户端,动态获取ip。
常用命令参数如下:
-i <ifname> // 网络接口名称 -s <script> // udhcpc script -a // 使用arping验证提供的地址 -t <count> // 发送数据包次数 -T <time> // 数据包间时间间隔(默认是3s) -f // 前台执行 -b // 后台执行 -n // 租约获取失败时退出 -q // 获取到租约后退出
使用样例:
udhcpc -q -i wlan0 -s /etc/init.d/udhcpc.script &
2.5. hostapd使用¶
hostapd用来将当前设备作为热点,允许其它网络设备接入。
使用样例:
hostapd -B /config/wifi/hostapd.conf // -B:在后台执行守护进程
2.6. dnsmasq使用¶
dnsmasq是一个轻量级的,易于配置的DNS转发器和DHCP服务器。它的目的是给一个小网络提供DNS和可选的DHCP。
常用命令参数如下:
-i <ifname> // 网络接口名称 -C <path> // 指定配置文件路径(默认为/etc/dnsmasq.conf) --no-daemon // 非后台执行
使用样例:
dnsmasq -i p2p0 --no-daemon -C /config/wifi/dnsmasq.conf &
2.7. hostapd_cli使用¶
hostapd_cli作为hostapd的客户端,使用时,首先需要先启动hostapd主程序。hostapd启动后,运行cli客户端时,会自动去连接当前正在工作的hostapd进程,连接成功后,cli客户端就可以对hostapd应用程序进行参数的获取和控制。
常用命令参数如下:
-i <ifname> // 网络接口名称 -p <path> // 控制套接字路径(默认为/var/run/hostapd) -B // 后台执行守护进程
使用样例:
/config/wifi/hostapd_cli -I p2p0 –p /var/run/hostapd all_sta &
3. WIFI功能测试¶
3.1. 加载WIFI驱动¶
先insmod加载WIFI驱动,以ssw101b为例,对应驱动是ssw101b_wifi_HT40_usb.ko。执行insmod ssw101b_wifi_HT40_usb.ko,使用ifconfig –a查看,可以看到新生成wlan0节点和p2p0节点:

3.2. STA模式测试¶
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/lib:/config/wifi mkdir -p /tmp/wifi/run chmod 777 /tmp/wifi/run ifconfig wlan0 up
创建wpa_supplicant.conf文件,编辑如下,使用测试热点为”WiFi_test”,密码为“12345678”。

测试连接:
/config/wifi/wpa_supplicant -Dnl80211 -i wlan0 -c /appconfigs/wpa_supplicant.conf -d &
获取IP:
udhcpc -q -i wlan0 -s /etc/init.d/udhcpc.script &
查看wlan0信息:

扫描热点:
/config/wifi/iwlist wlan0 scan | grep Cell -A 5

可以看到,当前连接的热点“WiFi_test”信道为1。
3.3. AP模式测试¶
mkdir -p /var/run/hostapd mkdir -p /var/wifi/misc mkdir -p /var/lib/misc ifconfig p2p0 up ifconfig p2p0 192.168.1.100 netmask 255.255.255.0
hostapd配置文件在/config/wifi/hostapd.conf,其中ssid为当前设备的热点名称,wpa_passphrase为设备的连接密码。可修改此文件变更设备名称和密码。
开启热点:
/config/wifi/hostapd -B /config/wifi/hostapd.conf /config/wifi/dnsmasq -i p2p0 --no-daemon -C /config/wifi/dnsmasq.conf &
网络设备可以搜索到热点“ssw101bap”,使用手机连接该热点:

查看设备连接信息:
/config/wifi/hostapd_cli -i p2p0 -p /var/run/hostapd all_sta &

可以看到接入数量为 1,接入设备mac与手机mac一致。
3.4. 桥接模式测试¶
WIFI同时开启STA和AP的情况下,在wlan0和p2p0之间建立桥接。
Kernel配置添加网络桥接支持,编译kernel在kernel/modules目录会生成llc.ko,stp.ko,bridge.ko。网络桥接前依次加载这三个驱动。注:Kernel网络相关配置变化,wifi驱动可能需要重新编译。

建立桥接还需要需编辑/config/wifi/hostapd.conf,添加bridge字段,并修改channel,使之与STA模式接入热点的信道相同。

编译kernel和wifi驱动后,按3.1节加载wifi驱动,再按3.2节和3.3节的步骤启用STA模式接入测试热点“WiFi_test”,并启用AP模式开启热点。
建立桥接:
brctl addbr br0 brctl addif br0 wlan0 brctl addif br0 p2p0 ifconfig br0 up
使用测试手机接入热点“ssw101bap”。在“WiFi_test”接入外网的情况下,测试手机可正常访问外网。
查看br0信息:

4. MI_WLAN使用示例¶
4.1. MI_WLAN在STA模式下连接热点¶
本地设备连接AP示例:
1. static WLAN_HANDLE g_wlanHdl = -1;
2. static MI_WLAN_InitParams_t g_stParam = {"/config/wifi/wlan.json"};
3. static MI_WLAN_OpenParams_t g_stOpenParam = {E_MI_WLAN_NETWORKTYPE_INFRA};
4. static MI_WLAN_ConnectParam_t g_stConnectParam = {
5. E_MI_WLAN_SECURITY_WPA,
6. "WiFi_test",
7. "12345678",
8. 5000
9. };
10.
11. static bool g_bConnected = false;
12. static pthread_t g_ptConn = NULL;
13. static bool g_bThreadRun = false;
14.
15. void *_ConnectWorkThread(void *args)
16. {
17. int nTimeoutCnt = 50; // timeout 10s
18. MI_WLAN_Status_t status;
19. MI_WLAN_ConnectParam_t *pstConnParam = (MI_WLAN_ConnectParam_t*)args;
20. MI_WLAN_Connect(&g_wlanHdl, pstConnParam);
21. printf("current conn info: handle=%d, ssid=%s, passwd=%s\n", g_wlanHdl, (char*)pstConnParam->au8SSId, (char*)pstConnParam->au8Password);
22.
23. while (1)
24. {
25. if (!g_bThreadRun)
26. break;
27.
28. if (nTimeoutCnt-- <= 0)
29. {
30. printf("connect failed, timeout\n");
31. break;
32. }
33.
34. static int i = 0;
35. MI_WLAN_GetStatus(g_wlanHdl, &status);
36. printf("MI_WLAN_GetStatus: count %d\n", i++);
37.
38. if (status.stStaStatus.state == WPA_COMPLETED)
39. {
40. g_bConnected = true;
41. printf("connect success: ssid=%s, ip=%s\n", (char*)status.stStaStatus.ssid, (char*)status.stStaStatus.ip_address);
42. break;
43. }
44.
45. usleep(100000);
46. }
47.
48. return NULL;
49. }
50.
51. int main(int argc, char **argv)
52. {
53. MI_WLAN_ScanResult_t scanResult;
54. char ch = 0;
55.
56. // init wlan module
57. if (MI_WLAN_Init(&g_stParam))
58. {
59. printf("Wlan init failed, please ensure wlan module is enabled.\n");
60. return -1;
61. }
62.
63. if (MI_WLAN_Open(&g_stOpenParam))
64. {
65. printf("wlan open failed\n");
66. break;
67. }
68.
69. g_bThreadRun = true;
70. pthread_create(&g_ptConn, NULL, _ConnectWorkThread, &g_stConnectParam);
71.
72. while ((ch = getchar()) != 'q')
73. {
74. if (ch == 's')
75. {
76. memset(&scanResult, 0, sizeof(MI_WLAN_ScanResult_t));
77. MI_WLAN_Scan(NULL, &scanResult);
78.
79. if (scanResult.u8APNumber > 0)
80. {
81. printf("Scan result:\n");
82.
83. for (int i = 0; i < scanResult.u8APNumber; i++)
84. {
85. char *pSsid = (char*)scanResult.stAPInfo[i].au8SSId;
86. if (pSsid && strcmp(pSsid, "\"\""))
87. {
88. char trimSsid[36];
89. memset(trimSsid, 0, sizeof(trimSsid));
90. strncpy(trimSsid, pSsid+1, strlen(pSsid));
91. printf("SSID: %s\n", trimSsid);
92. printf("MAC: %s\n", (char*)scanResult.stAPInfo[i].au8Mac);
93. printf("encrypt: %s\n", scanResult.stAPInfo[i].bEncryptKey?"true":"false");
94. printf("signalSTR: %d db\n", scanResult.stAPInfo[i].stQuality.signalSTR);
95. printf("frequency: %f GHz\n", scanResult.stAPInfo[i].fFrequency);
96. printf("bitrate: %f Mb/s\n", scanResult.stAPInfo[i].fBitRate);
97. printf("channel: %d\n", scanResult.stAPInfo[i].u8Channel);
98. printf("channel: %d\n", scanResult.stAPInfo[i].u16CellId);
99. printf("\n");
100. }
101. }
102. }
103. }
104. }
105.
106. g_bThreadRun = false;
107. pthread_join(g_ptConn, NULL);
108.
109. if (g_bConnected)
110. {
111. MI_WLAN_Disconnect(g_wlanHdl);
112. g_bConnected = false;
113. }
114.
115. MI_WLAN_Close(&g_stOpenParam);
116. MI_WLAN_DeInit();
117.
118. return 0;
119. }
4.2. MI_WLAN在AP模式下开启热点¶
本地设备作为host示例:
1. static WLAN_HANDLE g_apHdl = AP_HANDLE;
2. static MI_WLAN_OpenParams_t g_stOpenParam = {E_MI_WLAN_NETWORKTYPE_AP};
3. static MI_WLAN_InitParams_t g_stParam = {"/config/wifi/wlan.json"};
4. static MI_WLAN_Status_t g_stStatus;
5. static bool g_bConnected = false;
6.
7. int main(int argc, char **argv)
8. {
9. // init wlan module
10. if (MI_WLAN_Init(&g_stParam))
11. {
12. printf("Wlan init failed, please ensure wlan module is enabled.\n");
13. return -1;
14. }
15.
16. if (MI_WLAN_Open(&g_stOpenParam))
17. {
18. printf("wlan open failed\n");
19. break;
20. }
21.
22. if (MI_SUCCESS == MI_WLAN_Connect(&g_apHdl, NULL))
23. g_bConnected = true;
24.
25. while ((ch = getchar()) != 'q')
26. {
27. if (ch == 's')
28. {
29. MI_WLAN_GetStatus(AP_HANDLE, &g_stStatus);
30. if (g_stStatus.stApStatus.u16HostNum > 0)
31. {
32. printf("Access port:\n");
33.
34. for (int i = 0; i < g_stStatus.stApStatus.u16HostNum; i++)
35. {
36. printf("HostName: %s\n", g_stStatus.stApStatus.astHosts[i].hostname);
37. printf("IP: %s\n", (char*)g_stStatus.stApStatus.astHosts[i].ipaddr);
38. printf("MAC: %s\n", (char*)g_stStatus.stApStatus.astHosts[i].macaddr);
39. printf("Connected time: %lld\n", g_stStatus.stApStatus.astHosts[i].connectedtime);
40. printf("\n");
41. }
42. }
43. }
44. }
45.
46. if (g_bConnected)
47. {
48. MI_WLAN_Disconnect(g_apHdl);
49. g_bConnected = false;
50. }
51.
52. MI_WLAN_Close(&g_stOpenParam);
53. MI_WLAN_DeInit();
54.
55. return 0;
56.
57. }
5. DEMO参考¶
MI_WLAN DemoCode参考: