refactor(panel): 前后端按模块拆分+屏幕/控制合并页 — 后端meowpanel.c 6372行拆src/*.c+mp.h(235函数原型,20端点output byte-identical,0warning)+前端拆mp_shared/mp_pages/meowpanel三层;屏幕·遥控合并(左屏实时画面+右MD3 SVG矢量按钮无emoji);重编后热更TF卡
This commit is contained in:
1 parent
f3ae06d7cd
commit
2dc4cad454
26 files changed
+9317
-2755
No files matched your search
@@ -0,0 +1,126 @@
|
||||
/* 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;
|
||||
}
|
||||
Reference in new issue
Block a user