Files
MeowOS-For-R3P2/patch_v2/meowpanel/src/mp_key.c
T

127 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* mp_key.c — 远程控制域:按键注入(写 /dev/input/event* EV_KEY,物理键红线内)。 */
#include "mp.h"
#define PWR_KEYDEV "/dev/input/event0"
#define ADC_KEYDEV "/dev/input/event2"
int keycode_to_device(int code, const char **dev)
{
switch (code) {
case KEY_POWER: *dev = PWR_KEYDEV; return KEY_POWER;
case KEY_PREVIOUSSONG: *dev = PWR_KEYDEV; return KEY_PREVIOUSSONG;
case KEY_VOLUMEUP: *dev = ADC_KEYDEV; return KEY_VOLUMEUP;
case KEY_VOLUMEDOWN: *dev = ADC_KEYDEV; return KEY_VOLUMEDOWN;
case KEY_NEXTSONG: *dev = ADC_KEYDEV; return KEY_NEXTSONG;
case KEY_PLAYPAUSE: *dev = ADC_KEYDEV; return KEY_PLAYPAUSE;
default: return -1;
}
}
int inject_key_event(const char *dev, int code, int down)
{
int fd = open(dev, O_WRONLY | O_NONBLOCK);
if (fd < 0) return -1;
struct input_event ev;
memset(&ev, 0, sizeof ev);
ev.type = EV_KEY;
ev.code = code;
ev.value = down ? 1 : 0;
int ok = (write(fd, &ev, sizeof ev) == (ssize_t)sizeof ev);
if (ok) {
memset(&ev, 0, sizeof ev);
ev.type = EV_SYN;
ev.code = SYN_REPORT;
ev.value = 0;
ok = (write(fd, &ev, sizeof ev) == (ssize_t)sizeof ev);
}
close(fd);
return ok ? 0 : -1;
}
int inject_key_release(int code, int press_ms)
{
const char *dev = NULL;
int kc = keycode_to_device(code, &dev);
if (kc < 0) return -1;
int release_ms = press_ms > 0 ? press_ms : 0;
if (inject_key_event(dev, code, 1) < 0) return -1;
if (release_ms > 0) usleep((useconds_t)release_ms * 1000);
else usleep(80 * 1000);
if (inject_key_event(dev, code, 0) < 0) return -1;
return 0;
}
int api_key_single(int sock, int code, const req_t *r)
{
int press_ms = 0;
char pressbuf[16] = "tap";
const char *press = pressbuf;
if (r->body && r->body[0]) {
jv_t *root = jv_parse(r->body, (int)r->body_len);
if (root) {
jv_t *p = jv_obj_get(root, "press");
if (p && p->type == J_STR) snprintf(pressbuf, sizeof pressbuf, "%s", p->str);
jv_t *m = jv_obj_get(root, "ms");
if (m && m->type == J_NUM) press_ms = (int)m->inum;
jv_free(root);
}
}
if (!strcmp(press, "hold"))
return send_err(sock, 501, "NOT_IMPLEMENTED", "hold 持续注入需常驻通道(阶段 D),后端未实现");
if (strcmp(press, "tap") && strcmp(press, "long"))
return send_err(sock, 400, "BAD_REQUEST", "press 非法");
if (press_ms <= 0) {
if (!strcmp(press, "long")) press_ms = 3000;
}
/* 物理键红线:禁止映射 返回(158)/主页(172)/确认/exit(APPS.md)。 */
if (code == 158 || code == 172 || code == 32 || code == 28 || code == 96)
return send_err(sock, 403, "FORBIDDEN", "该键码(返回/主页/确认)按物理键红线禁止映射");
const char *tmpdev = NULL;
int dispatchable = (keycode_to_device(code, &tmpdev) >= 0);
if (!dispatchable)
return send_err(sock, 422, "UNSUPPORTED", "不支持的键码(仅音量/电源/播放/上下曲)");
if (inject_key_release(code, press_ms) < 0)
return send_err(sock, 500, "INTERNAL", "按键注入失败(无法打开输入设备)");
sbuf_t s = {0};
sA(&s, "{\"code\":%d,\"press\":\"%s\",\"dispatched\":true}", code, press);
int ret = send_json(sock, 200, s.b ? s.b : "");
sbuf_free(&s);
return ret;
}
int api_key_batch(int sock, const req_t *r)
{
if (!r->body || !r->body[0]) return send_err(sock, 400, "BAD_REQUEST", "缺少 body");
jv_t *root = jv_parse(r->body, (int)r->body_len);
if (!root) return send_err(sock, 400, "BAD_REQUEST", "body 非合法 JSON");
jv_t *keys = jv_obj_get(root, "keys");
if (!keys || keys->type != J_ARR) { jv_free(root); return send_err(sock, 400, "BAD_REQUEST", "缺 keys 数组"); }
sbuf_t s = {0};
int first = 1;
for (const jv_t *k = keys->child; k; k = k->next) {
if (k->type != J_OBJ) continue;
jv_t *c = jv_obj_get(k, "code");
jv_t *p = jv_obj_get(k, "press");
jv_t *m = jv_obj_get(k, "ms");
if (!c || c->type != J_NUM) continue;
int code = (int)c->inum;
if (code == 158 || code == 172) continue; /* 红线跳过 */
int press_ms = (m && m->type == J_NUM) ? (int)m->inum : 0;
if (p && p->type == J_STR && !strcmp(p->str, "long") && press_ms <= 0) press_ms = 3000;
const char *tmpdev = NULL;
if (keycode_to_device(code, &tmpdev) < 0) continue;
if (inject_key_release(code, press_ms) < 0) continue;
if (!first) sA(&s, ",");
first = 0;
sA(&s, "%d", code);
}
jv_free(root);
sbuf_t o = {0};
if (first) sA(&o, "{\"dispatched\":[]}");
else sA(&o, "{\"dispatched\":[%s]}", s.b);
int ret = send_json(sock, 200, o.b ? o.b : "");
sbuf_free(&s); sbuf_free(&o);
return ret;
}