diff --git a/input/drivers/switch_input.c b/input/drivers/switch_input.c index 07993f0a17..699bbf6e15 100644 --- a/input/drivers/switch_input.c +++ b/input/drivers/switch_input.c @@ -197,12 +197,14 @@ static void switch_input_grab_mouse(void *data, bool state) static bool switch_input_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength) { - (void)data; - (void)port; - (void)effect; - (void)strength; - - return false; +#ifdef HAVE_LIBNX + switch_input_t *sw = (switch_input_t*) data; + if (!sw) + return false; + return input_joypad_set_rumble(sw->joypad, port, effect, strength); +#else + return false; +#endif } static bool switch_input_keyboard_mapping_is_blocked(void *data) diff --git a/input/drivers_joypad/switch_joypad.c b/input/drivers_joypad/switch_joypad.c index 247a8baa6c..81b971294d 100644 --- a/input/drivers_joypad/switch_joypad.c +++ b/input/drivers_joypad/switch_joypad.c @@ -35,6 +35,13 @@ static uint16_t pad_state[MAX_PADS]; static int16_t analog_state[MAX_PADS][2][2]; extern uint64_t lifecycle_state; +#ifdef HAVE_LIBNX +static u32 vibration_handles[MAX_PADS][2]; +static u32 vibration_handleheld[2]; +static HidVibrationValue vibration_values[MAX_PADS][2]; +static HidVibrationValue vibration_stop; +#endif + static const char *switch_joypad_name(unsigned pad) { return "Switch Controller"; @@ -57,8 +64,21 @@ static bool switch_joypad_init(void *data) #ifdef HAVE_LIBNX unsigned i; hidScanInput(); + + // Switch like stop behavior with muted band channels and frequencies set to default. + vibration_stop.amp_low = 0.0f; + vibration_stop.freq_low = 160.0f; + vibration_stop.amp_high = 0.0f; + vibration_stop.freq_high = 320.0f; + for (i = 0; i < MAX_PADS; i++) + { switch_joypad_autodetect_add(i); + hidInitializeVibrationDevices(vibration_handles[i], 2, i, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + memcpy(&vibration_values[i][0], &vibration_stop, sizeof(HidVibrationValue)); + memcpy(&vibration_values[i][1], &vibration_stop, sizeof(HidVibrationValue)); + } + hidInitializeVibrationDevices(vibration_handleheld, 2, CONTROLLER_HANDHELD, TYPE_HANDHELD | TYPE_JOYCON_PAIR); #else hid_init(); switch_joypad_autodetect_add(0); @@ -146,7 +166,16 @@ static bool switch_joypad_query_pad(unsigned pad) static void switch_joypad_destroy(void) { -#ifndef HAVE_LIBNX +#ifdef HAVE_LIBNX + unsigned i; + for (i = 0; i < MAX_PADS; i++) + { + memcpy(&vibration_values[i][0], &vibration_stop, sizeof(HidVibrationValue)); + memcpy(&vibration_values[i][1], &vibration_stop, sizeof(HidVibrationValue)); + hidSendVibrationValues(vibration_handles[i], vibration_values[i], 2); + } + hidSendVibrationValues(vibration_handleheld, vibration_values[0], 2); +#else hid_finalize(); #endif } @@ -241,6 +270,34 @@ static void switch_joypad_poll(void) } #endif +#ifdef HAVE_LIBNX +bool switch_joypad_set_rumble(unsigned pad, + enum retro_rumble_effect type, uint16_t strength) +{ + u32* handle; + float amp; + + if (pad >= MAX_PADS || !vibration_handles[pad]) + return false; + + amp = (float)strength / 65535.0f; + amp *= 0.5f; // Max strength is too strong + if (type == RETRO_RUMBLE_STRONG) + { + vibration_values[pad][0].amp_low = amp; + vibration_values[pad][1].amp_low = amp; + } + else + { + vibration_values[pad][0].amp_high = amp; + vibration_values[pad][1].amp_high = amp; + } + + handle = (pad == 0 && hidGetHandheldMode()) ? vibration_handleheld : vibration_handles[pad]; + return R_SUCCEEDED(hidSendVibrationValues(handle, vibration_values[pad], 2)); +} +#endif + input_device_driver_t switch_joypad = { switch_joypad_init, switch_joypad_query_pad, @@ -249,7 +306,11 @@ input_device_driver_t switch_joypad = { switch_joypad_get_buttons, switch_joypad_axis, switch_joypad_poll, +#ifdef HAVE_LIBNX + switch_joypad_set_rumble, +#else NULL, /* set_rumble */ +#endif switch_joypad_name, "switch" };