diff options
author | Oxore <oxore@protonmail.com> | 2024-01-01 01:41:38 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2024-01-01 01:41:38 +0300 |
commit | 6474e88847f9adf627b91fb56778fd9a9b775d66 (patch) | |
tree | 2025ebfddb368b1542dc91019b3924f63cce1389 | |
parent | 502c9e34eef744065855b0e033191f0d8bd4ab73 (diff) |
Impl switching between normal and keyboard mode
-rw-r--r-- | Readme.md | 2 | ||||
-rw-r--r-- | layout.svg | 23 | ||||
-rw-r--r-- | main.c | 153 |
3 files changed, 115 insertions, 63 deletions
@@ -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:  @@ -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" /> <text xml:space="preserve" style="font-weight:bold;font-size:3.52778px;line-height:1.1;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none" @@ -4643,26 +4643,7 @@ <g id="g307860-3" transform="translate(-91.25788,21.249376)" - style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke:#ff0000"> - <rect - height="7.3990045" - width="48.712379" - y="160.68263" - x="-53.886993" - id="rect1604-6" - style="fill:#ffffff;stroke:#ff0000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none" /> - <text - xml:space="preserve" - style="font-weight:bold;font-size:2.82222px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;letter-spacing:0px;word-spacing:0px;text-anchor:middle;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke:none;fill:#ff0000" - x="-29.482573" - y="165.1497" - id="text301519-7"><tspan - sodipodi:role="line" - id="tspan301517-5" - style="font-size:2.82222px;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke:none;fill:#ff0000" - x="-29.482573" - y="165.1497">Currently not implemented</tspan></text> - </g> + style="stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke:#ff0000" /> <g id="g307860-3-3" transform="translate(-178.33217,18.678992)" @@ -76,10 +76,11 @@ enum keys_mask { struct state { uint32_t keys; // keys_mask + bool keyboard_mode; }; #define MAPPINGS_NUM 105 -struct mapping g_mapping[MAPPINGS_NUM] = { +static struct mapping g_mapping[MAPPINGS_NUM] = { /* Right single */ { .first = SIDE_RIGHT, .keys = KMASK_WEST, .code = KEY_BACKSPACE }, { .first = SIDE_RIGHT, .keys = KMASK_SOUTH, .code = KEY_ENTER }, @@ -178,19 +179,40 @@ struct mapping g_mapping[MAPPINGS_NUM] = { { .first = SIDE_NO, .keys = 0, .code = KEY_DOWN }, }; -bool should_stop = false; -int ifd = -1; +static bool g_should_stop = false; +static int g_ifd = -1; +struct state g_state = {0}; + +static void grab(int ifd) +{ + int ret = ioctl(ifd, EVIOCGRAB, (void *)1); + int err = errno; + if (ret != 0) { + fprintf(stderr, "Grab failed: ioctl(ifd, EVIOCGRAB, 1), err=%d: %s", err, strerror(err)); + exit(1); + } +} + +static void ungrab(int ifd) +{ + int ret = ioctl(ifd, EVIOCGRAB, (void *)0); + int err = errno; + if (ret != 0) { + fprintf(stderr, "Ungrab failed: ioctl(ifd, EVIOCGRAB, 0), err=%d: %s", err, strerror(err)); + exit(1); + } +} static void sigint_handler(int _value) { (void) _value; - should_stop = true; + g_should_stop = true; printf("Received SIGINT, quitting...\n"); - { - int ret = ioctl(ifd, EVIOCGRAB, (void *)0); + if (g_state.keyboard_mode) { + int ret = ioctl(g_ifd, EVIOCGRAB, (void *)0); if (ret != 0) { fprintf(stderr, "Ungrab failed: "); - perror("ioctl(ifd, EVIOCGRAB, 0)"); + perror("ioctl(g_ifd, EVIOCGRAB, 0)"); exit(1); } } @@ -289,8 +311,42 @@ static enum side which_side_state(struct state state) return (state.keys >> 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; } } |