diff --git a/input/udev_joypad.c b/input/udev_joypad.c index c1014de752..dd5afb26db 100644 --- a/input/udev_joypad.c +++ b/input/udev_joypad.c @@ -56,7 +56,7 @@ struct udev_joypad int num_effects; int effects[2]; // [0] - strong, [1] - weak - bool support_ff[2]; + bool has_set_ff[2]; char *ident; char *path; @@ -183,9 +183,37 @@ static bool udev_set_rumble(unsigned i, enum retro_rumble_effect effect, bool st if (pad->fd < 0) return false; - if (!pad->support_ff[effect]) + if (pad->num_effects < 2) return false; + // Have to defer the force feedback settings to here. + // For some reason, effects are getting dropped when they're set at init. + // Setting at init seems to work for pads which are hotplugged ... + // + // This approach might be cleaner in the end if we end up supporting configurable force feedback. + if (!pad->has_set_ff[effect]) + { + struct ff_effect e; + memset(&e, 0, sizeof(e)); + e.type = FF_RUMBLE; + e.id = -1; + switch (effect) + { + case RETRO_RUMBLE_STRONG: e.u.rumble.strong_magnitude = 0xc000; break; + case RETRO_RUMBLE_WEAK: e.u.rumble.weak_magnitude = 0xc000; break; + default: return false; + } + + if (ioctl(pad->fd, EVIOCSFF, &e) < 0) + { + RARCH_ERR("Failed to set rumble effect on pad #%u.\n", i); + return false; + } + + pad->has_set_ff[effect] = true; + pad->effects[effect] = e.id; + } + struct input_event play; memset(&play, 0, sizeof(play)); play.type = EV_FF; @@ -214,12 +242,84 @@ static void udev_joypad_poll(void) (((1UL << ((nr) % (sizeof(long) * CHAR_BIT))) & ((addr)[(nr) / (sizeof(long) * CHAR_BIT)])) != 0) #define NBITS(x) ((((x) - 1) / (sizeof(long) * CHAR_BIT)) + 1) +#if 0 +static void test_initial_rumble(int fd, const char *path) +{ + // Check for rumble features. + unsigned long ffbit[NBITS(FF_MAX)] = {0}; + if (ioctl(fd, EVIOCGBIT(EV_FF, sizeof(ffbit)), ffbit) >= 0) + { + if (test_bit(FF_RUMBLE, ffbit)) + RARCH_LOG("[udev]: Pad (%s) supports force feedback.\n", + path); + + int effects; + if (ioctl(fd, EVIOCGEFFECTS, &effects) >= 0) + RARCH_LOG("[udev]: Pad (%s) supports %d force feedback effects.\n", path, effects); + + if (effects >= 2) + { + struct ff_effect effect; + bool support_ff[2]; + int effects[2] = {-1, -1}; + + // Strong rumble. + memset(&effect, 0, sizeof(effect)); + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.strong_magnitude = 0x8000; + effect.u.rumble.weak_magnitude = 0; + support_ff[0] = ioctl(fd, EVIOCSFF, &effect) == 0; + if (support_ff[0]) + { + RARCH_LOG("[udev]: (%s) supports \"strong\" rumble effect (id %d).\n", + path, effect.id); + effects[RETRO_RUMBLE_STRONG] = effect.id; // Gets updated by ioctl(). + } + + // Weak rumble. + memset(&effect, 0, sizeof(effect)); + effect.type = FF_RUMBLE; + effect.id = -1; + effect.u.rumble.strong_magnitude = 0; + effect.u.rumble.weak_magnitude = 0xc000; + support_ff[1] = ioctl(fd, EVIOCSFF, &effect) == 0; + if (support_ff[1]) + { + RARCH_LOG("[udev]: Pad (%s) supports \"weak\" rumble effect (id %d).\n", + path, effect.id); + effects[RETRO_RUMBLE_WEAK] = effect.id; + } + + struct input_event play; + memset(&play, 0, sizeof(play)); + play.type = EV_FF; + play.code = effects[0]; + play.value = true; + write(fd, &play, sizeof(play)); + rarch_sleep(500); + play.value = false; + write(fd, &play, sizeof(play)); + rarch_sleep(500); + play.code = effects[1]; + play.value = true; + write(fd, &play, sizeof(play)); + rarch_sleep(500); + play.value = false; + write(fd, &play, sizeof(play)); + } + } + +} +#endif + static int open_joystick(const char *path) { int fd = open(path, O_RDWR | O_NONBLOCK); if (fd < 0) return fd; + unsigned long evbit[NBITS(EV_MAX)] = {0}; unsigned long keybit[NBITS(KEY_MAX)] = {0}; unsigned long absbit[NBITS(ABS_MAX)] = {0}; @@ -233,6 +333,7 @@ static int open_joystick(const char *path) if (!test_bit(EV_KEY, evbit)) goto error; + return fd; error: @@ -272,6 +373,7 @@ static bool add_pad(unsigned i, int fd, const char *path) return false; } + RARCH_LOG("[udev]: Plugged pad: %s on port #%u.\n", pad->ident, i); struct stat st; @@ -333,39 +435,6 @@ static bool add_pad(unsigned i, int fd, const char *path) if (ioctl(fd, EVIOCGEFFECTS, &pad->num_effects) >= 0) RARCH_LOG("[udev]: Pad #%u (%s) supports %d force feedback effects.\n", i, path, pad->num_effects); - - if (pad->num_effects >= 2) - { - struct ff_effect effect; - - // Strong rumble. - memset(&effect, 0, sizeof(effect)); - effect.type = FF_RUMBLE; - effect.id = -1; - effect.u.rumble.strong_magnitude = 0x8000; - effect.u.rumble.weak_magnitude = 0; - pad->support_ff[0] = ioctl(fd, EVIOCSFF, &effect) == 0; - if (pad->support_ff[0]) - { - RARCH_LOG("[udev]: Pad #%u (%s) supports \"strong\" rumble effect (id %d).\n", - i, path, effect.id); - pad->effects[RETRO_RUMBLE_STRONG] = effect.id; // Gets updated by ioctl(). - } - - // Weak rumble. - memset(&effect, 0, sizeof(effect)); - effect.type = FF_RUMBLE; - effect.id = -1; - effect.u.rumble.strong_magnitude = 0; - effect.u.rumble.weak_magnitude = 0xc000; - pad->support_ff[1] = ioctl(fd, EVIOCSFF, &effect) == 0; - if (pad->support_ff[1]) - { - RARCH_LOG("[udev]: Pad #%u (%s) supports \"weak\" rumble effect (id %d).\n", - i, path, effect.id); - pad->effects[RETRO_RUMBLE_WEAK] = effect.id; // Gets updated by ioctl(). - } - } } return true; @@ -407,6 +476,10 @@ static void check_device(const char *path, bool hotplugged) #else (void)hotplugged; #endif + +#if 0 + test_initial_rumble(fd, path); +#endif } else {