Some work on forcefeedback/rumble
This commit is contained in:
parent
fbf4744a4c
commit
8639d800b5
4 changed files with 100 additions and 4 deletions
2
TODO
2
TODO
|
@ -1,3 +1,5 @@
|
|||
- fix http://userweb.kernel.org/~dtor/eviocgbit-bug.html in evtest
|
||||
- cleanup evtest some more, add more features
|
||||
- make guitar button configurable
|
||||
- --mimic-xpad
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ uInputCfg::uInputCfg()
|
|||
dpad_as_button = false;
|
||||
trigger_as_zaxis = false;
|
||||
dpad_only = false;
|
||||
|
||||
force_feedback = false;
|
||||
|
||||
// Button Mapping
|
||||
btn_map[XBOX_BTN_START] = BTN_START;
|
||||
btn_map[XBOX_BTN_GUIDE] = BTN_MODE;
|
||||
|
@ -86,7 +87,7 @@ uInput::uInput(GamepadType type, uInputCfg config_)
|
|||
|
||||
for (int i = 0; i < uinput_filename_count; ++i)
|
||||
{
|
||||
if ((fd = open(uinput_filename[i], O_WRONLY | O_NDELAY)) >= 0)
|
||||
if ((fd = open(uinput_filename[i], O_RDWR | O_NDELAY)) >= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -137,6 +138,13 @@ uInput::setup_xbox360_gamepad(GamepadType type)
|
|||
ioctl(fd, UI_SET_EVBIT, EV_ABS);
|
||||
ioctl(fd, UI_SET_EVBIT, EV_KEY);
|
||||
|
||||
if (cfg.force_feedback)
|
||||
{
|
||||
ioctl(fd, UI_SET_EVBIT, EV_FF);
|
||||
ioctl(fd, UI_SET_FFBIT, FF_PERIODIC);
|
||||
ioctl(fd, UI_SET_FFBIT, FF_RUMBLE);
|
||||
}
|
||||
|
||||
ioctl(fd, UI_SET_ABSBIT, cfg.axis_map[XBOX_AXIS_X1]);
|
||||
ioctl(fd, UI_SET_ABSBIT, cfg.axis_map[XBOX_AXIS_Y1]);
|
||||
|
||||
|
@ -199,6 +207,9 @@ uInput::setup_xbox360_gamepad(GamepadType type)
|
|||
|
||||
strncpy(uinp.name, "Xbox Gamepad (userspace driver)", UINPUT_MAX_NAME_SIZE);
|
||||
|
||||
if (cfg.force_feedback)
|
||||
uinp.ff_effects_max = 16;
|
||||
|
||||
uinp.id.version = 0;
|
||||
uinp.id.bustype = BUS_USB;
|
||||
uinp.id.vendor = 0x045e; // FIXME: this shouldn't be hardcoded
|
||||
|
@ -545,4 +556,73 @@ uInput::send(Xbox360GuitarMsg& msg)
|
|||
send_axis(cfg.axis_map[XBOX_AXIS_Y1], msg.tilt);
|
||||
}
|
||||
|
||||
void
|
||||
uInput::update()
|
||||
{
|
||||
if (cfg.force_feedback)
|
||||
{
|
||||
struct input_event ev;
|
||||
|
||||
int ret;
|
||||
if ((ret = read(fd, &ev, sizeof(ev))) == sizeof(ev))
|
||||
{
|
||||
std::cout << "type: " << ev.type << " code: " << ev.code << " value: " << ev.value << std::endl;
|
||||
|
||||
switch(ev.type)
|
||||
{
|
||||
case EV_FF:
|
||||
std::cout << "EV_FF: playing effect: effect_id = " << ev.code << " value: " << ev.value << std::endl;
|
||||
break;
|
||||
|
||||
case EV_UINPUT:
|
||||
switch (ev.code)
|
||||
{
|
||||
case UI_FF_UPLOAD:
|
||||
{
|
||||
struct uinput_ff_upload upload;
|
||||
memset(&upload, 0, sizeof(upload));
|
||||
|
||||
// *VERY* important, without this you
|
||||
// break the kernel and have to reboot due
|
||||
// to dead hanging process
|
||||
upload.request_id = ev.value;
|
||||
|
||||
ioctl(fd, UI_BEGIN_FF_UPLOAD, &upload);
|
||||
|
||||
std::cout << "FF_UPLOAD: rumble upload: effect_id = " << upload.effect.id << std::endl;
|
||||
|
||||
upload.retval = 0;
|
||||
|
||||
ioctl(fd, UI_END_FF_UPLOAD, &upload);
|
||||
}
|
||||
break;
|
||||
|
||||
case UI_FF_ERASE:
|
||||
{
|
||||
struct uinput_ff_erase erase;
|
||||
memset(&erase, 0, sizeof(erase));
|
||||
|
||||
// *VERY* important, without this you
|
||||
// break the kernel and have to reboot due
|
||||
// to dead hanging process
|
||||
erase.request_id = ev.value;
|
||||
|
||||
ioctl(fd, UI_BEGIN_FF_ERASE, &erase);
|
||||
|
||||
std::cout << "FF_ERASE: rumble erase: effect_id = " << erase.effect_id << std::endl;
|
||||
erase.retval = 0; // FIXME: is this used?
|
||||
|
||||
ioctl(fd, UI_END_FF_ERASE, &erase);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
std::cout << "--------------------------------" << std::endl;
|
||||
}
|
||||
if (ret < 0)
|
||||
std::cout << "Error: " << strerror(errno) << " " << ret << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
bool dpad_as_button;
|
||||
bool trigger_as_zaxis;
|
||||
bool dpad_only;
|
||||
bool force_feedback;
|
||||
|
||||
int btn_map[XBOX_BTN_MAX];
|
||||
int axis_map[XBOX_AXIS_MAX];
|
||||
|
@ -59,6 +60,8 @@ public:
|
|||
|
||||
void send_button(uint16_t code, int32_t value);
|
||||
void send_axis(uint16_t code, int32_t value);
|
||||
|
||||
void update();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -380,6 +380,7 @@ void print_command_line_help(int argc, char** argv)
|
|||
std::cout << " --square-axis Cause the diagonals to be reported as (1,1) instead of (0.7, 0.7)" << std::endl;
|
||||
std::cout << " --relative-axis MAP Make an axis emulate a joystick throttle (example: y2=64000)" << std::endl;
|
||||
std::cout << " --autofire MAP Cause the given buttons to act as autofire (example: A=250)" << std::endl;
|
||||
std::cout << " --force-feedback Enable force feedback support" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "See README for more documentation and examples." << std::endl;
|
||||
std::cout << "Report bugs to Ingo Ruhnke <grumbel@gmx.de>" << std::endl;
|
||||
|
@ -531,6 +532,10 @@ void parse_command_line(int argc, char** argv, CommandLineOptions& opts)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
else if (strcmp(argv[i], "--force-feedback") == 0)
|
||||
{
|
||||
opts.uinput_config.force_feedback = true;
|
||||
}
|
||||
else if (strcmp(argv[i], "-b") == 0 ||
|
||||
strcmp(argv[i], "--buttonmap") == 0)
|
||||
{
|
||||
|
@ -860,6 +865,8 @@ void print_info(struct usb_device* dev,
|
|||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "ForceFeedback: " << ((opts.uinput_config.force_feedback) ? "enabled" : "disabled") << std::endl;
|
||||
}
|
||||
|
||||
namespace Math {
|
||||
|
@ -980,7 +987,8 @@ void controller_loop(uInput* uinput, XboxGenericController* controller, CommandL
|
|||
relative_axis_modifier.reset(new RelativeAxisModifier(opts.relative_axis_map));
|
||||
|
||||
if (autofire_modifier.get() ||
|
||||
relative_axis_modifier.get())
|
||||
relative_axis_modifier.get() ||
|
||||
opts.uinput_config.force_feedback)
|
||||
timeout = 30;
|
||||
|
||||
memset(&oldmsg, 0, sizeof(oldmsg));
|
||||
|
@ -1050,6 +1058,8 @@ void controller_loop(uInput* uinput, XboxGenericController* controller, CommandL
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
uinput->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1177,8 +1187,9 @@ void run_main(CommandLineOptions& opts)
|
|||
uInput* uinput = 0;
|
||||
if (!opts.no_uinput)
|
||||
{
|
||||
std::cout << "Starting with uinput" << std::endl;
|
||||
std::cout << "Starting with uinput... " << std::flush;
|
||||
uinput = new uInput(opts.gamepad_type, opts.uinput_config);
|
||||
std::cout << "done" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue