From 51b6fa81abc2cfd6d18be244b328f2a7595dd914 Mon Sep 17 00:00:00 2001 From: Dejvino Date: Sun, 31 May 2020 00:12:58 +0200 Subject: [PATCH] Add vibrate --- README.md | 14 +++++++ meson.build | 2 + src/vibrate.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 src/vibrate.c diff --git a/README.md b/README.md index a1f9cb4..8ac7081 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,20 @@ $ pptk-cpu-sleep get disabled ``` +### vibrate +Controls the vibrator to play a vibration pattern. +``` +# vibrate for 1 second +$ pptk-vibrate 1000 + +# vibrate for 500 ms, wait for 500 ms, repeat this pattern 5 times +# resulting in an alternating vibration for 5 seconds in total +$ pptk-vibrate 500 500 5 + +# 6 short vibrations followed by 3 long vibrations +$ pptk-vibrate 300 200 6 && pptk-vibrate 1500 500 3 +``` + ## Build & Install ``` $ meson build diff --git a/meson.build b/meson.build index 6fc7df1..cf37e07 100644 --- a/meson.build +++ b/meson.build @@ -5,4 +5,6 @@ executable('pptk-backlight', ['src/backlight.c'], executable('pptk-led', ['src/led.c'], install: true, install_mode: install_suid) executable('pptk-cpu-sleep', ['src/cpu-sleep.c'], + install: true, install_mode: install_suid) +executable('pptk-vibrate', ['src/vibrate.c'], install: true, install_mode: install_suid) \ No newline at end of file diff --git a/src/vibrate.c b/src/vibrate.c new file mode 100644 index 0000000..b09b4df --- /dev/null +++ b/src/vibrate.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static char *argv0 = "./vibrate"; +static char *vibrator_file = "/dev/input/event4"; + +void print_usage() +{ + printf("usage: %s LENGTH [DELAY] [COUNT]\n", argv0); + printf(" LENGTH = [0..] ... duration of vibration (in ms)\n"); + printf(" DELAY = [0..] ... delay before vibration is repeated (in ms)\n"); + printf(" COUNT = [1..] ... how many times the vibration pattern is to be repeated\n"); +} + +void print_usage_and_fail() +{ + print_usage(); + exit(EXIT_FAILURE); +} + +void assert(bool success, char* error_message) +{ + if (success) { + return; + } + fprintf(stderr, "%s\n", error_message); + exit(EXIT_FAILURE); +} + +void write_event(int fd, int e_id, int value) +{ + struct input_event event; + memset(&event, 0, sizeof(event)); + event.type = EV_FF; + event.code = e_id; + event.value = value; + int res = write(fd, &event, sizeof event); + assert(res >= 0, "write event failed"); +} + +void vibrate(int length, int delay, int repeat) +{ + int res; + + res = setuid(0); + assert(res == 0, "Cannot set root permissions via setuid(0)."); + + int fd = open(vibrator_file, O_RDWR | O_CLOEXEC); + if (fd < 0) { + fprintf(stderr, "Cannot open file '%s' for writing.\n", vibrator_file); + exit(EXIT_FAILURE); + } + + int effects; + res = ioctl(fd, EVIOCGEFFECTS, &effects); + assert(res >= 0, "ioctl(EVIOCGEFFECTS) failed"); + assert(effects > 0, "not enough simultaneous effects supported"); + + /* upload rumble effect */ + struct ff_effect e; + memset(&e, 0, sizeof(e)); + e.type = FF_RUMBLE, + e.id = -1; + e.replay.length = length; + e.replay.delay = delay; + e.u.rumble.strong_magnitude = 0xc000; + e.u.rumble.weak_magnitude = 0; + res = ioctl(fd, EVIOCSFF, &e); + assert(res >= 0, "ioctl(EVIOCSFF) failed"); + + /* play vibration pattern */ + write_event(fd, e.id, repeat); + usleep((length + delay) * repeat * 1000); + write_event(fd, e.id, 0); + + /* clear rumble effect */ + res = ioctl(fd, EVIOCRMFF, e.id); + assert(res >= 0, "ioctl(EVIOCRMFF) failed"); + + close(fd); +} + +int main(int argc, char *argv[]) +{ + if (argc < 1) { + print_usage_and_fail(); + } + argv0 = argv[0]; + if (argc < 2) { + print_usage_and_fail(); + } + int length = atoi(argv[1]); + int delay = argc < 3 ? 0 : atoi(argv[2]); + int repeat = argc < 4 ? 1 : atoi(argv[3]); + if (length < 0 || delay < 0 || repeat <= 0) { + print_usage_and_fail(); + } + //printf("vibrate %d ms, wait %d ms, repeat %d\n", length, delay, repeat); + vibrate(length, delay, repeat); + exit(EXIT_SUCCESS); +}