Init user_dev in src/linux_uinput.?pp properly, only create extra devices when needed
This commit is contained in:
parent
2d1c6d1d32
commit
895f56373d
7 changed files with 240 additions and 72 deletions
|
@ -605,6 +605,21 @@ bool str2event(const std::string& name, int& type, int& code)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string btn2str(int i)
|
||||
{
|
||||
return evdev_btn_names[i];
|
||||
}
|
||||
|
||||
std::string abs2str(int i)
|
||||
{
|
||||
return evdev_abs_names[i];
|
||||
}
|
||||
|
||||
std::string rel2str(int i)
|
||||
{
|
||||
return evdev_rel_names[i];
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include <string>
|
||||
|
||||
bool str2event(const std::string& name, int& type, int& code);
|
||||
std::string btn2str(int i);
|
||||
std::string abs2str(int i);
|
||||
std::string rel2str(int i);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
@ -25,10 +26,13 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "evdev_helper.hpp"
|
||||
#include "linux_uinput.hpp"
|
||||
|
||||
LinuxUinput::LinuxUinput()
|
||||
: key_bit(false),
|
||||
LinuxUinput::LinuxUinput(const std::string& name)
|
||||
: name(name),
|
||||
fd(-1),
|
||||
key_bit(false),
|
||||
rel_bit(false),
|
||||
abs_bit(false),
|
||||
led_bit(false),
|
||||
|
@ -38,6 +42,8 @@ LinuxUinput::LinuxUinput()
|
|||
std::fill_n(rel_lst, REL_CNT, false);
|
||||
std::fill_n(key_lst, KEY_CNT, false);
|
||||
|
||||
memset(&user_dev, 0, sizeof(uinput_user_dev));
|
||||
|
||||
// Open the input device
|
||||
const char* uinput_filename[] = { "/dev/input/uinput", "/dev/uinput", "/dev/misc/uinput" };
|
||||
const int uinput_filename_count = (sizeof(uinput_filename)/sizeof(char*));
|
||||
|
@ -77,6 +83,8 @@ LinuxUinput::~LinuxUinput()
|
|||
void
|
||||
LinuxUinput::add_abs(uint16_t code, int min, int max)
|
||||
{
|
||||
// std::cout << "add_abs: " << abs2str(code) << " (" << min << ", " << max << ") " << name << std::endl;
|
||||
|
||||
if (!abs_lst[code])
|
||||
{
|
||||
abs_lst[code] = true;
|
||||
|
@ -97,6 +105,8 @@ LinuxUinput::add_abs(uint16_t code, int min, int max)
|
|||
void
|
||||
LinuxUinput::add_rel(uint16_t code)
|
||||
{
|
||||
// std::cout << "add_rel: " << rel2str(code) << " " << name << std::endl;
|
||||
|
||||
if (!rel_lst[code])
|
||||
{
|
||||
rel_lst[code] = true;
|
||||
|
@ -114,6 +124,8 @@ LinuxUinput::add_rel(uint16_t code)
|
|||
void
|
||||
LinuxUinput::add_key(uint16_t code)
|
||||
{
|
||||
// std::cout << "add_key: " << btn2str(code) << " " << name << std::endl;
|
||||
|
||||
if (!key_lst[code])
|
||||
{
|
||||
key_lst[code] = true;
|
||||
|
@ -129,21 +141,24 @@ LinuxUinput::add_key(uint16_t code)
|
|||
}
|
||||
|
||||
void
|
||||
LinuxUinput::finish(const char* name)
|
||||
LinuxUinput::finish()
|
||||
{
|
||||
std::cout << "Finalizing UInput" << std::endl;
|
||||
strncpy(user_dev.name, name, UINPUT_MAX_NAME_SIZE);
|
||||
strncpy(user_dev.name, name.c_str(), UINPUT_MAX_NAME_SIZE);
|
||||
user_dev.id.version = 0;
|
||||
user_dev.id.bustype = BUS_USB;
|
||||
user_dev.id.vendor = 0x045e; // FIXME: this shouldn't be hardcoded
|
||||
user_dev.id.product = 0x028e;
|
||||
|
||||
//std::cout << "Finalizing uinput: '" << user_dev.name << "'" << std::endl;
|
||||
|
||||
if (write(fd, &user_dev, sizeof(user_dev)) < 0)
|
||||
throw std::runtime_error(std::string("uinput:finish: ") + strerror(errno));
|
||||
throw std::runtime_error("uinput:finish: " + name + strerror(errno));
|
||||
|
||||
if (ioctl(fd, UI_DEV_CREATE))
|
||||
{
|
||||
std::cout << "Unable to create UINPUT device." << std::endl;
|
||||
std::ostringstream out;
|
||||
out << "LinuxUinput: Unable to create UINPUT device: '" << name << "': " << strerror(errno);
|
||||
throw std::runtime_error(out.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#define HEADER_LINUX_UINPUT_HPP
|
||||
|
||||
#include <linux/uinput.h>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
/** */
|
||||
class LinuxUinput
|
||||
{
|
||||
private:
|
||||
std::string name;
|
||||
int fd;
|
||||
uinput_user_dev user_dev;
|
||||
bool key_bit;
|
||||
|
@ -39,7 +41,7 @@ private:
|
|||
bool key_lst[KEY_CNT];
|
||||
|
||||
public:
|
||||
LinuxUinput();
|
||||
LinuxUinput(const std::string& name);
|
||||
~LinuxUinput();
|
||||
|
||||
/*@{*/
|
||||
|
@ -53,7 +55,7 @@ public:
|
|||
void add_rel(uint16_t code);
|
||||
|
||||
/** Finish*/
|
||||
void finish(const char* name);
|
||||
void finish();
|
||||
/*@}*/
|
||||
|
||||
void send(uint16_t type, uint16_t code, int32_t value);
|
||||
|
|
240
src/uinput.cpp
240
src/uinput.cpp
|
@ -54,6 +54,9 @@ ButtonEvent::create(int type, int code)
|
|||
case EV_KEY:
|
||||
break;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"This should never be reached");
|
||||
}
|
||||
|
@ -122,6 +125,9 @@ AxisEvent::create(int type, int code)
|
|||
ev.key.secondary_code = code;
|
||||
ev.key.threshold = 8000;
|
||||
break;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(!"This should never be reached");
|
||||
|
@ -196,6 +202,10 @@ uInputCfg::uInputCfg()
|
|||
trigger_as_zaxis = false;
|
||||
dpad_only = false;
|
||||
force_feedback = false;
|
||||
extra_devices = true;
|
||||
|
||||
std::fill_n(btn_map, (int)XBOX_BTN_MAX, ButtonEvent::create(-1, -1));
|
||||
std::fill_n(axis_map, (int)XBOX_AXIS_MAX, AxisEvent::create(-1, -1));
|
||||
|
||||
// Button Mapping
|
||||
btn_map[XBOX_BTN_START] = ButtonEvent::create(EV_KEY, BTN_START);
|
||||
|
@ -242,33 +252,120 @@ uInputCfg::uInputCfg()
|
|||
axis_map[XBOX_AXIS_DPAD_Y] = AxisEvent::create(EV_ABS, ABS_HAT0Y);
|
||||
}
|
||||
|
||||
bool
|
||||
uInput::need_keyboard_device()
|
||||
{
|
||||
for(int i = 0; i < XBOX_BTN_MAX; ++i)
|
||||
{
|
||||
if (cfg.btn_map[i].type == EV_KEY &&
|
||||
is_keyboard_button(cfg.btn_map[i].code))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < XBOX_AXIS_MAX; ++i)
|
||||
{
|
||||
if (cfg.axis_map[i].type == EV_KEY &&
|
||||
(is_keyboard_button(cfg.axis_map[i].code) ||
|
||||
is_keyboard_button(cfg.axis_map[i].key.secondary_code)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
uInput::need_mouse_device()
|
||||
{
|
||||
for(int i = 0; i < XBOX_BTN_MAX; ++i)
|
||||
{
|
||||
if (cfg.btn_map[i].type == EV_KEY &&
|
||||
is_mouse_button(cfg.btn_map[i].code))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (cfg.btn_map[i].type == EV_REL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < XBOX_AXIS_MAX; ++i)
|
||||
{
|
||||
if (cfg.axis_map[i].type == EV_KEY &&
|
||||
(is_mouse_button(cfg.axis_map[i].code) ||
|
||||
is_mouse_button(cfg.axis_map[i].key.secondary_code)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (cfg.axis_map[i].type == EV_REL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
uInput::is_mouse_button(int ev_code)
|
||||
{
|
||||
return (ev_code >= BTN_MOUSE && ev_code <= BTN_TASK);
|
||||
}
|
||||
|
||||
bool
|
||||
uInput::is_keyboard_button(int ev_code)
|
||||
{
|
||||
return (ev_code < 256);
|
||||
}
|
||||
|
||||
uInput::uInput(GamepadType type, uInputCfg config_)
|
||||
:cfg(config_)
|
||||
: cfg(config_)
|
||||
{
|
||||
std::fill_n(axis_state, (int)XBOX_AXIS_MAX, 0);
|
||||
std::fill_n(button_state, (int)XBOX_BTN_MAX, false);
|
||||
|
||||
joystick_uinput = std::auto_ptr<LinuxUinput>(new LinuxUinput());
|
||||
keyboard_uinput = std::auto_ptr<LinuxUinput>(new LinuxUinput());
|
||||
mouse_uinput = std::auto_ptr<LinuxUinput>(new LinuxUinput());
|
||||
joystick_uinput_dev = std::auto_ptr<LinuxUinput>(new LinuxUinput("Xbox Gamepad (userspace driver)"));
|
||||
joystick_uinput_dev->add_key(BTN_X);
|
||||
joystick_uinput_dev->add_abs(ABS_X, -1, 1);
|
||||
joystick_uinput_dev->add_abs(ABS_Y, -1, 1);
|
||||
joystick_uinput_dev->finish();
|
||||
|
||||
if (type == GAMEPAD_XBOX360 || type == GAMEPAD_XBOX || type == GAMEPAD_XBOX360_WIRELESS)
|
||||
if (0)
|
||||
{
|
||||
setup_xbox360_gamepad(type);
|
||||
}
|
||||
else if (type == GAMEPAD_XBOX360_GUITAR)
|
||||
{
|
||||
setup_xbox360_guitar();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unhandled type: " << type << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
joystick_uinput->finish("Xbox Gamepad (userspace driver)");
|
||||
keyboard_uinput->finish("Xbox Gamepad - Keyboard Emulation (userspace driver)");
|
||||
mouse_uinput->finish("Xbox Gamepad - Mouse Emulation (userspace driver)");
|
||||
if (cfg.extra_devices)// && need_mouse_device())
|
||||
{
|
||||
mouse_uinput_dev = std::auto_ptr<LinuxUinput>(new LinuxUinput("Xbox Gamepad - Mouse Emulation (userspace driver)"));
|
||||
}
|
||||
|
||||
if (cfg.extra_devices)// && need_keyboard_device())
|
||||
{
|
||||
keyboard_uinput_dev = std::auto_ptr<LinuxUinput>(new LinuxUinput("Xbox Gamepad - Keyboard Emulation (userspace driver)"));
|
||||
}
|
||||
|
||||
if (type == GAMEPAD_XBOX360 || type == GAMEPAD_XBOX || type == GAMEPAD_XBOX360_WIRELESS)
|
||||
{
|
||||
setup_xbox360_gamepad(type);
|
||||
}
|
||||
else if (type == GAMEPAD_XBOX360_GUITAR)
|
||||
{
|
||||
setup_xbox360_guitar();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Unhandled type: " << type << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
joystick_uinput_dev->finish();
|
||||
|
||||
if (keyboard_uinput_dev.get()) keyboard_uinput_dev->finish();
|
||||
if (mouse_uinput_dev.get()) mouse_uinput_dev->finish();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -350,11 +447,6 @@ uInput::setup_xbox360_gamepad(GamepadType type)
|
|||
add_button(XBOX_BTN_THUMB_L);
|
||||
add_button(XBOX_BTN_THUMB_R);
|
||||
|
||||
struct uinput_user_dev uinp;
|
||||
memset(&uinp,0,sizeof(uinp));
|
||||
|
||||
strncpy(uinp.name, "Xbox Gamepad (userspace driver)", UINPUT_MAX_NAME_SIZE);
|
||||
|
||||
// if (cfg.force_feedback)
|
||||
// uinp.ff_effects_max = 64;
|
||||
}
|
||||
|
@ -693,7 +785,7 @@ uInput::update(float delta)
|
|||
|
||||
if (i->time >= i->next_time)
|
||||
{
|
||||
mouse_uinput->send(EV_REL, cfg.axis_map[i->axis].code,
|
||||
get_mouse_uinput()->send(EV_REL, cfg.axis_map[i->axis].code,
|
||||
static_cast<int>(cfg.axis_map[i->axis].rel.value * axis_state[i->axis]) / 32767);
|
||||
i->next_time += cfg.axis_map[i->axis].rel.repeat;
|
||||
}
|
||||
|
@ -712,7 +804,7 @@ uInput::update(float delta)
|
|||
<< " " << cfg.btn_map[i->button].rel.value
|
||||
<< " " << cfg.btn_map[i->button].rel.repeat << std::endl;
|
||||
|
||||
mouse_uinput->send(EV_REL, cfg.btn_map[i->button].code,
|
||||
get_mouse_uinput()->send(EV_REL, cfg.btn_map[i->button].code,
|
||||
static_cast<int>(cfg.btn_map[i->button].rel.value * button_state[i->button]));
|
||||
i->next_time += cfg.btn_map[i->button].rel.repeat;
|
||||
}
|
||||
|
@ -829,23 +921,23 @@ uInput::send_button(int code, bool value)
|
|||
void
|
||||
uInput::add_key(int ev_code)
|
||||
{
|
||||
if (ev_code < 256)
|
||||
keyboard_uinput->add_key(ev_code);
|
||||
else if (ev_code >= BTN_MOUSE && ev_code <= BTN_TASK)
|
||||
mouse_uinput->add_key(ev_code);
|
||||
if (is_keyboard_button(ev_code))
|
||||
get_keyboard_uinput()->add_key(ev_code);
|
||||
else if (is_mouse_button(ev_code))
|
||||
get_mouse_uinput()->add_key(ev_code);
|
||||
else
|
||||
joystick_uinput->add_key(ev_code);
|
||||
get_joystick_uinput()->add_key(ev_code);
|
||||
}
|
||||
|
||||
void
|
||||
uInput::send_key(int ev_code, bool value)
|
||||
{
|
||||
if (ev_code < 256)
|
||||
keyboard_uinput->send(EV_KEY, ev_code, value);
|
||||
else if (ev_code >= BTN_MOUSE && ev_code <= BTN_TASK)
|
||||
mouse_uinput->send(EV_KEY, ev_code, value);
|
||||
if (is_keyboard_button(ev_code))
|
||||
get_keyboard_uinput()->send(EV_KEY, ev_code, value);
|
||||
else if (is_mouse_button(ev_code))
|
||||
get_mouse_uinput()->send(EV_KEY, ev_code, value);
|
||||
else
|
||||
joystick_uinput->send(EV_KEY, ev_code, value);
|
||||
get_joystick_uinput()->send(EV_KEY, ev_code, value);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -862,7 +954,7 @@ uInput::send_axis(int code, int32_t value)
|
|||
{
|
||||
case EV_ABS:
|
||||
if (event.type == EV_ABS || event.type == EV_KEY)
|
||||
joystick_uinput->send(event.type, event.code, value);
|
||||
get_joystick_uinput()->send(event.type, event.code, value);
|
||||
break;
|
||||
|
||||
case EV_REL:
|
||||
|
@ -901,28 +993,33 @@ uInput::add_axis(int code, int min, int max)
|
|||
{
|
||||
const AxisEvent& event = cfg.axis_map[code];
|
||||
|
||||
if (event.type == EV_ABS)
|
||||
switch(event.type)
|
||||
{
|
||||
joystick_uinput->add_abs(event.code, min, max);
|
||||
}
|
||||
else if (event.type == EV_REL)
|
||||
{
|
||||
mouse_uinput->add_rel(event.code);
|
||||
RelAxisState rel_axis_state;
|
||||
rel_axis_state.axis = code;
|
||||
rel_axis_state.time = 0;
|
||||
rel_axis_state.next_time = 0;
|
||||
rel_axis.push_back(rel_axis_state);
|
||||
}
|
||||
else if (event.type == EV_KEY)
|
||||
{
|
||||
add_key(event.code);
|
||||
if (event.code != event.key.secondary_code)
|
||||
add_key(event.key.secondary_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "uInput: Unhandled event type: " << event.type << std::endl;
|
||||
case EV_ABS:
|
||||
get_joystick_uinput()->add_abs(event.code, min, max);
|
||||
break;
|
||||
|
||||
case EV_REL:
|
||||
{
|
||||
get_mouse_uinput()->add_rel(event.code);
|
||||
|
||||
RelAxisState rel_axis_state;
|
||||
rel_axis_state.axis = code;
|
||||
rel_axis_state.time = 0;
|
||||
rel_axis_state.next_time = 0;
|
||||
rel_axis.push_back(rel_axis_state);
|
||||
}
|
||||
break;
|
||||
|
||||
case EV_KEY:
|
||||
add_key(event.code);
|
||||
if (event.code != event.key.secondary_code)
|
||||
add_key(event.key.secondary_code);
|
||||
break;
|
||||
|
||||
default:
|
||||
std::cout << "uInput: Unhandled event type: " << event.type << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,7 +1034,8 @@ uInput::add_button(int code)
|
|||
}
|
||||
else if (event.type == EV_REL)
|
||||
{
|
||||
mouse_uinput->add_rel(event.code);
|
||||
get_mouse_uinput()->add_rel(event.code);
|
||||
|
||||
RelButtonState rel_button_state;
|
||||
rel_button_state.button = code;
|
||||
rel_button_state.time = 0;
|
||||
|
@ -949,4 +1047,28 @@ uInput::add_button(int code)
|
|||
}
|
||||
}
|
||||
|
||||
LinuxUinput*
|
||||
uInput::get_mouse_uinput() const
|
||||
{
|
||||
if (mouse_uinput_dev.get())
|
||||
return mouse_uinput_dev.get();
|
||||
else
|
||||
return joystick_uinput_dev.get();
|
||||
}
|
||||
|
||||
LinuxUinput*
|
||||
uInput::get_keyboard_uinput() const
|
||||
{
|
||||
if (keyboard_uinput_dev.get())
|
||||
return keyboard_uinput_dev.get();
|
||||
else
|
||||
return joystick_uinput_dev.get();
|
||||
}
|
||||
|
||||
LinuxUinput*
|
||||
uInput::get_joystick_uinput() const
|
||||
{
|
||||
return joystick_uinput_dev.get();
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -93,6 +93,7 @@ public:
|
|||
bool trigger_as_zaxis;
|
||||
bool dpad_only;
|
||||
bool force_feedback;
|
||||
bool extra_devices;
|
||||
|
||||
ButtonEvent btn_map[XBOX_BTN_MAX];
|
||||
AxisEvent axis_map[XBOX_AXIS_MAX];
|
||||
|
@ -103,9 +104,9 @@ public:
|
|||
class uInput
|
||||
{
|
||||
private:
|
||||
std::auto_ptr<LinuxUinput> joystick_uinput;
|
||||
std::auto_ptr<LinuxUinput> keyboard_uinput;
|
||||
std::auto_ptr<LinuxUinput> mouse_uinput;
|
||||
std::auto_ptr<LinuxUinput> joystick_uinput_dev;
|
||||
std::auto_ptr<LinuxUinput> keyboard_uinput_dev;
|
||||
std::auto_ptr<LinuxUinput> mouse_uinput_dev;
|
||||
uInputCfg cfg;
|
||||
|
||||
int axis_state[XBOX_AXIS_MAX];
|
||||
|
@ -149,6 +150,16 @@ public:
|
|||
void send_axis(int code, int32_t value);
|
||||
|
||||
void update(float delta);
|
||||
|
||||
LinuxUinput* get_mouse_uinput() const;
|
||||
LinuxUinput* get_keyboard_uinput() const;
|
||||
LinuxUinput* get_joystick_uinput() const;
|
||||
|
||||
bool need_mouse_device();
|
||||
bool need_keyboard_device();
|
||||
|
||||
bool is_mouse_button(int ev_code);
|
||||
bool is_keyboard_button(int ev_code);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -156,7 +156,7 @@ void set_ui_button_map(ButtonEvent* ui_button_map, const std::string& str)
|
|||
}
|
||||
else
|
||||
{
|
||||
std::cout << string2btn(str.substr(0, i)) << " -> " << str.substr(i+1, str.size()-i) << std::endl;
|
||||
//std::cout << string2btn(str.substr(0, i)) << " -> " << str.substr(i+1, str.size()-i) << std::endl;
|
||||
|
||||
XboxButton btn = string2btn(str.substr(0, i));
|
||||
ButtonEvent event = ButtonEvent::from_string(str.substr(i+1, str.size()-i));
|
||||
|
|
Loading…
Reference in a new issue