在android平台通常需要通过按键来实现一些快捷功能,可以通过模拟按键来完成对应功能。
例如hardware/power/power.cpp 中
bool sendPowerKeyToAndroid()
{
int fd = 0;
int ret = 0;
int version = 0;
FILE * deviceInfoFd = NULL;
char buffer[LINE_MAX_LEN];
char path[PATH_MAX_LEN] = {0};
char * ptr = NULL;
bool found = false;
//POWER key, see input.h
// #define KEY_POWER 116 = 0x74
struct input_event event[5] = {
{{0x0, 0x0}, 0x4, 0x4, 0xff},
{{0x0, 0x0}, 0x1, 0x74, 0x1},
{{0x0, 0x0}, 0x0, 0x0, 0x0},
{{0x0, 0x0}, 0x1, 0x74, 0x0},
{{0x0, 0x0}, 0x0, 0x0, 0x0}};
deviceInfoFd = fopen(INPUT_DEVICE_INFO_FILE_PATH, "r");
if (deviceInfoFd == NULL) {
return false;
}
while (fgets(buffer, LINE_MAX_LEN, deviceInfoFd) != NULL) {
if (strstr(buffer, IR_DEVICE_NAME) != NULL) {
found = true;
}
if ((found == true) && (strstr(buffer, "Handlers") != NULL)) {
ptr = strstr(buffer, "event");
if (ptr == NULL) {
return false;
}
sprintf(path, "%s%s", INPUT_DEVICE_PATH, ptr);
// strip space and '\n'
for (int pos = strlen(path) - 1; pos >= 0; pos--) {
if ((path[pos] == '\n') || (path[pos] == ' ')) {
path[pos] = '\0';
}
}
break;
}
}
fclose(deviceInfoFd);
fd = open(path, O_RDWR);
if (fd < 0) {
ALOGD("sendPowerKeyToAndroid could not open /dev/input/event0, %s\n", strerror(errno));
return false;
}
if (ioctl(fd, EVIOCGVERSION, &version)) {
ALOGD("sendPowerKeyToAndroid could not get driver version for /dev/input/event0, %s\n", strerror(errno));
return false;
}
ret = write(fd, &event, sizeof(input_event)*5);
if (ret < (int)sizeof(input_event)*5) {
ALOGD("sendPowerKeyToAndroid write event failed, %s\n", strerror(errno));
return false;
} else {
ALOGD("sendPowerKeyToAndroid write event success \n");
}
if (close(fd) < 0) {
ALOGD("sendPowerKeyToAndroid could not close /dev/input/event0, %s\n", strerror(errno));
return false;
}
return true;
}
#define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */
#define INPUT_DEVICE_INFO_FILE_PATH "/proc/bus/input/devices"
#define INPUT_DEVICE_PATH "/dev/input/"
#define IR_DEVICE_NAME "MStar Smart TV IR Receiver"
#define LINE_MAX_LEN 1024
#define PATH_MAX_LEN 64
解析节点
打开节点/proc/bus/input/devices,解析Handlers键值,
此处为“kbd event1”
遥控器事件节点
if ((found == true) && (strstr(buffer, "Handlers") != NULL)) {
ptr = strstr(buffer, "event");
if (ptr == NULL) {
return false;
}
sprintf(path, "%s%s", INPUT_DEVICE_PATH, ptr);
// strip space and '\n'
for (int pos = strlen(path) - 1; pos >= 0; pos--) {
if ((path[pos] == '\n') || (path[pos] == ' ')) {
path[pos] = '\0';
}
}
break;
}
将“/dev/input/” 和 “event1” 拼接得到 /dev/input/event1 即为遥控器设备节点。
封装按键信息
struct input_event
{
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};
struct input_event event[5] = {
{{0x0, 0x0}, 0x4, 0x4, 0xff},
{{0x0, 0x0}, 0x1, 0x74, 0x1},
{{0x0, 0x0}, 0x0, 0x0, 0x0},
{{0x0, 0x0}, 0x1, 0x74, 0x0},
{{0x0, 0x0}, 0x0, 0x0, 0x0}};
例如平台捕获power 键,键值信息如下:
事件类型,事件码,键值,已经按键顺序。
发送按键
封装好的有序event 信息,往节点发送接口。
ret = write(fd, &event, sizeof(input_event)*5);
if (ret < (int)sizeof(input_event)*5) {
ALOGD("sendPowerKeyToAndroid write event failed, %s\n", strerror(errno));
return false;
} else {
ALOGD("sendPowerKeyToAndroid write event success \n");
}
举一反三,我们可以通过对输入设备(ir,touch,keyboard…)
发送模拟事件。