From 6474e88847f9adf627b91fb56778fd9a9b775d66 Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 1 Jan 2024 01:41:38 +0300 Subject: Impl switching between normal and keyboard mode --- Readme.md | 2 +- layout.svg | 23 +--------- main.c | 153 ++++++++++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 115 insertions(+), 63 deletions(-) diff --git a/Readme.md b/Readme.md index 826d15e..0716c52 100644 --- a/Readme.md +++ b/Readme.md @@ -123,7 +123,7 @@ udevadm control --reload-rules && udevadm trigger ## Usage -Now you can issue keyboard keypresses by pressing some combinations of the gamepad buttons as shown in the following chart: +The program starts in non-keyboard mode. Press the "PS" button (round one in the middle) to switch to the keyboard mode. Now you can issue keyboard keypresses by pressing some combinations of the gamepad buttons as shown in the following chart: ![Key mapping](layout.svg) diff --git a/layout.svg b/layout.svg index f0cb663..f5e63db 100644 --- a/layout.svg +++ b/layout.svg @@ -4617,7 +4617,7 @@ y="156.78517" x="-81.55162" id="rect1604-1-9" - style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:6, 1;stroke-dashoffset:0" /> + style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0" /> - - Currently not implemented - + style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke:#ff0000" /> > KMASK_SIDE_SHIFT) & 3; } +static struct state release_all(int ofd, struct state state) +{ + if (state.keys & KMASK_LT) { + emulate_key_release(ofd, KEY_LEFTCTRL); + } + if (state.keys & KMASK_RT) { + emulate_key_release(ofd, KEY_LEFTSHIFT); + } + if (state.keys & KMASK_LB) { + emulate_key_release(ofd, KEY_LEFTMETA); + } + if (state.keys & KMASK_RB) { + emulate_key_release(ofd, KEY_LEFTALT); + } + if (state.keys & KMASK_THUMBL_LEFT) + emulate_key_release(ofd, KEY_LEFT); + else if (state.keys & KMASK_THUMBL_RIGHT) + emulate_key_release(ofd, KEY_RIGHT); + if (state.keys & KMASK_THUMBL_UP) + emulate_key_release(ofd, KEY_UP); + else if (state.keys & KMASK_THUMBL_DOWN) + emulate_key_release(ofd, KEY_DOWN); + state.keys = 0; + return state; +} + static struct state keypress(struct state state, struct input_event ev, int ofd) { + if (state.keyboard_mode == false) { + if (ev.type == EV_KEY && ev.code == BTN_MODE) { + state.keyboard_mode = true; + grab(g_ifd); + printf("Keyboard mode on\n"); + } + return state; + } printf("<- %s, code=%u, value=%d\n", ev.type == EV_KEY ? "EV_KEY" : "EV_ABS", ev.code, ev.value); if (which_side_state(state) == SIDE_NO) { const enum side side = which_side_key(ev); @@ -317,23 +373,31 @@ static struct state keypress(struct state state, struct input_event ev, int ofd) break; case BTN_TL2: // Control - state.keys |= KMASK_LT; - emulate_key_press(ofd, KEY_LEFTCTRL); + if (state.keyboard_mode) { + state.keys |= KMASK_LT; + emulate_key_press(ofd, KEY_LEFTCTRL); + } break; case BTN_TR2: // Shift - state.keys |= KMASK_RT; - emulate_key_press(ofd, KEY_LEFTSHIFT); + if (state.keyboard_mode) { + state.keys |= KMASK_RT; + emulate_key_press(ofd, KEY_LEFTSHIFT); + } break; case BTN_TL: // Super - state.keys |= KMASK_LB; - emulate_key_press(ofd, KEY_LEFTMETA); + if (state.keyboard_mode) { + state.keys |= KMASK_LB; + emulate_key_press(ofd, KEY_LEFTMETA); + } break; case BTN_TR: // Alt - state.keys |= KMASK_RB; - emulate_key_press(ofd, KEY_LEFTALT); + if (state.keyboard_mode) { + state.keys |= KMASK_RB; + emulate_key_press(ofd, KEY_LEFTALT); + } break; case BTN_SELECT: state.keys |= KMASK_SHARE; @@ -342,10 +406,13 @@ static struct state keypress(struct state state, struct input_event ev, int ofd) state.keys |= KMASK_OPTIONS; break; case BTN_MODE: - state.keys |= KMASK_PS; + state.keyboard_mode = false; + state = release_all(ofd, state); + ungrab(g_ifd); + printf("Keyboard mode off\n"); break; }; - } else if (ev.type == EV_ABS) { + } else if (state.keyboard_mode && ev.type == EV_ABS) { /* * d-pad is EV_ABS * left-right: code ABS_HAT0X, left=-1, right=1 @@ -402,6 +469,9 @@ static struct state keypress(struct state state, struct input_event ev, int ofd) static struct state keyrelease(struct state state, struct input_event ev, int ofd) { + if (state.keyboard_mode == false) { + return state; + } printf("<- %s, code=%u, value=%d\n", ev.type == EV_KEY ? "EV_KEY" : "EV_ABS", ev.code, ev.value); if (state.keys & KMASK_PRESSED) { for (ssize_t i = 0; i < MAPPINGS_NUM; i++) { @@ -432,23 +502,31 @@ static struct state keyrelease(struct state state, struct input_event ev, int of break; case BTN_TL2: // Control + if (state.keys & KMASK_LT) { + emulate_key_release(ofd, KEY_LEFTCTRL); + } state.keys &= ~KMASK_LT; - emulate_key_release(ofd, KEY_LEFTCTRL); break; case BTN_TR2: // Shift + if (state.keys & KMASK_RT) { + emulate_key_release(ofd, KEY_LEFTSHIFT); + } state.keys &= ~KMASK_RT; - emulate_key_release(ofd, KEY_LEFTSHIFT); break; case BTN_TL: // Super + if (state.keys & KMASK_LB) { + emulate_key_release(ofd, KEY_LEFTMETA); + } state.keys &= ~KMASK_LB; - emulate_key_release(ofd, KEY_LEFTMETA); break; case BTN_TR: // Alt + if (state.keys & KMASK_RB) { + emulate_key_release(ofd, KEY_LEFTALT); + } state.keys &= ~KMASK_RB; - emulate_key_release(ofd, KEY_LEFTALT); break; case BTN_SELECT: state.keys &= ~KMASK_SHARE; @@ -456,6 +534,8 @@ static struct state keyrelease(struct state state, struct input_event ev, int of case BTN_START: state.keys &= ~KMASK_OPTIONS; break; + case BTN_MODE: + break; }; } else if (ev.type == EV_ABS) { /* @@ -500,20 +580,12 @@ int main(int argc, char *argv[]) exit(1); } const char *input_path = argv[1]; - ifd = open(input_path, O_RDONLY); - if (ifd == -1) { + g_ifd = open(input_path, O_RDONLY); + if (g_ifd == -1) { fprintf(stderr, "\"%s\": ", input_path); perror("open"); exit(1); } - { - int ret = ioctl(ifd, EVIOCGRAB, (void *)1); - if (ret != 0) { - fprintf(stderr, "Grab failed: "); - perror("ioctl(ifd, EVIOCGRAB, 1)"); - exit(1); - } - } int ofd = open("/dev/uinput", O_WRONLY); if (ofd == -1) { fprintf(stderr, "\"/dev/uinput\": "); @@ -524,12 +596,11 @@ int main(int argc, char *argv[]) setup_output_device(ofd); - struct state state = {0}; int8_t abs_previous[ABS_CNT] = {0}; - while (!should_stop) { + while (!g_should_stop) { struct input_event ev; - ssize_t ret = read(ifd, &ev, sizeof(ev)); + ssize_t ret = read(g_ifd, &ev, sizeof(ev)); if (ret == -1) { perror("read"); exit(1); @@ -537,9 +608,9 @@ int main(int argc, char *argv[]) switch (ev.type) { case EV_KEY: if (ev.value == 1) { - state = keypress(state, ev, ofd); + g_state = keypress(g_state, ev, ofd); } else if (ev.value == 0) { - state = keyrelease(state, ev, ofd); + g_state = keyrelease(g_state, ev, ofd); } break; case EV_ABS: @@ -550,9 +621,9 @@ int main(int argc, char *argv[]) */ if (ev.code == ABS_HAT0X || ev.code == ABS_HAT0Y) { if (ev.value == 1 || ev.value == -1) { - state = keypress(state, ev, ofd); + g_state = keypress(g_state, ev, ofd); } else if (ev.value == 0) { - state = keyrelease(state, ev, ofd); + g_state = keyrelease(g_state, ev, ofd); } } else if (ev.code == ABS_X || ev.code == ABS_Y || ev.code == ABS_RX || ev.code == ABS_RY) { /* @@ -576,13 +647,13 @@ int main(int argc, char *argv[]) if (abs_previous[ev.code] != 0) { const int8_t value = ev.value; ev.value = 0; - state = keyrelease(state, ev, ofd); + g_state = keyrelease(g_state, ev, ofd); ev.value = value; } - state = keypress(state, ev, ofd); + g_state = keypress(g_state, ev, ofd); abs_previous[ev.code] = ev.value; } else if (ev.value == 0) { - state = keyrelease(state, ev, ofd); + g_state = keyrelease(g_state, ev, ofd); abs_previous[ev.code] = ev.value; } } -- cgit v1.2.3