4. 设置WiFi接口模式
任务说明
本案例实现Android WiFi HAL层中设置WiFi接口模式的核心逻辑。目标是通过HAL接口将指定无线网卡(如wlan0)设置为STA(Station)或AP(Access Point)模式,并完成模式切换时的底层驱动调用。案例聚焦于HAL层函数set_interface_mode的完整实现,包括模式合法性校验、驱动命令下发以及结果返回。
核心实现
// wifi_hal_mode_control.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/wireless.h>
#include <errno.h>
#define WIFI_INTERFACE_NAME_MAX 16
#define WIFI_DRIVER_CMD_BUF_SIZE 64
typedef enum {
WIFI_MODE_STA = 0,
WIFI_MODE_AP = 1,
WIFI_MODE_INVALID
} wifi_mode_t;
typedef struct {
char ifname[WIFI_INTERFACE_NAME_MAX];
wifi_mode_t mode;
} wifi_interface_mode_t;
// 向驱动下发模式设置命令
static int wifi_driver_set_mode(const char *ifname, wifi_mode_t mode) {
int sock = -1;
struct iwreq wrq;
char cmd_buf[WIFI_DRIVER_CMD_BUF_SIZE];
if (ifname == NULL || strlen(ifname) == 0) {
return -EINVAL;
}
// 创建socket用于ioctl
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
return -errno;
}
memset(&wrq, 0, sizeof(wrq));
memset(cmd_buf, 0, sizeof(cmd_buf));
// 构造驱动私有命令: SET_MODE=0 表示STA, SET_MODE=1 表示AP
snprintf(cmd_buf, sizeof(cmd_buf), "SET_MODE=%d", (mode == WIFI_MODE_AP) ? 1 : 0);
strncpy(wrq.ifr_name, ifname, IFNAMSIZ - 1);
wrq.u.data.pointer = cmd_buf;
wrq.u.data.length = strlen(cmd_buf) + 1;
wrq.u.data.flags = 0;
// 通过SIOCSIWPRIV下发驱动命令
if (ioctl(sock, SIOCSIWPRIV, &wrq) < 0) {
close(sock);
return -errno;
}
close(sock);
return 0;
}
// HAL层对外接口:设置WiFi接口模式
int set_interface_mode(const wifi_interface_mode_t *config) {
if (config == NULL) {
return -EINVAL;
}
// 校验接口名合法性
if (strlen(config->ifname) == 0 ||
strlen(config->ifname) >= WIFI_INTERFACE_NAME_MAX) {
return -EINVAL;
}
// 校验模式合法性
if (config->mode != WIFI_MODE_STA && config->mode != WIFI_MODE_AP) {
return -EINVAL;
}
// 调用驱动下发模式设置命令
int ret = wifi_driver_set_mode(config->ifname, config->mode);
if (ret != 0) {
return ret;
}
return 0;
}
关键逻辑说明
上述代码实现了完整的模式设置链路:set_interface_mode作为HAL层对外接口,首先校验传入的接口名和模式参数,随后通过wifi_driver_set_mode函数构造驱动私有命令SET_MODE=0/1,并利用SIOCSIWPRIVioctl调用下发至内核无线驱动。驱动收到命令后完成硬件模式切换。返回值0表示成功,负值对应标准errno错误码。
SVG:模式设置调用流程
编译与使用
# 编译(需Linux内核头文件)
gcc -c wifi_hal_mode_control.c -o wifi_hal_mode_control.o
# 链接生成可执行测试程序(示例main函数需自行添加)
# gcc wifi_hal_mode_control.o -o wifi_mode_test
验证方法
编写测试程序调用set_interface_mode,传入合法的接口名(如"wlan0")和模式值,观察返回值:
- 返回0:驱动命令下发成功,接口模式已切换;
- 返回-EINVAL:参数非法(接口名为空或模式值不在枚举范围内);
- 返回其他负值:驱动命令执行失败,可通过
errno或返回值值判断具体错误原因。
在真实硬件环境中,可通过iwconfig命令确认接口模式已从"Managed"(STA)切换为"Master"(AP),或反之。若驱动不支持SET_MODE私有命令,ioctl将返回-EOPNOTSUPP,此时需确认驱动已实现对应命令处理。