Changed trigger handling for evdev, added ability to map half-axis to a trigger
This commit is contained in:
parent
b8bd153649
commit
5fc3bd7595
7 changed files with 196 additions and 26 deletions
|
@ -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
105
src/evdev_absmap.cpp
Normal 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
49
src/evdev_absmap.hpp
Normal 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 */
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue