MeowOS for HiBy R3 Pro II — 公共发布版本(历史已重置)
• 全新单提交:清除含敏感信息的旧历史(sudo 口令、内网 IP、SSH 密钥路径、热点 SSID、设备 MAC) • 本地开发文档/测试记录/构建脚本全部移入 gitignored 的 devdocs/ 与 scripts/build/(不入库) • 保留:MeowOS 源码(launcher/watchdog/bootmenu/meow_svcd/SDK)、项目规范文档、mips-repo 增补组件:SDK 统一日志+通知 API、meow_svcd 服务管理器、mips-repo 软件仓库
This commit is contained in:
commit
245bee2946
136 files changed
+32730
No files matched your search
Executable
BIN
Binary file not shown.
@@ -0,0 +1,466 @@
|
||||
/* uinput_tap.c — remote touch/key injection for R3 Pro II.
|
||||
*
|
||||
* Modes:
|
||||
* uinput_tap daemon <cmd_fifo> create a virtual goodix-style touch
|
||||
* device + a virtual key device, then
|
||||
* serve commands from the fifo
|
||||
* uinput_tap tap <fifo> <x> <y> enqueue a tap command
|
||||
* uinput_tap key <fifo> <code> enqueue a key press+release
|
||||
* uinput_tap seq <fifo> <x1,y1;x2,y2;...> taps with 300ms gaps
|
||||
*
|
||||
* The virtual devices are created BEFORE hiby_player starts so its
|
||||
* hgl_ts input scanner opens them.
|
||||
*
|
||||
* Static MIPS32r2 musl build:
|
||||
* ~/Project/R3ProII/.tools/zig-mipsel-cc -Os -static uinput_tap.c -o uinput_tap
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/uinput.h>
|
||||
|
||||
#define DEV "/dev/uinput"
|
||||
|
||||
/* ---- input codes (avoid header dependency issues) ---- */
|
||||
#ifndef EV_SYN
|
||||
#define EV_SYN 0
|
||||
#define EV_KEY 1
|
||||
#define EV_REL 2
|
||||
#define EV_ABS 3
|
||||
#endif
|
||||
#ifndef ABS_MT_SLOT
|
||||
#define ABS_MT_SLOT 0x2f
|
||||
#define ABS_MT_TOUCH_MAJOR 0x30
|
||||
#define ABS_MT_POSITION_X 0x35
|
||||
#define ABS_MT_POSITION_Y 0x36
|
||||
#define ABS_MT_TRACKING_ID 0x39
|
||||
#endif
|
||||
#ifndef BTN_TOUCH
|
||||
#define BTN_TOUCH 0x14a
|
||||
#endif
|
||||
#ifndef SYN_REPORT
|
||||
#define SYN_REPORT 0
|
||||
#endif
|
||||
#ifndef KEY_VOLUMEUP
|
||||
#define KEY_VOLUMEUP 115
|
||||
#define KEY_VOLUMEDOWN 114
|
||||
#define KEY_POWER 116
|
||||
#define KEY_PLAY 207
|
||||
#define KEY_NEXT 163
|
||||
#define KEY_PREVIOUS 165
|
||||
#endif
|
||||
|
||||
static int ufd = -1;
|
||||
|
||||
static void emit(int type, int code, int val)
|
||||
{
|
||||
struct input_event ev;
|
||||
memset(&ev, 0, sizeof ev);
|
||||
ev.type = type;
|
||||
ev.code = code;
|
||||
ev.value = val;
|
||||
if (write(ufd, &ev, sizeof ev) != sizeof ev)
|
||||
perror("write event");
|
||||
}
|
||||
|
||||
static void syn(void)
|
||||
{
|
||||
emit(EV_SYN, SYN_REPORT, 0);
|
||||
}
|
||||
|
||||
/* full tap: MT protocol B + legacy ABS_X/ABS_Y + BTN_TOUCH */
|
||||
static void tap(int x, int y)
|
||||
{
|
||||
/* MT slot */
|
||||
emit(EV_ABS, ABS_MT_SLOT, 0);
|
||||
emit(EV_ABS, ABS_MT_TRACKING_ID, 7);
|
||||
emit(EV_ABS, ABS_MT_POSITION_X, x);
|
||||
emit(EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
emit(EV_ABS, ABS_MT_TOUCH_MAJOR, 6);
|
||||
/* legacy */
|
||||
emit(EV_ABS, ABS_X, x);
|
||||
emit(EV_ABS, ABS_Y, y);
|
||||
emit(EV_KEY, BTN_TOUCH, 1);
|
||||
syn();
|
||||
usleep(60000);
|
||||
emit(EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
emit(EV_KEY, BTN_TOUCH, 0);
|
||||
syn();
|
||||
}
|
||||
|
||||
static void keytap(int code)
|
||||
{
|
||||
emit(EV_KEY, code, 1);
|
||||
syn();
|
||||
usleep(80000);
|
||||
emit(EV_KEY, code, 0);
|
||||
syn();
|
||||
}
|
||||
|
||||
/* Use the legacy write()-based uinput API (struct uinput_user_dev) which is
|
||||
* supported by all kernels including the Ingenic 4.4.94 SDK (UI_DEV_SETUP
|
||||
* ioctl layout differs across versions -> avoid it). */
|
||||
/* Ingenic kernel 4.4.94 changed UINPUT_IOCTL_BASE from 'U'(0x55) to 'f'(0x66) */
|
||||
#define UINPUT_BASE 0x66
|
||||
#define UI_DEV_CREATE ((0x66u << 8) | 1u)
|
||||
#define UI_DEV_DESTROY ((0x66u << 8) | 2u)
|
||||
#define UI_SET_EVBIT (0x40000000u | (4u << 16) | (0x66u << 8) | 100u)
|
||||
#define UI_SET_KEYBIT (0x40000000u | (4u << 16) | (0x66u << 8) | 101u)
|
||||
#define UI_SET_RELBIT (0x40000000u | (4u << 16) | (0x66u << 8) | 102u)
|
||||
#define UI_SET_ABSBIT (0x40000000u | (4u << 16) | (0x66u << 8) | 103u)
|
||||
|
||||
struct uinput_user_dev_v44 {
|
||||
char name[80];
|
||||
struct input_id id;
|
||||
int ff_effects_max;
|
||||
int absmax[64];
|
||||
int absmin[64];
|
||||
int absfuzz[64];
|
||||
int absflat[64];
|
||||
};
|
||||
|
||||
static void set_abs(struct uinput_user_dev_v44 *u, int code, int min, int max)
|
||||
{
|
||||
u->absmin[code] = min;
|
||||
u->absmax[code] = max;
|
||||
}
|
||||
|
||||
static int dev_create(const char *name, unsigned short vendor,
|
||||
unsigned short product, unsigned short version)
|
||||
{
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, name, 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = vendor;
|
||||
u.id.product = product;
|
||||
u.id.version = version;
|
||||
if (write(ufd, &u, sizeof u) != (ssize_t)sizeof u) { perror("write uinput"); return -1; }
|
||||
if (ioctl(ufd, UI_DEV_CREATE) < 0) { perror("UI_DEV_CREATE"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_touch(const char *name)
|
||||
{
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_KEY);
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_ABS);
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_SYN);
|
||||
ioctl(ufd, UI_SET_KEYBIT, BTN_TOUCH);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_X);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_Y);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_MT_SLOT);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_MT_TOUCH_MAJOR);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_MT_POSITION_X);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_MT_POSITION_Y);
|
||||
ioctl(ufd, UI_SET_ABSBIT, ABS_MT_TRACKING_ID);
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, name, 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 0xdead;
|
||||
u.id.product = 0xbeef;
|
||||
u.id.version = 1;
|
||||
set_abs(&u, ABS_X, 0, 1023);
|
||||
set_abs(&u, ABS_Y, 0, 1023);
|
||||
set_abs(&u, ABS_MT_SLOT, 0, 9);
|
||||
set_abs(&u, ABS_MT_TOUCH_MAJOR, 0, 15);
|
||||
set_abs(&u, ABS_MT_POSITION_X, 0, 1023);
|
||||
set_abs(&u, ABS_MT_POSITION_Y, 0, 1023);
|
||||
set_abs(&u, ABS_MT_TRACKING_ID, 0, 65535);
|
||||
if (write(ufd, &u, sizeof u) != (ssize_t)sizeof u) { perror("write uinput"); return -1; }
|
||||
if (ioctl(ufd, UI_DEV_CREATE) < 0) { perror("UI_DEV_CREATE"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_keys(const char *name)
|
||||
{
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_KEY);
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_SYN);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_VOLUMEUP);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_VOLUMEDOWN);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_PLAY);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_NEXT);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_PREVIOUS);
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, name, 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 1;
|
||||
u.id.product = 1;
|
||||
u.id.version = 0x100;
|
||||
if (write(ufd, &u, sizeof u) != (ssize_t)sizeof u) { perror("write uinput"); return -1; }
|
||||
if (ioctl(ufd, UI_DEV_CREATE) < 0) { perror("UI_DEV_CREATE"); return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "usage: %s daemon|tap|key|seq ...\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(argv[1], "scan")) {
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "scan-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 5; u.id.product = 5; u.id.version = 1;
|
||||
write(ufd, &u, sizeof u);
|
||||
/* scan all 16-bit cmd cores (type<<8|nr), report non-EINVAL/ENOTTY */
|
||||
int found = 0;
|
||||
for (int t = 0; t < 256 && found < 40; t++) {
|
||||
for (int n = 0; n < 256 && found < 40; n++) {
|
||||
unsigned int cmd = (t << 8) | n; /* no dir/size bits */
|
||||
errno = 0;
|
||||
int rc = ioctl(ufd, cmd, 0);
|
||||
if (rc == 0 || (errno != EINVAL && errno != ENOTTY)) {
|
||||
printf("cmd=0x%04x (t=%02x n=%02x) rc=%d errno=%d\n", cmd, t, n, rc, errno);
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("done found=%d\n", found);
|
||||
/* deep scan nr 0x7d/0x7e with valid pointer + size bits */
|
||||
int val = 0;
|
||||
for (int nr = 0x7d; nr <= 0x7e; nr++) {
|
||||
for (int sz = 0; sz < 128; sz++) {
|
||||
unsigned int cmd = 0x40000000u | ((unsigned int)sz << 16) | (0x66u << 8) | (unsigned int)nr;
|
||||
errno = 0;
|
||||
int rc = ioctl(ufd, cmd, &val);
|
||||
if (rc == 0 || (errno != EINVAL && errno != ENOTTY)) {
|
||||
printf("deep cmd=0x%08x nr=%02x sz=%d rc=%d errno=%d\n", cmd, nr, sz, rc, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* also try _IOR (0x80000000) */
|
||||
for (int nr = 0x7d; nr <= 0x7e; nr++) {
|
||||
for (int sz = 0; sz < 128; sz++) {
|
||||
unsigned int cmd = 0x80000000u | ((unsigned int)sz << 16) | (0x66u << 8) | (unsigned int)nr;
|
||||
errno = 0;
|
||||
int rc = ioctl(ufd, cmd, &val);
|
||||
if (rc == 0 || (errno != EINVAL && errno != ENOTTY)) {
|
||||
printf("read cmd=0x%08x nr=%02x sz=%d rc=%d errno=%d\n", cmd, nr, sz, rc, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
sleep(1);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "verbose2")) {
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
printf("fd=%d\n", ufd);
|
||||
int r;
|
||||
r = ioctl(ufd, UI_SET_EVBIT, EV_KEY); printf("SET_EVBIT KEY rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_EVBIT, EV_ABS); printf("SET_EVBIT ABS rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_EVBIT, EV_SYN); printf("SET_EVBIT SYN rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_KEYBIT, BTN_TOUCH); printf("SET_KEYBIT TOUCH rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_ABSBIT, ABS_X); printf("SET_ABSBIT X rc=%d errno=%d\n", r, errno);
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "v2-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 6; u.id.product = 6; u.id.version = 1;
|
||||
set_abs(&u, ABS_X, 0, 1023);
|
||||
ssize_t wr = write(ufd, &u, sizeof u);
|
||||
printf("write=%zd errno=%d\n", wr, errno);
|
||||
r = ioctl(ufd, UI_DEV_CREATE); printf("DEV_CREATE rc=%d errno=%d\n", r, errno);
|
||||
printf("sleeping 10s...\n");
|
||||
sleep(10);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "inject")) {
|
||||
/* 直接 write /dev/input/event1 (goodix-ts): evdev 支持 write 注入。
|
||||
* 事件序列与 daemon 的 tap() 完全一致 (MT 协议 B + legacy ABS_X/Y +
|
||||
* BTN_TOUCH),与真实 goodix 驱动一致,hgl_ts 解析最可靠。 */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
const char *devpath = argc > 4 ? argv[4] : "/dev/input/event1";
|
||||
int fd = open(devpath, O_WRONLY);
|
||||
if (fd < 0) { perror("open evdev"); return 1; }
|
||||
struct input_event ev;
|
||||
int x = atoi(argv[2]), y = atoi(argv[3]);
|
||||
ssize_t wr;
|
||||
#define W(type_, code_, val_) do { \
|
||||
memset(&ev, 0, sizeof ev); \
|
||||
ev.type = (type_); ev.code = (code_); ev.value = (val_); \
|
||||
wr = write(fd, &ev, sizeof ev); \
|
||||
printf("wr %s rc=%zd errno=%d\n", #code_, wr, errno); \
|
||||
} while (0)
|
||||
W(EV_ABS, ABS_MT_SLOT, 0);
|
||||
W(EV_ABS, ABS_MT_TRACKING_ID, 7);
|
||||
W(EV_ABS, ABS_MT_POSITION_X, x);
|
||||
W(EV_ABS, ABS_MT_POSITION_Y, y);
|
||||
W(EV_ABS, ABS_MT_TOUCH_MAJOR, 6);
|
||||
W(EV_ABS, ABS_X, x);
|
||||
W(EV_ABS, ABS_Y, y);
|
||||
W(EV_KEY, BTN_TOUCH, 1);
|
||||
W(EV_SYN, SYN_REPORT, 0);
|
||||
usleep(80000);
|
||||
W(EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||
W(EV_KEY, BTN_TOUCH, 0);
|
||||
W(EV_SYN, SYN_REPORT, 0);
|
||||
printf("injected tap %d,%d to %s\n", x, y, devpath);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "alt")) {
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "alt-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 3; u.id.product = 3; u.id.version = 1;
|
||||
/* 厂商命令 nr=125/126 (base 0x66): 试带各种结构 */
|
||||
int r;
|
||||
r = ioctl(ufd, 0x667d, &u); printf("ioctl 0x667d(user_dev) rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, 0x667e, &u); printf("ioctl 0x667e(user_dev) rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, 0x6601, 0); printf("ioctl 0x6601(create) rc=%d errno=%d\n", r, errno);
|
||||
if (r == 0) { printf("created? sleeping\n"); sleep(4); }
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "brute")) {
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "brute-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 7; u.id.product = 7; u.id.version = 1;
|
||||
ssize_t wr = write(ufd, &u, sizeof u);
|
||||
printf("write=%zd errno=%d\n", wr, errno);
|
||||
/* brute UI_DEV_CREATE = _IO(base,1) = (base<<8)|1 */
|
||||
for (int b = 0; b < 256; b++) {
|
||||
unsigned long req = (unsigned long)((b << 8) | 1); /* brute keeps generic */
|
||||
errno = 0;
|
||||
int rc = ioctl(ufd, req, 0);
|
||||
if (rc == 0) { printf("FOUND base=0x%02x (%c) rc=0\n", b, b>=32&&b<127?b:'?'); break; }
|
||||
if (errno != EINVAL && errno != ENOTTY)
|
||||
printf("base=0x%02x rc=%d errno=%d\n", b, rc, errno);
|
||||
}
|
||||
sleep(2);
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "verbose")) {
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
printf("fd=%d\n", ufd);
|
||||
int r;
|
||||
r = ioctl(ufd, UI_SET_EVBIT, EV_KEY); printf("SET_EVBIT KEY rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_EVBIT, EV_SYN); printf("SET_EVBIT SYN rc=%d errno=%d\n", r, errno);
|
||||
r = ioctl(ufd, UI_SET_KEYBIT, KEY_POWER); printf("SET_KEYBIT PWR rc=%d errno=%d\n", r, errno);
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "verbose-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 8; u.id.product = 8; u.id.version = 1;
|
||||
ssize_t wr = write(ufd, &u, sizeof u);
|
||||
printf("write rc=%zd errno=%d (size %zu)\n", wr, errno, sizeof u);
|
||||
r = ioctl(ufd, UI_DEV_CREATE); printf("DEV_CREATE rc=%d errno=%d\n", r, errno);
|
||||
if (r == 0) { printf("OK sleeping\n"); sleep(3); }
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "minimal")) {
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_KEY);
|
||||
ioctl(ufd, UI_SET_EVBIT, EV_SYN);
|
||||
ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
|
||||
struct uinput_user_dev_v44 u;
|
||||
memset(&u, 0, sizeof u);
|
||||
strncpy(u.name, "minimal-test", 79);
|
||||
u.id.bustype = BUS_VIRTUAL;
|
||||
u.id.vendor = 9;
|
||||
u.id.product = 9;
|
||||
u.id.version = 1;
|
||||
ssize_t wr = write(ufd, &u, sizeof u);
|
||||
printf("write=%zd (expect %zu)\n", wr, sizeof u);
|
||||
int rc = ioctl(ufd, UI_DEV_CREATE);
|
||||
printf("create rc=%d errno=%d\n", rc, errno);
|
||||
if (rc == 0) {
|
||||
printf("device created, sleeping 5s\n");
|
||||
sleep(5);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(argv[1], "daemon")) {
|
||||
if (argc < 3) { fprintf(stderr, "daemon <fifo>\n"); return 1; }
|
||||
ufd = open(DEV, O_WRONLY | O_NONBLOCK);
|
||||
if (ufd < 0) { perror("open uinput"); return 1; }
|
||||
if (create_touch("goodix-ts-virt") < 0) return 1;
|
||||
printf("touch device created\n");
|
||||
if (create_keys("md-gpio-keys-virt") < 0) return 1;
|
||||
printf("key device created\n");
|
||||
fflush(stdout);
|
||||
/* serve fifo */
|
||||
unlink(argv[2]);
|
||||
if (mkfifo(argv[2], 0600) < 0) { perror("mkfifo"); return 1; }
|
||||
for (;;) {
|
||||
int f = open(argv[2], O_RDONLY);
|
||||
if (f < 0) { perror("open fifo"); sleep(1); continue; }
|
||||
char line[128];
|
||||
int n;
|
||||
while ((n = read(f, line, sizeof line - 1)) > 0) {
|
||||
line[n] = 0;
|
||||
int x, y, code;
|
||||
if (sscanf(line, "tap %d %d", &x, &y) == 2) {
|
||||
printf("tap %d %d\n", x, y); fflush(stdout);
|
||||
tap(x, y);
|
||||
} else if (sscanf(line, "key %d", &code) == 1) {
|
||||
printf("key %d\n", code); fflush(stdout);
|
||||
keytap(code);
|
||||
}
|
||||
}
|
||||
close(f);
|
||||
}
|
||||
} else if (!strcmp(argv[1], "tap")) {
|
||||
int x = atoi(argv[3]), y = atoi(argv[4]);
|
||||
int f = open(argv[2], O_WRONLY);
|
||||
if (f < 0) { perror("fifo"); return 1; }
|
||||
char buf[64];
|
||||
int n = snprintf(buf, sizeof buf, "tap %d %d\n", x, y);
|
||||
write(f, buf, n);
|
||||
close(f);
|
||||
return 0;
|
||||
} else if (!strcmp(argv[1], "key")) {
|
||||
int code = atoi(argv[3]);
|
||||
int f = open(argv[2], O_WRONLY);
|
||||
if (f < 0) { perror("fifo"); return 1; }
|
||||
char buf[64];
|
||||
int n = snprintf(buf, sizeof buf, "key %d\n", code);
|
||||
write(f, buf, n);
|
||||
close(f);
|
||||
return 0;
|
||||
} else if (!strcmp(argv[1], "seq")) {
|
||||
/* seq <fifo> x1,y1;x2,y2;... */
|
||||
int f = open(argv[2], O_WRONLY);
|
||||
if (f < 0) { perror("fifo"); return 1; }
|
||||
char *p = argv[3];
|
||||
char buf[64];
|
||||
while (*p) {
|
||||
int x, y;
|
||||
if (sscanf(p, "%d,%d", &x, &y) == 2) {
|
||||
int n = snprintf(buf, sizeof buf, "tap %d %d\n", x, y);
|
||||
write(f, buf, n);
|
||||
usleep(350000);
|
||||
}
|
||||
while (*p && *p != ';') p++;
|
||||
if (*p == ';') p++;
|
||||
}
|
||||
close(f);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user