在Brillo系统中,提供了iw这个命令,可以对无线网卡进行配置,设置WiFi的工作模式AP(接入点模式,相当于一个无线路由器,SoftAP)或者是STA模式。apmanager需要一个WiFi HAL层模块,对WiFi的工作模式进行切换。(device/generic/brillo/wifi_driver_hal/README)。
从相关的代码来看,各家实现的方式都不太一样:
- Intel – Edision的实现方式
相关的代码在:hardware/bsp/intel/peripheral/wifi/bcm43340/bcm43340_hal.cpp
从代码上看,实现方式是先往kernel结点中写入对应的firmware, 再重启一下WiFi对应的网口(wlan0)。
- Qualcomm – Dragonboard的实现方式
相关的代码在:hardware/bsp/qcom/peripheral/wifi/wcn3620/wifi_driver_hal_qcwcn.cpp
从代码上看,只需要往/sys/module/wlan/parameters/con_mode写入工作模式就可以了。相对来说简单了一点。
- RPi 2B – rtl8188cu的实现方式 (目前SoftAP模式还不能正常工作)
相关的代码在:device/hzak/rpi/bsp/rtl8192cu/rtl8192cu_hal.cpp
参考相关的文档,使用命令进行切换(SoftAP模式):
$ ifconfig wlan0 down $ iw dev wlan0 del $ iw phy phy0 interface add wlan0 type __ap $ ifconfig wlan0 up
切换成STA模式:
$ ifconfig wlan0 down $ iw dev wlan0 del $ iw phy phy0 interface add wlan0 type station $ ifconfig wlan0 up
设置完后再通过iw查看:
$ iw dev wlan0 info
本来想用最简单的方法来实现HAL层:
static wifi_driver_error wifi_driver_set_mode_rtl8192cu( wifi_driver_mode mode, char* wifi_device_name, size_t wifi_device_name_size) { system("/system/bin/ifconfig wlan0 down"); switch (mode) { case WIFI_MODE_AP: system("/system/bin/iw phy phy0 interface add wlan0 type __ap"); break; case WIFI_MODE_STATION: system("/system/bin/iw phy phy0 interface add wlan0 type station"); break; } system("/system/bin/ifconfig wlan0 up"); // ... }
由于SELinux的存在,程序运行的时候给了很多的警告。由于有iw(external/iw)的源代码,分析了一下,当iw编译成静态库最终编译进HAL模块问题也不大,于是改写的相关的代码。需要注意的是,连接成动态库的时候,要将iw所有的section编译进去(LOCAL_WHOLE_STATIC_LIBRARIES := libiw):
include $(CLEAR_VARS) LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_LDFLAGS := -Wl,--no-gc-sections LOCAL_C_INCLUDES += device/generic/brillo/wifi_driver_hal/include LOCAL_WHOLE_STATIC_LIBRARIES := libiw LOCAL_STATIC_LIBRARIES := libnl LOCAL_SHARED_LIBRARIES := libcutils LOCAL_SRC_FILES := rtl8192cu_hal.cpp LOCAL_MODULE := $(WIFI_DRIVER_HAL_MODULE) LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_MODULE_TAGS := optional include $(BUILD_SHARED_LIBRARY)
原因是iw对所有的命令的定义都放在了特定的section里了,从external/iw/iw.h中可以看到:
#define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel)\ static struct cmd \ __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\ __attribute__((used)) __attribute__((section("__cmd"))) = { \ .name = (_name), \ .args = (_args), \ .cmd = (_nlcmd), \ .nl_msg_flags = (_flags), \ .hidden = (_hidden), \ .idby = (_idby), \ .handler = (_handler), \ .help = (_help), \ .parent = _section, \ .selector = (_sel), \ }
编译后可以用arm-linux-androideabi-objdump查看(可以看到__cmd有0x1040字节):
$ arm-linux-androideabi-objdump -h out/target/product/rpi/symbols/system/bin/iw out/target/product/rpi/symbols/system/bin/iw: file format elf32-littlearm Sections: Idx Name Size VMA LMA File off Algn 0 .interp 00000013 00000154 00000154 00000154 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 1 .note.android.ident 00000018 00000168 00000168 00000168 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 2 .note.gnu.build-id 00000020 00000180 00000180 00000180 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 3 .dynsym 00000790 000001a0 000001a0 000001a0 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 4 .dynstr 0000050a 00000930 00000930 00000930 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA 5 .gnu.hash 000000e8 00000e3c 00000e3c 00000e3c 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 6 .gnu.version 000000f2 00000f24 00000f24 00000f24 2**1 CONTENTS, ALLOC, LOAD, READONLY, DATA 7 .gnu.version_r 00000070 00001018 00001018 00001018 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 8 .rel.dyn 00002508 00001088 00001088 00001088 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 9 .rel.plt 000002b8 00003590 00003590 00003590 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 10 .plt 00000428 00003848 00003848 00003848 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 11 .text 00015e6c 00003c70 00003c70 00003c70 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 12 .ARM.exidx 00000e58 00019adc 00019adc 00019adc 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 13 .rodata 0000af6c 0001a940 0001a940 0001a940 2**4 CONTENTS, ALLOC, LOAD, READONLY, DATA 14 .ARM.extab 000000f8 000258ac 000258ac 000258ac 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA 15 .data.rel.ro.local 000013ec 00027910 00027910 00026910 2**4 CONTENTS, ALLOC, LOAD, DATA 16 .preinit_array 00000008 00028cfc 00028cfc 00027cfc 2**2 CONTENTS, ALLOC, LOAD, DATA 17 .init_array 0000001c 00028d04 00028d04 00027d04 2**2 CONTENTS, ALLOC, LOAD, DATA 18 .fini_array 0000000c 00028d20 00028d20 00027d20 2**2 CONTENTS, ALLOC, LOAD, DATA 19 .dynamic 00000118 00028d2c 00028d2c 00027d2c 2**2 CONTENTS, ALLOC, LOAD, DATA 20 .got 000001b8 00028e48 00028e48 00027e48 2**2 CONTENTS, ALLOC, LOAD, DATA 21 .data 00000c0c 00029000 00029000 00028000 2**3 CONTENTS, ALLOC, LOAD, DATA 22 __cmd 00001040 00029c0c 00029c0c 00028c0c 2**2 CONTENTS, ALLOC, LOAD, DATA 23 .bss 00000210 0002ac50 0002ac50 00029c50 2**3 ALLOC 24 .comment 00000049 00000000 00000000 00029c4c 2**0 CONTENTS, READONLY 25 .debug_str 0000f5b4 00000000 00000000 00029c95 2**0 CONTENTS, READONLY, DEBUGGING 26 .debug_loc 0001a514 00000000 00000000 00039249 2**0 CONTENTS, READONLY, DEBUGGING 27 .debug_abbrev 000061ef 00000000 00000000 0005375d 2**0 CONTENTS, READONLY, DEBUGGING 28 .debug_info 00031efa 00000000 00000000 0005994c 2**0 CONTENTS, READONLY, DEBUGGING 29 .debug_ranges 00003b80 00000000 00000000 0008b846 2**0 CONTENTS, READONLY, DEBUGGING 30 .debug_pubnames 0000671e 00000000 00000000 0008f3c6 2**0 CONTENTS, READONLY, DEBUGGING 31 .debug_pubtypes 00005613 00000000 00000000 00095ae4 2**0 CONTENTS, READONLY, DEBUGGING 32 .debug_frame 0000417c 00000000 00000000 0009b0f8 2**2 CONTENTS, READONLY, DEBUGGING 33 .debug_line 00011ff3 00000000 00000000 0009f274 2**0 CONTENTS, READONLY, DEBUGGING 34 .debug_aranges 00000160 00000000 00000000 000b1268 2**3 CONTENTS, READONLY, DEBUGGING 35 .note.gnu.gold-version 0000001c 00000000 00000000 000b13c8 2**2 CONTENTS, READONLY 36 .ARM.attributes 00000038 00000000 00000000 000b13e4 2**0 CONTENTS, READONLY
虽然做了这么多的努力,但还是只能使STA模式正常工作,SoftAP还是不能正常工作。
参考文档:
- https://wireless.wiki.kernel.org/en/users/documentation/iw
- https://wiki.archlinux.org/index.php/Software_access_point
- https://wiki.archlinux.org/index.php/Wireless_network_configuration
设置为STA模式后,怎么连路由呢?
请看这篇文档(命令行的做法):http://www.brobwind.com/archives/179
后续会在Android客户端加上这个功能。