一、总体思路
首先我们需要搞清楚Hi3516中Wifi的相关模块,以及他们之间的关系,其实和linux是很相似的。首先,我们需要运行一个的Daemon,也就是上文提到的wpa_supplicant,负责对网卡的硬件调用,比如连接wifi、断开wifi、启动热点等等。这个Daemon开放一个socket端口,外部程序可以通过本地连接向其发送指令实现间接对wifi的调用,这无疑是给我们提供了很大的便利,不用从底层重新造轮子了。
鸿蒙OS代码中,有一个示例,在//applications/sample/camera/communication/wpa_cli,实现了连接Daemon、扫描热点、连接热点等功能。
现在方案就很明确了,第一启动Daemon,第二向Daemon发送命令。下面我们就来详细分析如何实现。
二、启动Daemon
查看代码//applications/sample/camera/communication/wpa_supplicant/src/wpa_sample.c,找到main函数,发现它只做了一件事情,那就是调用pthread_create创建了一个线程,线程执行的函数是ThreadMain。而ThreadMain也只做了一件事情,那就是加载/usr/lib/libwpa.so,然后执行了其中的wpa_main函数,同时把命令行参数传递了进去。而wpa_main函数具体调用网卡就是通过hdf框架向内核态发送消息了,这里就不再赘述。
static void* ThreadMain() { printf("[WpaSample]init wpa_supplicant.\n"); void *handleLibWpa = dlopen("/usr/lib/libwpa.so", RTLD_NOW | RTLD_LOCAL); if (handleLibWpa == NULL) { printf("[WpaSample]dlopen libwpa failed.\n"); return NULL; } int (*func)(int, char **) = NULL; func = dlsym(handleLibWpa, "wpa_main"); if (func == NULL) { dlclose(handleLibWpa); printf("[WpaSample]dlsym wpa_main failed.\n"); return NULL; } int ret = func(g_wpaArgc, g_wpaArg); printf("[WpaSample]run wpa_main failed, ret:%d.\n", ret); for (int i = 0; i < g_wpaArgc; i++) { printf("[WpaSample]arg %d:%s.\n", i, g_wpaArg[i]); } if (dlclose(handleLibWpa) != 0) { printf("[WpaSample]dlclose libwpa failed.\n"); return NULL; } return NULL; } int main(int argc, char *argv[]) { g_wpaArgc = argc; for (int i = 0; i < g_wpaArgc; i++) { g_wpaArg[i] = argv[i]; } int ret = pthread_create(&g_wpaThread, NULL, ThreadMain, NULL); if (ret != 0) { printf("[WpaSample]create thread failed error:%s.\n", strerror(ret)); return 1; } pthread_join(g_wpaThread, NULL); return 0; }