diff options
Diffstat (limited to 'platform/x11/joystick_linux.cpp')
-rw-r--r-- | platform/x11/joystick_linux.cpp | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/platform/x11/joystick_linux.cpp b/platform/x11/joystick_linux.cpp index 2793cc5734..3b854a8d46 100644 --- a/platform/x11/joystick_linux.cpp +++ b/platform/x11/joystick_linux.cpp @@ -45,7 +45,9 @@ #define test_bit(nr, addr) (((1UL << ((nr) % LONG_BITS)) & ((addr)[(nr) / LONG_BITS])) != 0) #define NBITS(x) ((((x)-1)/LONG_BITS)+1) +#ifdef UDEV_ENABLED static const char* ignore_str = "/dev/input/js"; +#endif joystick_linux::Joystick::Joystick() { fd = -1; @@ -198,7 +200,6 @@ void joystick_linux::monitor_joysticks(udev *p_udev) { } usleep(50000); } - //printf("exit udev\n"); udev_monitor_unref(mon); } #endif @@ -258,7 +259,7 @@ void joystick_linux::close_joystick(int p_id) { attached_devices.remove(attached_devices.find(joy.devpath)); input->joy_connection_changed(p_id, false, ""); }; -}; +} static String _hex_str(uint8_t p_byte) { @@ -270,7 +271,7 @@ static String _hex_str(uint8_t p_byte) { ret[1] = dict[p_byte & 0xF]; return ret; -}; +} void joystick_linux::setup_joystick_properties(int p_id) { @@ -316,13 +317,21 @@ void joystick_linux::setup_joystick_properties(int p_id) { } } } -} + joy->force_feedback = false; + joy->ff_effect_timestamp = 0; + unsigned long ffbit[NBITS(FF_CNT)]; + if (ioctl(joy->fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) != -1) { + if (test_bit(FF_RUMBLE, ffbit)) { + joy->force_feedback = true; + } + } +} void joystick_linux::open_joystick(const char *p_path) { int joy_num = get_free_joy_slot(); - int fd = open(p_path, O_RDONLY | O_NONBLOCK); + int fd = open(p_path, O_RDWR | O_NONBLOCK); if (fd != -1 && joy_num != -1) { unsigned long evbit[NBITS(EV_MAX)] = { 0 }; @@ -392,6 +401,53 @@ void joystick_linux::open_joystick(const char *p_path) { } } +void joystick_linux::joystick_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) +{ + Joystick& joy = joysticks[p_id]; + if (!joy.force_feedback || joy.fd == -1 || p_weak_magnitude < 0.f || p_weak_magnitude > 1.f || p_strong_magnitude < 0.f || p_strong_magnitude > 1.f) { + return; + } + if (joy.ff_effect_id != -1) { + joystick_vibration_stop(p_id, p_timestamp); + } + + struct ff_effect effect; + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.weak_magnitude = floor(p_weak_magnitude * (float)0xffff); + effect.u.rumble.strong_magnitude = floor(p_strong_magnitude * (float)0xffff); + effect.replay.length = floor(p_duration * 1000); + effect.replay.delay = 0; + + if (ioctl(joy.fd, EVIOCSFF, &effect) < 0) { + return; + } + + struct input_event play; + play.type = EV_FF; + play.code = effect.id; + play.value = 1; + write(joy.fd, (const void*)&play, sizeof(play)); + + joy.ff_effect_id = effect.id; + joy.ff_effect_timestamp = p_timestamp; +} + +void joystick_linux::joystick_vibration_stop(int p_id, uint64_t p_timestamp) +{ + Joystick& joy = joysticks[p_id]; + if (!joy.force_feedback || joy.fd == -1 || joy.ff_effect_id == -1) { + return; + } + + if (ioctl(joy.fd, EVIOCRMFF, joy.ff_effect_id) < 0) { + return; + } + + joy.ff_effect_id = -1; + joy.ff_effect_timestamp = p_timestamp; +} + InputDefault::JoyAxis joystick_linux::axis_correct(const input_absinfo *p_abs, int p_value) const { int min = p_abs->minimum; @@ -485,6 +541,19 @@ uint32_t joystick_linux::process_joysticks(uint32_t p_event_id) { if (len == 0 || (len < 0 && errno != EAGAIN)) { close_joystick(i); }; + + if (joy->force_feedback) { + uint64_t timestamp = input->get_joy_vibration_timestamp(i); + if (timestamp > joy->ff_effect_timestamp) { + Vector2 strength = input->get_joy_vibration_strength(i); + float duration = input->get_joy_vibration_duration(i); + if (strength.x == 0 && strength.y == 0) { + joystick_vibration_stop(i, timestamp); + } else { + joystick_vibration_start(i, strength.x, strength.y, duration, timestamp); + } + } + } } joy_mutex->unlock(); return p_event_id; |