系统:嵌入式 linux 系统
平台:高通平台
代码:
#include <fcntl.h>
#include <linux/uinput.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main() {
struct uinput_setup usetup;
struct input_event ev;
// 1. 打开 /dev/uinput 设备
int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if (fd < 0) {
perror("Failed to open /dev/uinput");
return 1;
}
// 2. 告诉 uinput 我们需要发送按键事件 (EV_KEY)
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_KEYBIT, KEY_POWER); // 设置支持 KEY_POWER
// 3. 告诉 uinput 我们将要使用的按键是电源键 (KEY_POWER)
ioctl(fd, UI_SET_KEYBIT, KEY_POWER);
// 4. 初始化虚拟设备的信息
memset(&usetup, 0, sizeof(usetup));
snprintf(usetup.name, UINPUT_MAX_NAME_SIZE, "Virtual Power Button");
usetup.id.bustype = BUS_USB;
usetup.id.vendor = 0x1234; // 任意供应商 ID
usetup.id.product = 0x5678; // 任意产品 ID
usetup.id.version = 1;
// 5. 创建虚拟设备
ioctl(fd, UI_DEV_SETUP, &usetup);
ioctl(fd, UI_DEV_CREATE);
sleep(1); // 休眠 1 秒以确保设备已准备好
while(1){
printf("power_on: down\n");
// 6. 模拟电源键按下 (KEY_POWER press)
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_KEY;
ev.code = KEY_POWER;
ev.value = 1; // 按下状态
write(fd, &ev, sizeof(struct input_event));
// 同步事件 (告诉内核事件已结束)
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(fd, &ev, sizeof(struct input_event));
printf("power_on: realse\n");
// 6. 模拟电源键按下 (KEY_POWER press)
// 模拟电源键释放 (KEY_POWER release)
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_KEY;
ev.code = KEY_POWER;
ev.value = 0; // 释放状态
write(fd, &ev, sizeof(struct input_event));
// 同步事件
memset(&ev, 0, sizeof(struct input_event));
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
write(fd, &ev, sizeof(struct input_event));
sleep(3); // 暂停 1 秒以查看效果
}
// while(1){sleep(1);}
// 7. 销毁虚拟设备
ioctl(fd, UI_DEV_DESTROY);
close(fd);
return 0;
}
1 将上述代码保存为 virtual_power_button.c。
2 编译代码:
aarch64-oe-linux-gcc -o virtual_power_button virtual_power_button.c
(aarch64-oe-linux-gcc是我的交叉编译环境。
如果是在ubuntu运行可以这样子编译:
gcc -o virtual_power_button virtual_power_button.c)
adb push virtual_power_button /data/ #push到/data/目录
3 使用 root用户该程序,因为操作 uinput 需要超级用户权限:
./virtual_power_button
3.1 运行后会生成类似这样子的设备:
/data # cat /proc/bus/input/devices | grep -A 5 -B 1 “Virtual Power
Button” I: Bus=0003 Vendor=1234 Product=5678 Version=0001 N:
Name=“Virtual Power Button” P: Phys= S:
Sysfs=/devices/virtual/input/input11 U: Uniq= H: Handlers=kbd event5
cpufreq B: PROP=0
3.2 我这里生成的是event5,所以可以监听event5,验证按键按下和释放的过程
/data # ./evtest /dev/input/event5 Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1234 product 0x5678 version 0x1
Input device name: “Virtual Power Button” Supported events: Event
type 0 (EV_SYN) Event type 1 (EV_KEY)
Event code 116 (KEY_POWER) Properties: Testing … (interrupt to exit) Event: time 1729590307.1729590307, type 1 (EV_KEY), code 116
(KEY_POWER), value 1 Event: time 1729590307.1729590307, --------------
SYN_REPORT ------------ Event: time 1729590307.1729590307, type 1
(EV_KEY), code 116 (KEY_POWER), value 0 Event: time
1729590307.1729590307, -------------- SYN_REPORT ------------ Event: time 1729590310.1729590310, type 1 (EV_KEY), code 116 (KEY_POWER),
value 1 Event: time 1729590310.1729590310, -------------- SYN_REPORT
------------ Event: time 1729590310.1729590310, type 1 (EV_KEY), code 116 (KEY_POWER), value 0 Event: time 1729590310.1729590310,
-------------- SYN_REPORT ------------