RfKill
内核使用 rfkill 模块管理无线设备,rfkill 提供两种类型的用户态接口用于查询和控制无线设备:
1. /dev/rfkill
这是一个标准的 I/O 设备,可以使用标准的 open(), close() ioctl() 等操作查询和控制每个无线设备的状态,相关的头文件 /usr/include/linux/rfkill.h
2. /sys/class/rfkill/
每个 rfkill 设备会在 sysfs 中创建自己的一个节点,都有下面文件:
- name : 接口或驱动名称,注册 rfkill 设备时指定。
- type : 设备类型, wlan | bluethooth …
- persistent : 从外存谋取的软限制状态
- state : 当前的无线设备状态
- 0 : RFKILL_STATE_SOFT_BLOCKED 被软件关闭
- 1 : RFKILL_STATE_UNBLOCKED 开启
- 2 : RFKILL_STATE_HARD_BLOCKED 被硬件驱动关闭
设备禁用类型
- 软件禁用,由用户态应用程序触发,并通过 rfkill 接口关闭无线设备。
- 硬件驱动禁用,由内核硬件驱动程序触发的关闭,硬件驱动程序(平台驱动)调用 rfkill 接口通知硬件被关闭。
平台驱动中的 rfkill 相关部分
// 状态设备
static int ls3a_rfkill_set(void * data, bool blocked)
{
// 调用 EC 设备无线设备状态
...
}
// 状态查询
static void ls3a_rfkill_query(struct rfkill * rfkill, void * data)
{
// 调用 EC 设备查询无线设备的状态
...
rfkill_set_sw_state(rfkill, state_soft); // 设置 soft state
rfkill_set_hw_state(rfkill, state_hard); // 设备 hard state
}
// rfkill 操作函数
static const struct rfkill_ops ls3a_rfkill_ops =
{
.set_block = ls3a_rfkill_set,
.query = ls3a_rfkill_query,
};
static int __init ls3a_setup_rfkill(void)
{
// wifi
wifi_rfkill = rfkill_alloc("ls3a-wifi", ...);
...
rfkill_register(wifi_rfkill);
// bluetooth
bluetooth_rfkill = rfkill_alloc("ls3a-bluetooth", ...);
...
rfkill_register(bluetooth_rfkill);
// wwan
wwan_rfkill = rfkill_alloc("ls3a-wwan", ...);
...
rfkill_register(wwan_rfkill);
}
static void ls3a_cleanup_rfkill(void)
{
// wifi
rfkill_unregsiter(wifi_rfkill);
rfkill_destroy(wifi_rfkill);
// bluetooth
rfkill_unregsiter(bluetooth_rfkill);
rfkill_destroy(bluetooth_rfkill);
// wwan
rfkill_unregsiter(wwan_rfkill);
rfkill_destroy(wwan_rfkill);
}
static int __init ls3a_init(void)
{
// 注册平台驱动和其它设备初始化
platform_device = platform_driver_register(&platform_driver);
...
// 设置 rfkill 设备
ls3a_setup_rfkill();
...
return 0;
}
static void __exit ls3a_exit(void)
{
// 注销平台设备和其它设备
...
// 清除 rfkill 设备
ls3a_cleanup_rfkill();
}
module_init(ls3a_init);
module_exit(ls3a_exit);
Over!
mark了