From 9bb38e28d787cd7e5c49f69fc0676f7ae2231dd4 Mon Sep 17 00:00:00 2001 From: Linus Date: Thu, 26 Dec 2019 17:30:15 +0100 Subject: [PATCH] Port rmTouchToggler to rmButtonToggler --- .gitignore | 3 +- README.md | 20 +++--- button_toggler.c | 154 +++++++++++++++++++++++++++++++++++++++++ button_toggler.service | 9 +++ touchToggler.c | 123 -------------------------------- touchToggler.service | 9 --- 6 files changed, 176 insertions(+), 142 deletions(-) create mode 100644 button_toggler.c create mode 100644 button_toggler.service delete mode 100644 touchToggler.c delete mode 100644 touchToggler.service diff --git a/.gitignore b/.gitignore index d3e24ff..45f80d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -touchToggler +button_toggler +.vscode/** diff --git a/README.md b/README.md index d7391fb..1be65a3 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ -# rmTouchToggler +# rmButtonToggler -This tool lets you toggle the touchpad by pressing both the left and the right button at once. +This tool lets you toggle all button input by pressing the left and right buttons together. -This is a answer to [this post](https://www.reddit.com/r/RemarkableTablet/comments/b48tbv/). +## IMPORTANT +Blocking all buttons also **includes** the **power/wakeup** button! +Should the device enter sleep mode, you either need to perform the button combination again (it'll work even when sleeping) or restart the device by holding the power button for about 10 seconds (that will still work). Otherwise you won't be able to get the device out of sleep. -**DISCLAIMER**: I won't be liable for any harm done using this software. +**DISCLAIMER:** I won't be liable for any harm done using this software. # Install Copy the latest release binary (or compile it yourself using the [cross-compiler](https://remarkable.engineering/)) to the reMarkable. -It should be in the home directory (at `/home/root/touchToggler`). +It should be in the home directory (at `/home/root/button_toggler`). -Copy the file `touchToggler.service` into `/etc/system/systemd/`. +Copy the file `button_toggler.service` into `/etc/system/systemd/`. SSH into the reMarkable. -Run `chmod +x touchToggler`. +Run `chmod +x button_toggler`. -Start it using `systemctl start touchToggler` and stop it using `systemctl stop touchToggler`. +Start it using `systemctl start button_toggler` and stop it using `systemctl stop button_toggler`. -To enable it on autostart run `systemctl enable touchToggler`. To revert this run `systemctl disable touchToggler`. +To enable it on autostart run `systemctl enable button_toggler`. To revert this run `systemctl disable button_toggler`. diff --git a/button_toggler.c b/button_toggler.c new file mode 100644 index 0000000..68b2a06 --- /dev/null +++ b/button_toggler.c @@ -0,0 +1,154 @@ +/* + * Press LEFT+RIGHT to block and unblock all buttons. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Renamed copy of input_event from linux-kernel of the reMarkable +// Source: https://github.com/reMarkable/linux/blob/b82cb2adc32411c98ffc0db86cdd12858c8b39df/include/uapi/linux/input.h#L24 +struct rm_input_event { + struct timeval time; + uint16_t type; + uint16_t code; + int32_t value; +}; + +typedef enum { + LEFT, + MIDDLE, + RIGHT, + POWER, + WAKEUP +} Button; + +// Codes as used by ev +typedef enum { + CODE_LEFT = 105, + CODE_MIDDLE = 102, + CODE_RIGHT = 106, + CODE_POWER = 116, + CODE_WAKEUP = 143 +} ButtonCode; + +Button codeToButton(ButtonCode evCode) { + // Source: https://github.com/canselcik/libremarkable/blob/master/src/input/gpio.rs + switch(evCode) { + case CODE_LEFT: return LEFT; + case CODE_MIDDLE: return MIDDLE; + case CODE_RIGHT: return RIGHT; + case CODE_POWER: return POWER; + case CODE_WAKEUP: return WAKEUP; + default: + fprintf(stderr, "FATAL: Unknown evCode %d in the context of a button!!!"); + exit(1); + return -1; // Doesn't matter + } +} + +ButtonCode buttonToCode(Button button) { + switch(button) { + case LEFT: return CODE_LEFT; + case MIDDLE: return CODE_MIDDLE; + case RIGHT: return CODE_RIGHT; + case POWER: return CODE_POWER; + case WAKEUP: return CODE_WAKEUP; + default: + fprintf(stderr, "FATAL: Unknown Button enum value %d !!!"); + exit(1); + return -1; // Doesn't matter + } +} + +int gpioInputFd; +bool buttonState[5]; +bool blocking = false; + + +void setBlocking(bool newBlocking) { + if(blocking == newBlocking) + return; + + ioctl(gpioInputFd, EVIOCGRAB, newBlocking); + if(newBlocking) + printf("Buttons grabbed. Only filtered input allowed!\n"); + else + printf("Touchpad released. All input allowed!\n"); + + blocking = newBlocking; +} + +int main(int argc, char const *argv[]) +{ + // Init state + buttonState[LEFT] = false; + buttonState[MIDDLE] = false; + buttonState[RIGHT] = false; + buttonState[POWER] = false; + buttonState[WAKEUP] = false; + + // Open file where input events for the hardware buttons (over gpio pins) get received + gpioInputFd = open("/dev/input/event2", O_RDWR); + + if(gpioInputFd < 0) { + perror("Failed to open gpio event file"); + exit(1); + } + + struct rm_input_event inputEvent; // Will contain the read data + size_t readBytes; // Read progress in case one event needs multiple reads. + ssize_t result; + + while(1) { + result = read(gpioInputFd, ((uint8_t*) &inputEvent) + readBytes, sizeof(inputEvent) - readBytes); + + if(result < 0) { + // Failed to read required data. Should never happen. + perror("Failed to read gpio event file"); + + if(close(gpioInputFd) != 0) + perror("Faild to close gpio event file"); + + return 1; + } + + readBytes += result; + if(readBytes < sizeof(inputEvent)) + continue; // Event not fully read, yet. + readBytes = 0; // Reset read progress. + + if(inputEvent.type != 1) + continue; + + Button button = codeToButton(inputEvent.code); + bool isPressed = inputEvent.value > 0; + buttonState[button] = isPressed; + //printf("Pressed: %d", isPressed); + + if(buttonState[LEFT] && buttonState[RIGHT] && (button == LEFT || button == RIGHT)) { + setBlocking(!blocking); + } + + // Debug: + //printf("\nLEFT: %d\nMIDDLE: %d\nRIGHT: %d\nPOWER: %d\nWAKEUP: %d\n", + // buttonState[LEFT], buttonState[MIDDLE], buttonState[RIGHT], buttonState[POWER], buttonState[WAKEUP]); + //printf("Type: %d, Code: %d, Value: %d\n", inputEvent.type, inputEvent.code, inputEvent.value); + + + } + + + return 0; +} diff --git a/button_toggler.service b/button_toggler.service new file mode 100644 index 0000000..7c73319 --- /dev/null +++ b/button_toggler.service @@ -0,0 +1,9 @@ +[Unit] +Description=LEFT+RIGHT to toggle the all buttons. +After=home.mount + +[Service] +ExecStart=/home/root/button_toggler + +[Install] +WantedBy=multi-user.target diff --git a/touchToggler.c b/touchToggler.c deleted file mode 100644 index b822f14..0000000 --- a/touchToggler.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Press LEFT+RIGHT to block and unblock the touchscreen. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Renamed copy of input_event from linux-kernel of the reMarkable -// Source: https://github.com/reMarkable/linux/blob/b82cb2adc32411c98ffc0db86cdd12858c8b39df/include/uapi/linux/input.h#L24 -struct rm_input_event { - struct timeval time; - uint16_t type; - uint16_t code; - int32_t value; -}; - -enum Button { - LEFT, - MIDDLE, - RIGHT, - POWER, - WAKEUP -}; - -ssize_t codeToButton(uint16_t evCode) { - // Source: https://github.com/canselcik/libremarkable/blob/master/src/input/gpio.rs - switch(evCode) { - case 105: - return LEFT; - case 102: - return MIDDLE; - case 106: - return RIGHT; - case 116: - return POWER; - case 143: - return WAKEUP; - default: - fprintf(stderr, "FATAL: Unknown evCode %d !!!"); - exit(1); - return -1; - } -} - -int main(int argc, char const *argv[]) -{ - - int touchInputFd = open("/dev/input/event1", O_WRONLY | O_NONBLOCK); // Even though we won't write - // Open file where input events for the hardware buttons (over gpio pins) get received - FILE* gpioInputFp = gpioInputFp = fopen("/dev/input/event2", "r"); - - if(gpioInputFp == NULL) { - fprintf(stderr, "Failed to open gpio event file!\n"); - exit(1); - } - - struct rm_input_event inputEvent; // Will contain the read data - size_t inputEventSize = sizeof(inputEvent); - size_t readBytes; - - uint8_t buttonState[5]; - buttonState[LEFT] = 0; - buttonState[MIDDLE] = 0; - buttonState[RIGHT] = 0; - buttonState[POWER] = 0; - buttonState[WAKEUP] = 0; - - /*bool*/uint8_t touchGrabbed = 0; - - while(1) { - readBytes = fread((void*) &inputEvent, 1, inputEventSize, gpioInputFp); - - if(readBytes != inputEventSize) { - // Failed to read required data. Should never happen. - perror("Failed to read gpio event file"); - - if(fclose(gpioInputFp) != 0) - perror("Faild to close gpio event file"); - - return 1; - } - - if(inputEvent.type != 1) - continue; - - int button = codeToButton(inputEvent.code); - uint8_t isPressed = inputEvent.value ? 1 : 0; - buttonState[button] = isPressed; - - if(buttonState[LEFT] && buttonState[RIGHT] && (button == LEFT || button == RIGHT)) { - if(!touchGrabbed) { - printf("Touchpad grabbed. No input possible!\n"); - ioctl(touchInputFd, EVIOCGRAB, 1); // Block touch input - } else { - printf("Touchpad released. Input possible again.\n"); - ioctl(touchInputFd, EVIOCGRAB, 0); // Unblock touch input - } - - touchGrabbed = !touchGrabbed; - } - - // Debug: - //printf("\nLEFT: %d\nMIDDLE: %d\nRIGHT: %d\nPOWER: %d\nWAKEUP: %d\n", - // buttonState[LEFT], buttonState[MIDDLE], buttonState[RIGHT], buttonState[POWER], buttonState[WAKEUP]); - //printf("Type: %d, Code: %d, Value: %d\n", inputEvent.type, inputEvent.code, inputEvent.value); - - - } - - - return 0; -} diff --git a/touchToggler.service b/touchToggler.service deleted file mode 100644 index 9afd861..0000000 --- a/touchToggler.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=LEFT+RIGHT to toggle the touchscreen. -After=home.mount - -[Service] -ExecStart=/home/root/touchToggler - -[Install] -WantedBy=multi-user.target