概述
1.getevent命令使用
一般都是通过help来查询命令的使用方法,getevent命令也不例外
130|generic_x86:/ $ getevent -h
Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]
-t: show time stamps
-n: don't print newlines
-s: print switch states for given bits
-S: print all switch states
-v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)
-d: show HID descriptor, if available
-p: show possible events (errs, dev, name, pos. events)
-i: show all device info and possible events
-l: label event types and names in plain text
-q: quiet (clear verbosity mask)
-c: print given number of events then exit
-r: print rate events are received
其中最常用的参数就是:
-t: show time stamps—显示时间打印的时间
-l: label event types and names in plain text—这里表示把event事件类型名字打印出来
-r: print rate events are received—显示一下时间接受的速率
具体使用示例
127|generic_x86:/ $ gete -lrt
[ 171811.520824] /dev/input/event1: EV_ABS ABS_MT_TRACKING_ID 00000000
[ 171811.520824] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 00002fff
[ 171811.520824] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00006a76
[ 171811.520824] /dev/input/event1: EV_ABS ABS_MT_PRESSURE 00000400
[ 171811.520824] /dev/input/event1: EV_SYN SYN_REPORT 00000000
[ 171811.560128] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00006a43
[ 171811.560128] /dev/input/event1: EV_SYN SYN_REPORT 00000000 rate 25
[ 171811.563992] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 0000305a
[ 171811.563992] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00006a10
[ 171811.563992] /dev/input/event1: EV_SYN SYN_REPORT 00000000 rate 258
[ 171811.567507] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 000069dd
[ 171811.567507] /dev/input/event1: EV_SYN SYN_REPORT 00000000 rate 284
示例解释打印对应的格式
[ 171811.520824] /dev/input/event1: EV_ABS ABS_MT_TRACKING_ID 00000000
[事件打印时间] 具体节点文件名:事件类型 事件code 事件value
命令位置:
一般的命令都是在/system/bin下面,那么我们来/system/bin下找一个getevent
1|generic_x86:/system/bin $ ls -l | grep getevent
lrwxr-xr-x 1 root shell 7 2009-01-01 00:00 getevent -> toolbox
可以看到getevent命令是软连接的到toolbox的。
2.getevent源码分析
源码路径
system/core/toolbox/getevent.c
system/core/toolbox/toolbox.c
system/core/toolbox/tool.h
getevent命令链接到toolbox,那么入口函数就是toolbox的main函数了,就从toolbox的main函数开始讲起
以下是toolbox的源码分析,入口是main函数:
#define TOOL(name) int name##_main(int, char**);//这里会拼接名字
#include "tools.h"//这里内容其实就是TOOL(getevent) TOOL(getprop) TOOL(toolbox)
#undef TOOL
int main(int argc, char** argv) {
char* cmd = strrchr(argv[0], '/');
char* name = cmd ? (cmd + 1) : argv[0];//获取name就是getevent
for (size_t i = 0; tools[i].name; i++) {
if (!strcmp(tools[i].name, name)) {
return tools[i].func(argc, argv);//这里会调用到getevent_main
}
}
printf("%s: no such tooln", argv[0]);
return 127;
}
这部分是getevent的源码,入口函数getevent_main函数
static struct pollfd *ufds;
static char **device_names;
static int nfds;
static void print_event(int type, int code, int value, int print_flags)
{
const char *type_label, *code_label, *value_label;
if (print_flags & PRINT_LABELS) {
type_label = get_label(ev_labels, type);
code_label = NULL;
value_label = NULL;
switch(type) {
case EV_SYN:
code_label = get_label(syn_labels, code);
break;
case EV_KEY:
code_label = get_label(key_labels, code);
value_label = get_label(key_value_labels, value);
break;
case EV_REL:
code_label = get_label(rel_labels, code);
break;
case EV_ABS:
code_label = get_label(abs_labels, code);
switch(code) {
case ABS_MT_TOOL_TYPE:
value_label = get_label(mt_tool_labels, value);
}
break;
case EV_MSC:
code_label = get_label(msc_labels, code);
break;
case EV_LED:
code_label = get_label(led_labels, code);
break;
case EV_SND:
code_label = get_label(snd_labels, code);
break;
case EV_SW:
code_label = get_label(sw_labels, code);
break;
case EV_REP:
code_label = get_label(rep_labels, code);
break;
case EV_FF:
code_label = get_label(ff_labels, code);
break;
case EV_FF_STATUS:
code_label = get_label(ff_status_labels, code);
break;
}
if (type_label)
printf("%-12.12s", type_label);
else
printf("%04x ", type);
if (code_label)
printf(" %-20.20s", code_label);
else
printf(" %04x ", code);
if (value_label)
printf(" %-20.20s", value_label);
else
printf(" %08x ", value);
} else {
printf("%04x %04x %08x", type, code, value);
}
}
static void print_hid_descriptor(int bus, int vendor, int product)
{
const char *dirname = "/sys/kernel/debug/hid";
char prefix[16];
DIR *dir;
struct dirent *de;
char filename[PATH_MAX];
FILE *file;
char line[2048];
snprintf(prefix, sizeof(prefix), "%04X:%04X:%04X.", bus, vendor, product);
dir = opendir(dirname);
if(dir == NULL)
return;
while((de = readdir(dir))) {
if (strstr(de->d_name, prefix) == de->d_name) {
snprintf(filename, sizeof(filename), "%s/%s/rdesc", dirname, de->d_name);
file = fopen(filename, "r");
if (file) {
printf(" HID descriptor: %snn", de->d_name);
while (fgets(line, sizeof(line), file)) {
fputs(" ", stdout);
fputs(line, stdout);
}
fclose(file);
puts("");
}
}
}
closedir(dir);
}
static int open_device(const char *device, int print_flags)
{
int version;
int fd;
int clkid = CLOCK_MONOTONIC;
struct pollfd *new_ufds;
char **new_device_names;
char name[80];
char location[80];
char idstr[80];
struct input_id id;
//打开devive对应的设备文件
fd = open(device, O_RDONLY | O_CLOEXEC);
if(fd < 0) {
if(print_flags & PRINT_DEVICE_ERRORS)
fprintf(stderr, "could not open %s, %sn", device, strerror(errno));
return -1;
}
//做一些ioctl的操作
if(ioctl(fd, EVIOCGVERSION, &version)) {
if(print_flags & PRINT_DEVICE_ERRORS)
fprintf(stderr, "could not get driver version for %s, %sn", device, strerror(errno));
return -1;
}
if(ioctl(fd, EVIOCGID, &id)) {
if(print_flags & PRINT_DEVICE_ERRORS)
fprintf(stderr, "could not get driver id for %s, %sn", device, strerror(errno));
return -1;
}
name[sizeof(name) - 1] = '