Changed trigger handling for evdev, added ability to map half-axis to a trigger

This commit is contained in:
Ingo Ruhnke 2010-12-09 11:13:47 +01:00
parent b8bd153649
commit 5fc3bd7595
7 changed files with 196 additions and 26 deletions

View file

@ -279,11 +279,26 @@ CommandLineParser::set_ui_axismap_from_string(const std::string& str)
}
}
void set_evdev_absmap(std::map<int, XboxAxis>& absmap, const std::string& str)
void set_evdev_absmap(EvdevAbsMap& absmap, const std::string& str)
{
std::string lhs, rhs;
split_string_at(str, '=', &lhs, &rhs);
absmap[str2abs(lhs)] = string2axis(rhs);
if (!lhs.empty())
{
XboxAxis axis = string2axis(rhs);
switch (*lhs.rbegin())
{
case '-': absmap.bind_minus( str2abs(lhs.substr(0, lhs.length()-1)), axis ); break;
case '+': absmap.bind_plus ( str2abs(lhs.substr(0, lhs.length()-1)), axis ); break;
default: absmap.bind_both ( str2abs(lhs), axis ); break;
}
}
else
{
throw std::runtime_error("incorrect --evdev-absmap argument '" + str + "'");
}
}
void set_evdev_keymap(std::map<int, XboxButton>& keymap, const std::string& str)
@ -802,7 +817,7 @@ CommandLineParser::set_buttonmap(const std::string& name, const std::string& val
void
CommandLineParser::set_evdev_absmap(const std::string& name, const std::string& value)
{
m_options->evdev_absmap[str2abs(name)] = string2axis(value);
//FIXME:m_options->evdev_absmap[str2abs(name)] = string2axis(value);
}
void

105
src/evdev_absmap.cpp Normal file
View file

@ -0,0 +1,105 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "evdev_absmap.hpp"
#include "helper.hpp"
namespace {
inline float abs_to_float(int value, int min, int max)
{
float ret =
static_cast<float>(value - min) /
static_cast<float>(max - min) * 2.0f - 1.0f;
return Math::clamp(-1.0f, ret, 1.0f);
}
} // namespace
EvdevAbsMap::EvdevAbsMap() :
m_plus_map(),
m_minus_map(),
m_both_map()
{
}
void
EvdevAbsMap::bind_plus(int code, XboxAxis axis)
{
m_plus_map[code] = axis;
}
void
EvdevAbsMap::bind_minus(int code, XboxAxis axis)
{
m_minus_map[code] = axis;
}
void
EvdevAbsMap::bind_both(int code, XboxAxis axis)
{
m_both_map[code] = axis;
}
void
EvdevAbsMap::clear()
{
m_plus_map.clear();
m_minus_map.clear();
m_both_map.clear();
}
void
EvdevAbsMap::process(XboxGenericMsg& msg, int code, int value, int min, int max) const
{
{ // process plus map
std::map<int, XboxAxis>::const_iterator it = m_plus_map.find(code);
if (it != m_plus_map.end())
{
// '+ 1' so that we round up, instead of round down
const int center = (max - min + 1) / 2;
const float v = abs_to_float(value, center, min);
set_axis_float(msg, it->second, v);
}
}
{ // process minus map
std::map<int, XboxAxis>::const_iterator it = m_minus_map.find(code);
if (it != m_minus_map.end())
{
// '+ 1' so that we round up, instead of round down
const int center = (max - min + 1) / 2;
const float v = abs_to_float(value, center, max);
set_axis_float(msg, it->second, v);
}
}
{ // process minus map
std::map<int, XboxAxis>::const_iterator it = m_both_map.find(code);
if (it != m_both_map.end())
{
// '+ 1' so that we round up, instead of round down
const float v = abs_to_float(value, min, max);
set_axis_float(msg, it->second, v);
}
}
}
/* EOF */

49
src/evdev_absmap.hpp Normal file
View file

@ -0,0 +1,49 @@
/*
** Xbox360 USB Gamepad Userspace Driver
** Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HEADER_XBOXDRV_EVDEV_ABSMAP_HPP
#define HEADER_XBOXDRV_EVDEV_ABSMAP_HPP
#include <map>
#include "xboxmsg.hpp"
class XboxGenericMsg;
class EvdevAbsMap
{
public:
EvdevAbsMap();
void process(XboxGenericMsg& msg, int code, int value, int min, int max) const;
void bind_plus(int code, XboxAxis axis);
void bind_minus(int code, XboxAxis axis);
void bind_both(int code, XboxAxis axis);
void clear();
private:
std::map<int, XboxAxis> m_plus_map;
std::map<int, XboxAxis> m_minus_map;
std::map<int, XboxAxis> m_both_map;
};
#endif
/* EOF */

View file

@ -37,7 +37,7 @@
#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
EvdevController::EvdevController(const std::string& filename,
const std::map<int, XboxAxis>& absmap,
const EvdevAbsMap& absmap,
const std::map<int, XboxButton>& keymap) :
m_fd(-1),
m_name(),
@ -141,7 +141,6 @@ bool
EvdevController::apply(XboxGenericMsg& msg, const struct input_event& ev)
{
//std::cout << ev.type << " " << ev.code << " " << ev.value << std::endl;
switch(ev.type)
{
case EV_KEY:
@ -161,20 +160,11 @@ EvdevController::apply(XboxGenericMsg& msg, const struct input_event& ev)
case EV_ABS:
{
AbsMap::iterator it = m_absmap.find(ev.code);
if (it != m_absmap.end())
{
const struct input_absinfo& absinfo = m_absinfo[ev.code];
set_axis_float(msg, it->second,
static_cast<float>(ev.value - absinfo.minimum) / static_cast<float>(absinfo.maximum - absinfo.minimum) * 2.0f - 1.0f);
return true;
}
else
{
return false;
}
const struct input_absinfo& absinfo = m_absinfo[ev.code];
m_absmap.process(msg, ev.code, ev.value, absinfo.minimum, absinfo.maximum);
return true; // FIXME: wrong
break;
}
break;
default:
// not supported event

View file

@ -25,16 +25,18 @@
#include <queue>
#include "xboxmsg.hpp"
#include "evdev_absmap.hpp"
#include "xbox_generic_controller.hpp"
class EvdevAbsMap;
class EvdevController : public XboxGenericController
{
private:
int m_fd;
std::string m_name;
typedef std::map<int, XboxAxis> AbsMap;
AbsMap m_absmap;
EvdevAbsMap m_absmap;
typedef std::map<int, XboxButton> KeyMap;
KeyMap m_keymap;
@ -47,8 +49,8 @@ private:
public:
EvdevController(const std::string& filename,
const std::map<int, XboxAxis>& AbsMap,
const std::map<int, XboxButton>& KeyMap);
const EvdevAbsMap& absmap,
const std::map<int, XboxButton>& keyMap);
void set_rumble(uint8_t left, uint8_t right);
void set_led(uint8_t status);

View file

@ -26,6 +26,7 @@
#include "xpad_device.hpp"
#include "uinput_cfg.hpp"
#include "modifier.hpp"
#include "evdev_absmap.hpp"
class Options
{
@ -76,7 +77,7 @@ public:
bool four_way_restrictor;
int dpad_rotation;
std::string evdev_device;
std::map<int, XboxAxis> evdev_absmap;
EvdevAbsMap evdev_absmap;
std::map<int, XboxButton> evdev_keymap;
Options();

View file

@ -558,9 +558,13 @@ float s16_to_float(int16_t value)
}
}
/**
input: [0, 255]
output: [ -1.0f, 1.0f ]
*/
float u8_to_float(uint8_t value)
{
return static_cast<float>(value) / 255.0f;
return static_cast<float>(value) / 255.0f * 2.0f - 1.0f;
}
int16_t float_to_s16(float v)
@ -575,9 +579,13 @@ int16_t float_to_s16(float v)
}
}
/**
input: [ -1.0f, 1.0f ]
output: [0, 255]
*/
uint8_t float_to_u8(float v)
{
return static_cast<uint8_t>(Math::clamp(0.0f, v, 1.0f) * 255.0f);
return static_cast<uint8_t>(Math::clamp(0.0f, (v + 1.0f) / 2.0f, 1.0f) * 255.0f);
}
float get_axis_float(XboxGenericMsg& msg, XboxAxis axis)
@ -912,7 +920,7 @@ XboxAxis string2axis(const std::string& str_)
else if (str == "dpad_y")
return XBOX_AXIS_DPAD_Y;
else if (str == "trigger")
else if (str == "trigger" || str == "z" || str == "rudder")
return XBOX_AXIS_TRIGGER;
else