rumble support for xinput and evdev
This commit is contained in:
parent
91e7c45a5c
commit
a39503dd56
|
@ -22,7 +22,7 @@ Plugins:
|
|||
ImageUpdate(data);
|
||||
*/
|
||||
void UpdateInputState(u32 port);
|
||||
void UpdateVibration(u32 port, u32 value);
|
||||
void UpdateVibration(u32 port, float power, float inclination, u32 duration_ms);
|
||||
|
||||
extern u16 kcode[4];
|
||||
extern u32 vks[4];
|
||||
|
@ -46,10 +46,10 @@ struct MapleConfigMap : IMapleConfigMap
|
|||
this->player_num = player_num;
|
||||
}
|
||||
|
||||
void SetVibration(u32 value)
|
||||
void SetVibration(float power, float inclination, u32 duration_ms)
|
||||
{
|
||||
int player_num = this->player_num == -1 ? dev->bus_id : this->player_num;
|
||||
UpdateVibration(player_num, value);
|
||||
UpdateVibration(player_num, power, inclination, duration_ms);
|
||||
}
|
||||
|
||||
void GetInput(PlainJoystickState* pjs)
|
||||
|
|
|
@ -52,7 +52,7 @@ struct PlainJoystickState
|
|||
|
||||
struct IMapleConfigMap
|
||||
{
|
||||
virtual void SetVibration(u32 value) = 0;
|
||||
virtual void SetVibration(float power, float inclination, u32 duration_ms) = 0;
|
||||
virtual void GetInput(PlainJoystickState* pjs)=0;
|
||||
virtual void SetImage(void* img)=0;
|
||||
virtual ~IMapleConfigMap() {}
|
||||
|
|
|
@ -957,7 +957,7 @@ struct maple_microphone: maple_base
|
|||
|
||||
struct maple_sega_purupuru : maple_base
|
||||
{
|
||||
u16 AST, AST_ms;
|
||||
u16 AST = 19, AST_ms = 5000;
|
||||
u32 VIBSET;
|
||||
|
||||
virtual MapleDeviceType get_device_type()
|
||||
|
@ -1053,8 +1053,32 @@ struct maple_sega_purupuru : maple_base
|
|||
case MDCF_SetCondition:
|
||||
|
||||
VIBSET = *(u32*)&dma_buffer_in[4];
|
||||
//Do the rumble thing!
|
||||
config->SetVibration(VIBSET);
|
||||
{
|
||||
//Do the rumble thing!
|
||||
u8 POW_POS = (VIBSET >> 8) & 0x7;
|
||||
u8 POW_NEG = (VIBSET >> 12) & 0x7;
|
||||
u8 FREQ = (VIBSET >> 16) & 0xFF;
|
||||
s16 INC = (VIBSET >> 24) & 0xFF;
|
||||
if (VIBSET & 0x8000) // INH
|
||||
INC = -INC;
|
||||
else if (!(VIBSET & 0x0800)) // EXH
|
||||
INC = 0;
|
||||
bool CNT = VIBSET & 1;
|
||||
|
||||
float power = min((POW_POS + POW_NEG) / 7.0, 1.0);
|
||||
|
||||
u32 duration_ms;
|
||||
if (FREQ > 0 && (!CNT || INC))
|
||||
duration_ms = min((int)(1000 * (INC ? abs(INC) * max(POW_POS, POW_NEG) : 1) / FREQ), (int)AST_ms);
|
||||
else
|
||||
duration_ms = AST_ms;
|
||||
float inclination;
|
||||
if (INC == 0 || power == 0)
|
||||
inclination = 0.0;
|
||||
else
|
||||
inclination = FREQ / (1000.0 * INC * max(POW_POS, POW_NEG));
|
||||
config->SetVibration(power, inclination, duration_ms);
|
||||
}
|
||||
|
||||
return MDRS_DeviceReply;
|
||||
|
||||
|
|
|
@ -207,3 +207,14 @@ void GamepadDevice::save_mapping()
|
|||
return;
|
||||
input_mapper->save(make_mapping_filename().c_str());
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, float power, float inclination, u32 duration_ms)
|
||||
{
|
||||
int i = GamepadDevice::GetGamepadCount() - 1;
|
||||
for ( ; i >= 0; i--)
|
||||
{
|
||||
std::shared_ptr<GamepadDevice> gamepad = GamepadDevice::GetGamepad(i);
|
||||
if (gamepad != NULL && gamepad->maple_port() == port && gamepad->is_rumble_enabled())
|
||||
gamepad->rumble(power, inclination, duration_ms);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ public:
|
|||
void save_mapping();
|
||||
bool remappable() { return _remappable && input_mapper != NULL; }
|
||||
|
||||
virtual void rumble(float power, float inclination, u32 duration_ms) {}
|
||||
virtual void update_rumble() {}
|
||||
bool is_rumble_enabled() { return _rumble_enabled; }
|
||||
|
||||
static void Register(std::shared_ptr<GamepadDevice> gamepad)
|
||||
{
|
||||
_gamepads_mutex.lock();
|
||||
|
@ -101,6 +105,8 @@ private:
|
|||
input_detected_cb _input_detected;
|
||||
bool _remappable;
|
||||
|
||||
bool _rumble_enabled = true;
|
||||
|
||||
static std::vector<std::shared_ptr<GamepadDevice>> _gamepads;
|
||||
static std::mutex _gamepads_mutex;
|
||||
};
|
||||
|
|
|
@ -211,13 +211,5 @@ bool input_evdev_handle(u32 port)
|
|||
return true;
|
||||
}
|
||||
|
||||
void input_evdev_rumble(u32 port, u16 pow_strong, u16 pow_weak)
|
||||
{
|
||||
std::shared_ptr<EvdevGamepadDevice> dev = EvdevGamepadDevice::GetControllerForPort(port);
|
||||
if (dev != NULL)
|
||||
dev->Rumble(pow_strong, pow_weak);
|
||||
}
|
||||
|
||||
|
||||
#endif // USE_EVDEV
|
||||
|
||||
|
|
|
@ -4,4 +4,3 @@
|
|||
extern void input_evdev_init();
|
||||
extern void input_evdev_close();
|
||||
extern bool input_evdev_handle(u32 port);
|
||||
extern void input_evdev_rumble(u32 port, u16 pow_strong, u16 pow_weak);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "../input/gamepad_device.h"
|
||||
#include "oslib/oslib.h"
|
||||
#include "evdev.h"
|
||||
|
||||
class EvdevGamepadDevice : public GamepadDevice
|
||||
|
@ -60,36 +61,22 @@ public:
|
|||
close(_fd);
|
||||
}
|
||||
|
||||
// FIXME add to base class
|
||||
void Rumble(u16 pow_strong, u16 pow_weak)
|
||||
virtual void rumble(float power, float inclination, u32 duration_ms) override
|
||||
{
|
||||
printf("RUMBLE: %u / %u (%d)\n", pow_strong, pow_weak, _rumble_effect_id);
|
||||
struct ff_effect effect;
|
||||
effect.type = FF_RUMBLE;
|
||||
effect.id = _rumble_effect_id;
|
||||
effect.u.rumble.strong_magnitude = pow_strong;
|
||||
effect.u.rumble.weak_magnitude = pow_weak;
|
||||
effect.replay.length = 0;
|
||||
effect.replay.delay = 0;
|
||||
if (ioctl(_fd, EVIOCSFF, &effect) == -1)
|
||||
{
|
||||
perror("evdev: Force feedback error");
|
||||
_rumble_effect_id = -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rumble_effect_id = effect.id;
|
||||
vib_inclination = inclination * power;
|
||||
vib_stop_time = os_GetSeconds() + duration_ms / 1000.0;
|
||||
|
||||
// Let's play the effect
|
||||
input_event play;
|
||||
play.type = EV_FF;
|
||||
play.code = effect.id;
|
||||
play.value = 1;
|
||||
if (write(_fd, (const void*) &play, sizeof(play)) == -1)
|
||||
{
|
||||
perror("evdev: Force feedback error");
|
||||
_rumble_effect_id = -2;
|
||||
}
|
||||
do_rumble(power, duration_ms);
|
||||
}
|
||||
virtual void update_rumble() override
|
||||
{
|
||||
if (vib_inclination > 0)
|
||||
{
|
||||
int rem_time = (vib_stop_time - os_GetSeconds()) * 1000;
|
||||
if (rem_time <= 0)
|
||||
vib_inclination = 0;
|
||||
else
|
||||
do_rumble(vib_inclination * rem_time, rem_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +138,7 @@ protected:
|
|||
private:
|
||||
void read_input()
|
||||
{
|
||||
update_rumble();
|
||||
input_event ie;
|
||||
|
||||
while (read(_fd, &ie, sizeof(ie)) == sizeof(ie))
|
||||
|
@ -168,10 +156,47 @@ private:
|
|||
}
|
||||
|
||||
}
|
||||
void do_rumble(float power, u32 duration_ms)
|
||||
{
|
||||
// Remove previous effect
|
||||
if (_rumble_effect_id != -1)
|
||||
ioctl(_fd, EVIOCRMFF, _rumble_effect_id);
|
||||
|
||||
// Upload new effect
|
||||
struct ff_effect effect;
|
||||
effect.type = FF_RUMBLE;
|
||||
effect.id = -1; // Let the driver assign one
|
||||
effect.direction = 0;
|
||||
effect.replay.length = (u16)duration_ms;
|
||||
effect.replay.delay = 0;
|
||||
effect.u.rumble.strong_magnitude = (s16)(power * 32767);
|
||||
effect.u.rumble.weak_magnitude = (s16)(power * 32767);
|
||||
if (ioctl(_fd, EVIOCSFF, &effect) == -1)
|
||||
{
|
||||
perror("evdev: Force feedback error");
|
||||
_rumble_effect_id = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_rumble_effect_id = effect.id;
|
||||
|
||||
// Let's play the effect
|
||||
input_event play;
|
||||
play.type = EV_FF;
|
||||
play.code = effect.id;
|
||||
play.value = 1;
|
||||
if (write(_fd, (const void*) &play, sizeof(play)) == -1)
|
||||
{
|
||||
perror("evdev: Force feedback error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int _fd;
|
||||
std::string _devnode;
|
||||
int _rumble_effect_id;
|
||||
int _rumble_effect_id = -1;
|
||||
float vib_inclination = 0;
|
||||
double vib_stop_time = 0;
|
||||
static std::map<std::string, std::shared_ptr<EvdevGamepadDevice>> evdev_gamepads;
|
||||
};
|
||||
|
||||
|
|
|
@ -147,27 +147,6 @@ void UpdateInputState(u32 port)
|
|||
#endif
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value)
|
||||
{
|
||||
#if defined(USE_EVDEV)
|
||||
u8 POW_POS = (value >> 8) & 0x3;
|
||||
u8 POW_NEG = (value >> 12) & 0x3;
|
||||
u8 FREQ = (value >> 16) & 0xFF;
|
||||
|
||||
double pow = (POW_POS + POW_NEG) / 7.0;
|
||||
double pow_l = pow * (0x3B - FREQ) / 17.0;
|
||||
double pow_r = pow * (FREQ - 0x07) / 15.0;
|
||||
|
||||
if (pow_l > 1.0) pow_l = 1.0;
|
||||
if (pow_r > 1.0) pow_r = 1.0;
|
||||
|
||||
u16 pow_strong = (u16)(65535 * pow_l);
|
||||
u16 pow_weak = (u16)(65535 * pow_r);
|
||||
|
||||
input_evdev_rumble(port, pow_strong, pow_weak);
|
||||
#endif
|
||||
}
|
||||
|
||||
void os_DoEvents()
|
||||
{
|
||||
#if defined(SUPPORT_X11)
|
||||
|
|
|
@ -263,10 +263,6 @@ void UpdateInputState(u32 port) {
|
|||
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value) {
|
||||
|
||||
}
|
||||
|
||||
void os_CreateWindow() {
|
||||
|
||||
}
|
||||
|
|
|
@ -236,27 +236,6 @@ void UpdateInputState(u32 port)
|
|||
#endif
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value)
|
||||
{
|
||||
u8 POW_POS = (value >> 8) & 0x3;
|
||||
u8 POW_NEG = (value >> 12) & 0x3;
|
||||
u8 FREQ = (value >> 16) & 0xFF;
|
||||
|
||||
XINPUT_VIBRATION vib;
|
||||
|
||||
double pow = (POW_POS + POW_NEG) / 7.0;
|
||||
double pow_l = pow * (0x3B - FREQ) / 17.0;
|
||||
double pow_r = pow * (FREQ - 0x07) / 15.0;
|
||||
|
||||
if (pow_l > 1.0) pow_l = 1.0;
|
||||
if (pow_r > 1.0) pow_r = 1.0;
|
||||
|
||||
vib.wLeftMotorSpeed = (u16)(65535 * pow_l);
|
||||
vib.wRightMotorSpeed = (u16)(65535 * pow_r);
|
||||
|
||||
XInputSetState(port, &vib);
|
||||
}
|
||||
|
||||
// Windows class name to register
|
||||
#define WINDOW_CLASS "nilDC"
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ public:
|
|||
|
||||
void ReadInput()
|
||||
{
|
||||
update_rumble();
|
||||
|
||||
XINPUT_STATE state;
|
||||
|
||||
if (XInputGetState(_xinput_port, &state) == 0)
|
||||
|
@ -99,6 +101,23 @@ public:
|
|||
last_right_thumb_y = 0;
|
||||
}
|
||||
}
|
||||
virtual void rumble(float power, float inclination, u32 duration_ms) override
|
||||
{
|
||||
vib_inclination = inclination * power;
|
||||
vib_stop_time = os_GetSeconds() + duration_ms / 1000.0;
|
||||
|
||||
do_rumble(power);
|
||||
}
|
||||
virtual void update_rumble() override
|
||||
{
|
||||
if (vib_inclination > 0)
|
||||
{
|
||||
int rem_time = (vib_stop_time - os_GetSeconds()) * 1000;
|
||||
if (rem_time <= 0)
|
||||
vib_inclination = 0;
|
||||
do_rumble(vib_inclination * rem_time);
|
||||
}
|
||||
}
|
||||
|
||||
void Open()
|
||||
{
|
||||
|
@ -153,6 +172,16 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
void do_rumble(float power)
|
||||
{
|
||||
|
||||
XINPUT_VIBRATION vib;
|
||||
|
||||
vib.wLeftMotorSpeed = (u16)(65535 * power);
|
||||
vib.wRightMotorSpeed = (u16)(65535 * power);
|
||||
|
||||
XInputSetState(_xinput_port, &vib);
|
||||
}
|
||||
|
||||
const int _xinput_port;
|
||||
u32 last_buttons_state = 0;
|
||||
|
@ -162,6 +191,8 @@ private:
|
|||
s16 last_left_thumb_y = 0;
|
||||
s16 last_right_thumb_x = 0;
|
||||
s16 last_right_thumb_y = 0;
|
||||
double vib_stop_time;
|
||||
float vib_inclination;
|
||||
static std::vector<std::shared_ptr<XInputGamepadDevice>> xinput_gamepads;
|
||||
};
|
||||
|
||||
|
|
|
@ -175,11 +175,6 @@ void UpdateInputState(u32 Port)
|
|||
// @@@ Nothing here yet
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void *libPvr_GetRenderTarget()
|
||||
{
|
||||
return g_window; // the surface to render to
|
||||
|
|
|
@ -113,10 +113,6 @@ void UpdateInputState(u32 port) {
|
|||
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value) {
|
||||
|
||||
}
|
||||
|
||||
void get_mic_data(u8* ) {
|
||||
|
||||
}
|
||||
|
|
|
@ -68,10 +68,6 @@ void UpdateInputState(u32 port) {
|
|||
|
||||
}
|
||||
|
||||
void UpdateVibration(u32 port, u32 value) {
|
||||
|
||||
}
|
||||
|
||||
void os_CreateWindow() {
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue