Some more work towards allowing the daemon to use multiple controller slots
This commit is contained in:
parent
198f0324b0
commit
71e0cef5c0
13 changed files with 377 additions and 251 deletions
101
TODO
101
TODO
|
@ -1,4 +1,4 @@
|
|||
Pre Release Testing:
|
||||
slPre Release Testing:
|
||||
=====================
|
||||
|
||||
* check the version number
|
||||
|
@ -44,54 +44,10 @@ Stuff to do before 0.7.0 release:
|
|||
|
||||
* AxisSensitivity filter has overflow issue
|
||||
|
||||
* add support for pairing the controller to the PC (or zero)
|
||||
|
||||
--ps3-pair 00:00:00:00:00:00
|
||||
--ps3-pair-with-bluetooth
|
||||
|
||||
* Playstation 3 controller support
|
||||
- http://www.pabr.org/sixlinux/sixlinux.en.html
|
||||
- http://www.motioninjoy.com/
|
||||
|
||||
- figure out what the remaining unknown bits mean:
|
||||
|
||||
data from just pluging the controller in and out a few times
|
||||
without much pause inbetween:
|
||||
|
||||
Dualshock3:
|
||||
// leaving controller plugged in for a longer time settles to this:
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 c0
|
||||
00 00 02 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
^^^^^ ^^^^^
|
||||
00 00 01 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 11 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
00 00 02 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
wrong ideas: bluetooth master id
|
||||
|
||||
00 00 01 ef 16 00 00 00 00 11 fc 77 01 c0
|
||||
00 00 03 ef 16 00 00 00 00 11 fc 77 01 c0
|
||||
|
||||
SIXAXIS:
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77 01 81
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77 01
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77
|
||||
|
||||
// taken from: http://www.pabr.org/sixlinux/sixlinux.en.html
|
||||
00 00 02 ee 10 00 00 00 00 02 b2 77 01 81
|
||||
|
||||
random guesses: bluetooth id, serial number, calibration data,
|
||||
battery status
|
||||
|
||||
* fix the FIXME's
|
||||
|
||||
* fix event output (have it pre-modifier or post-modifier?)
|
||||
|
||||
* fix --no-uinput
|
||||
|
||||
* need to hide/disable the toggle button from the UIButtonmap
|
||||
|
||||
* move XBOX_BTN_UNKNOWN behind XBOX_BTN_MAX, so iteration can start
|
||||
|
@ -101,13 +57,20 @@ Stuff to do before 0.7.0 release:
|
|||
Daemon Related Stuff
|
||||
====================
|
||||
|
||||
* currently device creation fails as all configurations are assigned
|
||||
to the same virtual device
|
||||
|
||||
* improve output on which uinput devices are created
|
||||
|
||||
* fix --no-uinput
|
||||
|
||||
* uinput must be thread safe
|
||||
|
||||
* implement --on-connect and --on-disconnect for the daemon
|
||||
- maybe have a more general event interface that allows to run stuff
|
||||
on configuration changes, controller plug-ins, etc. (notifiy area as example)
|
||||
- also supply useful information as argument
|
||||
|
||||
* uinput must be thread safe
|
||||
|
||||
* handle multiple controllers in a sane manner (requires cloning of
|
||||
modifier maps, also auto increment of "auto" device id's)
|
||||
|
||||
|
@ -155,12 +118,52 @@ List Output
|
|||
1 hal daemon from Thomas Debouverie <debouverie_thomas@yahoo.fr>
|
||||
1 Implemented --ui-buttonmap A=BTN_A@{device_id} ??!?!?
|
||||
|
||||
* improve output on which uinput devices are created
|
||||
|
||||
|
||||
Stuff to do before 0.7.x release:
|
||||
=================================
|
||||
|
||||
* Playstation 3 controller support
|
||||
- http://www.pabr.org/sixlinux/sixlinux.en.html
|
||||
- http://www.motioninjoy.com/
|
||||
|
||||
- figure out what the remaining unknown bits mean:
|
||||
|
||||
data from just pluging the controller in and out a few times
|
||||
without much pause inbetween:
|
||||
|
||||
Dualshock3:
|
||||
// leaving controller plugged in for a longer time settles to this:
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 c0
|
||||
00 00 02 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
^^^^^ ^^^^^
|
||||
00 00 01 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 11 fc 77 01 de
|
||||
00 00 03 ef 16 00 00 00 00 33 fc 77 01 de
|
||||
00 00 02 ee 12 00 00 00 00 12 fc 77 01 de
|
||||
wrong ideas: bluetooth master id
|
||||
|
||||
00 00 01 ef 16 00 00 00 00 11 fc 77 01 c0
|
||||
00 00 03 ef 16 00 00 00 00 11 fc 77 01 c0
|
||||
|
||||
SIXAXIS:
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77 01 81
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77 01
|
||||
00 00 06 ee 10 00 00 00 00 06 83 77
|
||||
|
||||
// taken from: http://www.pabr.org/sixlinux/sixlinux.en.html
|
||||
00 00 02 ee 10 00 00 00 00 02 b2 77 01 81
|
||||
|
||||
random guesses: bluetooth id, serial number, calibration data,
|
||||
battery status
|
||||
|
||||
* add support for pairing the controller to the PC (or zero)
|
||||
|
||||
--ps3-pair 00:00:00:00:00:00
|
||||
--ps3-pair-with-bluetooth
|
||||
|
||||
* allow named sections in INI files:
|
||||
|
||||
[controller1/modifier]
|
||||
|
|
|
@ -18,6 +18,175 @@
|
|||
|
||||
#include "controller_config_set.hpp"
|
||||
|
||||
#include "uinput.hpp"
|
||||
#include "options.hpp"
|
||||
#include "log.hpp"
|
||||
|
||||
#include "modifier/dpad_rotation_modifier.hpp"
|
||||
#include "modifier/four_way_restrictor_modifier.hpp"
|
||||
#include "modifier/square_axis_modifier.hpp"
|
||||
|
||||
ControllerConfigSetPtr
|
||||
ControllerConfigSet::create(uInput& uinput, const Options::ControllerConfigs& opts)
|
||||
{
|
||||
ControllerConfigSetPtr m_config(new ControllerConfigSet);
|
||||
|
||||
for(Options::ControllerConfigs::const_iterator i = opts.begin();
|
||||
i != opts.end(); ++i)
|
||||
{
|
||||
const ControllerOptions& ctrl_opt = i->second;
|
||||
|
||||
ControllerConfigPtr config(new ControllerConfig(uinput, ctrl_opt));
|
||||
create_modifier(ctrl_opt, &config->get_modifier());
|
||||
m_config->add_config(config);
|
||||
|
||||
#ifdef FIXME
|
||||
// introspection of the config
|
||||
std::cout << "==[[ Active Modifier ]]==" << std::endl;
|
||||
for(std::vector<ModifierPtr>::iterator mod = config->get_modifier().begin();
|
||||
mod != config->get_modifier().end();
|
||||
++mod)
|
||||
{
|
||||
std::cout << (*mod)->str() << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
log_info << "UInput finish" << std::endl;
|
||||
|
||||
// After all the ControllerConfig registered their events, finish up
|
||||
// the device creation
|
||||
uinput.finish();
|
||||
|
||||
return m_config;
|
||||
}
|
||||
|
||||
void
|
||||
ControllerConfigSet::create_modifier(const ControllerOptions& opts, std::vector<ModifierPtr>* modifier)
|
||||
{
|
||||
if (!opts.calibration_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.calibration_map.begin();
|
||||
i != opts.calibration_map.end();
|
||||
++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.deadzone)
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
XboxAxis axes[] = { XBOX_AXIS_X1,
|
||||
XBOX_AXIS_Y1,
|
||||
|
||||
XBOX_AXIS_X2,
|
||||
XBOX_AXIS_Y2 };
|
||||
|
||||
for(size_t i = 0; i < sizeof(axes)/sizeof(XboxAxis); ++i)
|
||||
{
|
||||
axismap->add_filter(axes[i],
|
||||
AxisFilterPtr(new DeadzoneAxisFilter(-opts.deadzone,
|
||||
opts.deadzone,
|
||||
true)));
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.deadzone_trigger)
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
XboxAxis axes[] = { XBOX_AXIS_LT,
|
||||
XBOX_AXIS_RT };
|
||||
|
||||
for(size_t i = 0; i < sizeof(axes)/sizeof(XboxAxis); ++i)
|
||||
{
|
||||
axismap->add_filter(axes[i],
|
||||
AxisFilterPtr(new DeadzoneAxisFilter(-opts.deadzone_trigger,
|
||||
opts.deadzone_trigger,
|
||||
true)));
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.square_axis)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new SquareAxisModifier(XBOX_AXIS_X1, XBOX_AXIS_Y1)));
|
||||
modifier->push_back(ModifierPtr(new SquareAxisModifier(XBOX_AXIS_X2, XBOX_AXIS_Y2)));
|
||||
}
|
||||
|
||||
if (!opts.sensitivity_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.sensitivity_map.begin();
|
||||
i != opts.sensitivity_map.end(); ++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.four_way_restrictor)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new FourWayRestrictorModifier(XBOX_AXIS_X1, XBOX_AXIS_Y1)));
|
||||
modifier->push_back(ModifierPtr(new FourWayRestrictorModifier(XBOX_AXIS_X2, XBOX_AXIS_Y2)));
|
||||
}
|
||||
|
||||
if (!opts.relative_axis_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.relative_axis_map.begin();
|
||||
i != opts.relative_axis_map.end(); ++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.dpad_rotation)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new DpadRotationModifier(opts.dpad_rotation)));
|
||||
}
|
||||
|
||||
if (!opts.autofire_map.empty())
|
||||
{
|
||||
boost::shared_ptr<ButtonmapModifier> buttonmap(new ButtonmapModifier);
|
||||
|
||||
for(std::map<XboxButton, ButtonFilterPtr>::const_iterator i = opts.autofire_map.begin();
|
||||
i != opts.autofire_map.end(); ++i)
|
||||
{
|
||||
buttonmap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(buttonmap);
|
||||
}
|
||||
|
||||
// axismap, buttonmap comes last, as otherwise they would mess up the button and axis names
|
||||
if (!opts.buttonmap->empty())
|
||||
{
|
||||
modifier->push_back(opts.buttonmap);
|
||||
}
|
||||
|
||||
if (!opts.axismap->empty())
|
||||
{
|
||||
modifier->push_back(opts.axismap);
|
||||
}
|
||||
|
||||
modifier->insert(modifier->end(), opts.modifier.begin(), opts.modifier.end());
|
||||
}
|
||||
|
||||
ControllerConfigSet::ControllerConfigSet() :
|
||||
m_config(),
|
||||
m_current_config(0)
|
||||
|
|
|
@ -19,10 +19,26 @@
|
|||
#ifndef HEADER_XBOXDRV_CONTROLLER_CONFIG_SET_HPP
|
||||
#define HEADER_XBOXDRV_CONTROLLER_CONFIG_SET_HPP
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include "controller_config.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
class Options;
|
||||
class uInput;
|
||||
class ControllerConfigSet;
|
||||
|
||||
typedef boost::shared_ptr<ControllerConfigSet> ControllerConfigSetPtr;
|
||||
|
||||
class ControllerConfigSet
|
||||
{
|
||||
public:
|
||||
/** Creates a ControllerConfigSet from the Options object and connects it to uInput */
|
||||
static ControllerConfigSetPtr create(uInput& uinput, const Options::ControllerConfigs& opts);
|
||||
|
||||
private:
|
||||
static void create_modifier(const ControllerOptions& options, std::vector<ModifierPtr>* modifier);
|
||||
|
||||
private:
|
||||
std::vector<ControllerConfigPtr> m_config;
|
||||
int m_current_config;
|
||||
|
|
|
@ -22,186 +22,24 @@
|
|||
#include "options.hpp"
|
||||
#include "uinput.hpp"
|
||||
|
||||
#include "modifier/dpad_rotation_modifier.hpp"
|
||||
#include "modifier/four_way_restrictor_modifier.hpp"
|
||||
#include "modifier/square_axis_modifier.hpp"
|
||||
|
||||
DefaultMessageProcessor::DefaultMessageProcessor(uInput& uinput, const Options& opts) :
|
||||
DefaultMessageProcessor::DefaultMessageProcessor(uInput& uinput, ControllerConfigSetPtr config,
|
||||
const Options& opts) :
|
||||
m_uinput(uinput),
|
||||
m_config(),
|
||||
m_config(config),
|
||||
m_oldmsg(),
|
||||
m_config_toggle_button(opts.config_toggle_button)
|
||||
{
|
||||
memset(&m_oldmsg, 0, sizeof(m_oldmsg));
|
||||
|
||||
// create ControllerConfigs
|
||||
for(Options::ControllerSlots::const_iterator controller = opts.controller_slots.begin();
|
||||
controller != opts.controller_slots.end(); ++controller)
|
||||
{
|
||||
for(Options::ControllerConfigs::const_iterator i = controller->second.begin();
|
||||
i != controller->second.end(); ++i)
|
||||
{
|
||||
const ControllerOptions& ctrl_opt = i->second;
|
||||
|
||||
ControllerConfigPtr config(new ControllerConfig(uinput, ctrl_opt));
|
||||
create_modifier(ctrl_opt, &config->get_modifier());
|
||||
m_config.add_config(config);
|
||||
|
||||
#ifdef FIXME
|
||||
// introspection of the config
|
||||
std::cout << "==[[ Active Modifier ]]==" << std::endl;
|
||||
for(std::vector<ModifierPtr>::iterator mod = config->get_modifier().begin();
|
||||
mod != config->get_modifier().end();
|
||||
++mod)
|
||||
{
|
||||
std::cout << (*mod)->str() << std::endl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log_info << "UInput finish" << std::endl;
|
||||
|
||||
// After all the ControllerConfig registered their events, finish up
|
||||
// the device creation
|
||||
uinput.finish();
|
||||
}
|
||||
|
||||
DefaultMessageProcessor::~DefaultMessageProcessor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DefaultMessageProcessor::create_modifier(const ControllerOptions& opts, std::vector<ModifierPtr>* modifier)
|
||||
{
|
||||
if (!opts.calibration_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.calibration_map.begin();
|
||||
i != opts.calibration_map.end();
|
||||
++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.deadzone)
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
XboxAxis axes[] = { XBOX_AXIS_X1,
|
||||
XBOX_AXIS_Y1,
|
||||
|
||||
XBOX_AXIS_X2,
|
||||
XBOX_AXIS_Y2 };
|
||||
|
||||
for(size_t i = 0; i < sizeof(axes)/sizeof(XboxAxis); ++i)
|
||||
{
|
||||
axismap->add_filter(axes[i],
|
||||
AxisFilterPtr(new DeadzoneAxisFilter(-opts.deadzone,
|
||||
opts.deadzone,
|
||||
true)));
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.deadzone_trigger)
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
XboxAxis axes[] = { XBOX_AXIS_LT,
|
||||
XBOX_AXIS_RT };
|
||||
|
||||
for(size_t i = 0; i < sizeof(axes)/sizeof(XboxAxis); ++i)
|
||||
{
|
||||
axismap->add_filter(axes[i],
|
||||
AxisFilterPtr(new DeadzoneAxisFilter(-opts.deadzone_trigger,
|
||||
opts.deadzone_trigger,
|
||||
true)));
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.square_axis)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new SquareAxisModifier(XBOX_AXIS_X1, XBOX_AXIS_Y1)));
|
||||
modifier->push_back(ModifierPtr(new SquareAxisModifier(XBOX_AXIS_X2, XBOX_AXIS_Y2)));
|
||||
}
|
||||
|
||||
if (!opts.sensitivity_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.sensitivity_map.begin();
|
||||
i != opts.sensitivity_map.end(); ++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.four_way_restrictor)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new FourWayRestrictorModifier(XBOX_AXIS_X1, XBOX_AXIS_Y1)));
|
||||
modifier->push_back(ModifierPtr(new FourWayRestrictorModifier(XBOX_AXIS_X2, XBOX_AXIS_Y2)));
|
||||
}
|
||||
|
||||
if (!opts.relative_axis_map.empty())
|
||||
{
|
||||
boost::shared_ptr<AxismapModifier> axismap(new AxismapModifier);
|
||||
|
||||
for(std::map<XboxAxis, AxisFilterPtr>::const_iterator i = opts.relative_axis_map.begin();
|
||||
i != opts.relative_axis_map.end(); ++i)
|
||||
{
|
||||
axismap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(axismap);
|
||||
}
|
||||
|
||||
if (opts.dpad_rotation)
|
||||
{
|
||||
modifier->push_back(ModifierPtr(new DpadRotationModifier(opts.dpad_rotation)));
|
||||
}
|
||||
|
||||
if (!opts.autofire_map.empty())
|
||||
{
|
||||
boost::shared_ptr<ButtonmapModifier> buttonmap(new ButtonmapModifier);
|
||||
|
||||
for(std::map<XboxButton, ButtonFilterPtr>::const_iterator i = opts.autofire_map.begin();
|
||||
i != opts.autofire_map.end(); ++i)
|
||||
{
|
||||
buttonmap->add_filter(i->first, i->second);
|
||||
}
|
||||
|
||||
modifier->push_back(buttonmap);
|
||||
}
|
||||
|
||||
// axismap, buttonmap comes last, as otherwise they would mess up the button and axis names
|
||||
if (!opts.buttonmap->empty())
|
||||
{
|
||||
modifier->push_back(opts.buttonmap);
|
||||
}
|
||||
|
||||
if (!opts.axismap->empty())
|
||||
{
|
||||
modifier->push_back(opts.axismap);
|
||||
}
|
||||
|
||||
modifier->insert(modifier->end(), opts.modifier.begin(), opts.modifier.end());
|
||||
}
|
||||
|
||||
void
|
||||
DefaultMessageProcessor::send(const XboxGenericMsg& msg_in, int msec_delta)
|
||||
{
|
||||
if (!m_config.empty())
|
||||
if (!m_config->empty())
|
||||
{
|
||||
XboxGenericMsg msg = msg_in;
|
||||
|
||||
|
@ -214,24 +52,24 @@ DefaultMessageProcessor::send(const XboxGenericMsg& msg_in, int msec_delta)
|
|||
if (cur && cur != last)
|
||||
{
|
||||
// reset old mapping to zero to not get stuck keys/axis
|
||||
m_config.get_config()->get_uinput().reset_all_outputs();
|
||||
m_config->get_config()->get_uinput().reset_all_outputs();
|
||||
|
||||
// switch to the next input mapping
|
||||
m_config.next_config();
|
||||
m_config->next_config();
|
||||
|
||||
log_info << "Next Config" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// run the controller message through all modifier
|
||||
for(std::vector<ModifierPtr>::iterator i = m_config.get_config()->get_modifier().begin();
|
||||
i != m_config.get_config()->get_modifier().end();
|
||||
for(std::vector<ModifierPtr>::iterator i = m_config->get_config()->get_modifier().begin();
|
||||
i != m_config->get_config()->get_modifier().end();
|
||||
++i)
|
||||
{
|
||||
(*i)->update(msec_delta, msg);
|
||||
}
|
||||
|
||||
m_config.get_config()->get_uinput().update(msec_delta);
|
||||
m_config->get_config()->get_uinput().update(msec_delta);
|
||||
|
||||
// send current Xbox state to uinput
|
||||
if (memcmp(&msg, &m_oldmsg, sizeof(XboxGenericMsg)) != 0)
|
||||
|
@ -242,7 +80,7 @@ DefaultMessageProcessor::send(const XboxGenericMsg& msg_in, int msec_delta)
|
|||
// too
|
||||
m_oldmsg = msg;
|
||||
|
||||
m_config.get_config()->get_uinput().send(msg);
|
||||
m_config->get_config()->get_uinput().send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,20 +32,18 @@ class DefaultMessageProcessor : public MessageProcessor
|
|||
{
|
||||
private:
|
||||
uInput& m_uinput;
|
||||
ControllerConfigSet m_config;
|
||||
ControllerConfigSetPtr m_config;
|
||||
|
||||
XboxGenericMsg m_oldmsg; /// last data send to uinput
|
||||
XboxButton m_config_toggle_button;
|
||||
|
||||
public:
|
||||
DefaultMessageProcessor(uInput& uinput, const Options& opts);
|
||||
DefaultMessageProcessor(uInput& uinput, ControllerConfigSetPtr config,
|
||||
const Options& opts);
|
||||
~DefaultMessageProcessor();
|
||||
|
||||
void send(const XboxGenericMsg& msg, int msec_delta);
|
||||
|
||||
private:
|
||||
void create_modifier(const ControllerOptions& options, std::vector<ModifierPtr>* modifier);
|
||||
|
||||
private:
|
||||
DefaultMessageProcessor(const DefaultMessageProcessor&);
|
||||
DefaultMessageProcessor& operator=(const DefaultMessageProcessor&);
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "evdev_helper.hpp"
|
||||
#include "log.hpp"
|
||||
#include "force_feedback_handler.hpp"
|
||||
|
||||
LinuxUinput::LinuxUinput(DeviceType device_type, const std::string& name_, uint16_t vendor_, uint16_t product_) :
|
||||
|
@ -42,6 +44,8 @@ LinuxUinput::LinuxUinput(DeviceType device_type, const std::string& name_, uint1
|
|||
ff_callback(),
|
||||
needs_sync(true)
|
||||
{
|
||||
log_info << name << " " << vendor << ":" << product << std::endl;
|
||||
|
||||
std::fill_n(abs_lst, ABS_CNT, false);
|
||||
std::fill_n(rel_lst, REL_CNT, false);
|
||||
std::fill_n(key_lst, KEY_CNT, false);
|
||||
|
@ -93,7 +97,7 @@ LinuxUinput::~LinuxUinput()
|
|||
void
|
||||
LinuxUinput::add_abs(uint16_t code, int min, int max, int fuzz, int flat)
|
||||
{
|
||||
// std::cout << "add_abs: " << abs2str(code) << " (" << min << ", " << max << ") " << name << std::endl;
|
||||
log_info << "add_abs: " << abs2str(code) << " (" << min << ", " << max << ") " << name << std::endl;
|
||||
|
||||
if (!abs_lst[code])
|
||||
{
|
||||
|
@ -117,7 +121,7 @@ LinuxUinput::add_abs(uint16_t code, int min, int max, int fuzz, int flat)
|
|||
void
|
||||
LinuxUinput::add_rel(uint16_t code)
|
||||
{
|
||||
// std::cout << "add_rel: " << rel2str(code) << " " << name << std::endl;
|
||||
log_info << "add_rel: " << rel2str(code) << " " << name << std::endl;
|
||||
|
||||
if (!rel_lst[code])
|
||||
{
|
||||
|
@ -136,7 +140,7 @@ LinuxUinput::add_rel(uint16_t code)
|
|||
void
|
||||
LinuxUinput::add_key(uint16_t code)
|
||||
{
|
||||
// std::cout << "add_key: " << btn2str(code) << " " << name << std::endl;
|
||||
log_info << "add_key: " << key2str(code) << " " << name << std::endl;
|
||||
|
||||
if (!key_lst[code])
|
||||
{
|
||||
|
@ -220,14 +224,26 @@ LinuxUinput::finish()
|
|||
user_dev.id.vendor = vendor;
|
||||
user_dev.id.product = product;
|
||||
|
||||
log_info << "'" << user_dev.name << "' " << user_dev.id.vendor << ":" << user_dev.id.product << std::endl;
|
||||
|
||||
if (ff_bit)
|
||||
user_dev.ff_effects_max = ff_handler->get_max_effects();
|
||||
|
||||
//std::cout << "Finalizing uinput: '" << user_dev.name << "'" << std::endl;
|
||||
|
||||
if (write(fd, &user_dev, sizeof(user_dev)) < 0)
|
||||
throw std::runtime_error("uinput:finish: " + name + ": " + strerror(errno));
|
||||
{
|
||||
int write_ret = write(fd, &user_dev, sizeof(user_dev));
|
||||
if (write_ret < 0)
|
||||
{
|
||||
throw std::runtime_error("uinput:finish: " + name + ": " + strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info << "write return value: " << write_ret << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
log_info << "finish" << std::endl;
|
||||
if (ioctl(fd, UI_DEV_CREATE))
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
|
|
@ -92,6 +92,20 @@ Options::get_controller_slot()
|
|||
return controller_slots[controller_slot];
|
||||
}
|
||||
|
||||
const Options::ControllerConfigs&
|
||||
Options::get_controller_slot() const
|
||||
{
|
||||
ControllerSlots::const_iterator it = controller_slots.find(controller_slot);
|
||||
if (it == controller_slots.end())
|
||||
{
|
||||
assert(!"shouldn't happen");
|
||||
}
|
||||
else
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
ControllerOptions&
|
||||
Options::get_controller_options()
|
||||
{
|
||||
|
|
|
@ -146,6 +146,7 @@ public:
|
|||
Options();
|
||||
|
||||
ControllerConfigs& get_controller_slot();
|
||||
const ControllerConfigs& get_controller_slot() const;
|
||||
|
||||
/** Returns the currently active configuration */
|
||||
ControllerOptions& get_controller_options();
|
||||
|
|
|
@ -42,7 +42,7 @@ Xbox360Controller::Xbox360Controller(libusb_device* dev_,
|
|||
m_headset()
|
||||
{
|
||||
find_endpoints();
|
||||
if (true) // FIXME
|
||||
if (false)
|
||||
{
|
||||
std::cout << "EP(IN): " << endpoint_in << std::endl;
|
||||
std::cout << "EP(OUT): " << endpoint_out << std::endl;
|
||||
|
@ -207,7 +207,7 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
|
|||
else if (ret != LIBUSB_SUCCESS)
|
||||
{ // Error
|
||||
std::ostringstream str;
|
||||
str << "Xbox360Controller: USBError: " << ret << "\n" << usb_strerror(ret);
|
||||
str << "Xbox360Controller: libusb_interrupt_transfer(): " << usb_strerror(ret);
|
||||
throw std::runtime_error(str.str());
|
||||
}
|
||||
else if (len == 0)
|
||||
|
|
|
@ -463,7 +463,8 @@ Xboxdrv::run_main(const Options& opts)
|
|||
|
||||
global_exit_xboxdrv = false;
|
||||
|
||||
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, opts));
|
||||
ControllerConfigSetPtr config_set = ControllerConfigSet::create(*uinput, opts.get_controller_slot());
|
||||
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, config_set, opts));
|
||||
XboxdrvThread loop(message_proc, controller, opts);
|
||||
loop.controller_loop(opts);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ extern bool global_exit_xboxdrv;
|
|||
XboxdrvDaemon::XboxdrvDaemon() :
|
||||
m_udev(0),
|
||||
m_monitor(0),
|
||||
m_threads()
|
||||
m_controller_slots()
|
||||
{
|
||||
m_udev = udev_new();
|
||||
|
||||
|
@ -49,9 +49,10 @@ XboxdrvDaemon::XboxdrvDaemon() :
|
|||
|
||||
XboxdrvDaemon::~XboxdrvDaemon()
|
||||
{
|
||||
for(Threads::iterator i = m_threads.begin(); i != m_threads.end(); ++i)
|
||||
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||
{
|
||||
delete *i;
|
||||
delete i->thread;
|
||||
i->thread = 0;
|
||||
}
|
||||
|
||||
udev_monitor_unref(m_monitor);
|
||||
|
@ -61,13 +62,20 @@ XboxdrvDaemon::~XboxdrvDaemon()
|
|||
void
|
||||
XboxdrvDaemon::cleanup_threads()
|
||||
{
|
||||
size_t num_threads = m_threads.size();
|
||||
m_threads.erase(std::remove_if(m_threads.begin(), m_threads.end(),
|
||||
boost::bind(&XboxdrvThread::try_join_thread, _1)),
|
||||
m_threads.end());
|
||||
if (num_threads != m_threads.size())
|
||||
int count = 0;
|
||||
|
||||
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||
{
|
||||
log_info << "cleaned up " << (num_threads - m_threads.size()) << " thread(s)" << std::endl;
|
||||
if (i->thread)
|
||||
{
|
||||
i->thread->try_join_thread();
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
log_info << "cleaned up " << count << " thread(s)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,6 +181,20 @@ XboxdrvDaemon::run(const Options& opts)
|
|||
std::cout << "Starting without uinput" << std::endl;
|
||||
}
|
||||
|
||||
{ // create controller slots
|
||||
int slot_count = 0;
|
||||
|
||||
for(Options::ControllerSlots::const_iterator controller = opts.controller_slots.begin();
|
||||
controller != opts.controller_slots.end(); ++controller)
|
||||
{
|
||||
log_info << "creating slot: " << slot_count << std::endl;
|
||||
m_controller_slots.push_back(ControllerSlot(ControllerConfigSet::create(*uinput, controller->second)));
|
||||
slot_count += 1;
|
||||
}
|
||||
|
||||
log_info << "created " << m_controller_slots.size() << " controller slots" << std::endl;
|
||||
}
|
||||
|
||||
// Setup udev monitor and enumerate
|
||||
m_monitor = udev_monitor_new_from_netlink(m_udev, "udev");
|
||||
udev_monitor_filter_add_match_subsystem_devtype(m_monitor, "usb", "usb_device");
|
||||
|
@ -312,7 +334,8 @@ XboxdrvDaemon::print_info(struct udev_device* device)
|
|||
}
|
||||
|
||||
void
|
||||
XboxdrvDaemon::launch_xboxdrv(uInput* uinput, const XPadDevice& dev_type, const Options& opts, uint8_t busnum, uint8_t devnum)
|
||||
XboxdrvDaemon::launch_xboxdrv(uInput* uinput, const XPadDevice& dev_type, const Options& opts,
|
||||
uint8_t busnum, uint8_t devnum)
|
||||
{
|
||||
std::cout << "[XboxdrvDaemon] launching " << boost::format("%03d:%03d")
|
||||
% static_cast<int>(busnum)
|
||||
|
@ -328,11 +351,20 @@ XboxdrvDaemon::launch_xboxdrv(uInput* uinput, const XPadDevice& dev_type, const
|
|||
}
|
||||
else
|
||||
{
|
||||
std::auto_ptr<XboxGenericController> controller = XboxControllerFactory::create(dev_type, dev, opts);
|
||||
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, opts));
|
||||
std::auto_ptr<XboxdrvThread> thread(new XboxdrvThread(message_proc, controller, opts));
|
||||
thread->start_thread(opts);
|
||||
m_threads.push_back(thread.release());
|
||||
for(ControllerSlots::iterator i = m_controller_slots.begin(); i != m_controller_slots.end(); ++i)
|
||||
{
|
||||
if (i->thread == 0)
|
||||
{
|
||||
log_info << "found a free slot: " << (i - m_controller_slots.begin()) << std::endl;
|
||||
|
||||
std::auto_ptr<XboxGenericController> controller = XboxControllerFactory::create(dev_type, dev, opts);
|
||||
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, i->config, opts));
|
||||
std::auto_ptr<XboxdrvThread> thread(new XboxdrvThread(message_proc, controller, opts));
|
||||
thread->start_thread(opts);
|
||||
i->thread = thread.release();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "controller_config_set.hpp"
|
||||
|
||||
class Options;
|
||||
class uInput;
|
||||
struct XPadDevice;
|
||||
|
@ -33,8 +35,41 @@ class XboxdrvDaemon
|
|||
private:
|
||||
struct udev* m_udev;
|
||||
struct udev_monitor* m_monitor;
|
||||
typedef std::vector<XboxdrvThread*> Threads;
|
||||
Threads m_threads;
|
||||
|
||||
struct ControllerSlot
|
||||
{
|
||||
ControllerConfigSetPtr config;
|
||||
XboxdrvThread* thread;
|
||||
|
||||
ControllerSlot() :
|
||||
config(),
|
||||
thread(0)
|
||||
{}
|
||||
|
||||
ControllerSlot(ControllerConfigSetPtr config_,
|
||||
XboxdrvThread* thread_ = 0) :
|
||||
config(config_),
|
||||
thread(thread_)
|
||||
{}
|
||||
|
||||
ControllerSlot(const ControllerSlot& rhs) :
|
||||
config(rhs.config),
|
||||
thread(rhs.thread)
|
||||
{}
|
||||
|
||||
ControllerSlot& operator=(const ControllerSlot& rhs)
|
||||
{
|
||||
if (&rhs != this)
|
||||
{
|
||||
config = rhs.config;
|
||||
thread = rhs.thread;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<ControllerSlot> ControllerSlots;
|
||||
ControllerSlots m_controller_slots;
|
||||
|
||||
public:
|
||||
XboxdrvDaemon();
|
||||
|
|
|
@ -30,6 +30,9 @@ class Options;
|
|||
class XboxGenericController;
|
||||
class MessageProcessor;
|
||||
|
||||
/** XboxdrvThread handles a single XboxGenericController controller
|
||||
(optionally in a separate thread), reads it messages and passes it
|
||||
to the MessageProcessor */
|
||||
class XboxdrvThread // FIXME: find a better name, XboxdrvControllerLoop?!
|
||||
{
|
||||
private:
|
||||
|
|
Loading…
Add table
Reference in a new issue