Wired rumble callback through the new class hierachy

This commit is contained in:
Ingo Ruhnke 2011-01-26 15:34:09 +01:00
parent 941ff16f3e
commit 42b3d4f6f0
17 changed files with 188 additions and 125 deletions

View file

@ -16,19 +16,22 @@
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "controller_config_set.hpp"
#include "controller_slot_config.hpp"
#include <boost/bind.hpp>
#include "log.hpp"
#include "controller_options.hpp"
#include "log.hpp"
#include "uinput.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, int slot, bool extra_devices, const ControllerSlotOptions& opts)
ControllerSlotConfigPtr
ControllerSlotConfig::create(UInput& uinput, int slot, bool extra_devices, const ControllerSlotOptions& opts)
{
ControllerConfigSetPtr m_config(new ControllerConfigSet);
ControllerSlotConfigPtr m_config(new ControllerSlotConfig);
for(ControllerSlotOptions::Options::const_iterator i = opts.get_options().begin();
i != opts.get_options().end(); ++i)
@ -51,11 +54,57 @@ ControllerConfigSet::create(UInput& uinput, int slot, bool extra_devices, const
#endif
}
// LED
//ioctl(fd, UI_SET_EVBIT, EV_LED);
//ioctl(fd, UI_SET_LEDBIT, LED_MISC);
if (opts.get_force_feedback())
{
// FF_GAIN - relative strength of rumble
// FF_RUMBLE - basic rumble (delay, time)
// FF_CONSTANT - envelope, emulate with rumble
// FF_RAMP - same as constant, except strength grows
// FF_PERIODIC - envelope
// |- FF_SINE types of periodic effects
// |- FF_TRIANGLE
// |- FF_SQUARE
// |- FF_SAW_UP
// |- FF_SAW_DOWN
// '- FF_CUSTOM
int ff_device = opts.get_ff_device();
// basic types
uinput.add_ff(ff_device, FF_RUMBLE);
uinput.add_ff(ff_device, FF_PERIODIC);
uinput.add_ff(ff_device, FF_CONSTANT);
uinput.add_ff(ff_device, FF_RAMP);
// periodic effect subtypes
uinput.add_ff(ff_device, FF_SINE);
uinput.add_ff(ff_device, FF_TRIANGLE);
uinput.add_ff(ff_device, FF_SQUARE);
uinput.add_ff(ff_device, FF_SAW_UP);
uinput.add_ff(ff_device, FF_SAW_DOWN);
uinput.add_ff(ff_device, FF_CUSTOM);
// gin support
uinput.add_ff(ff_device, FF_GAIN);
// Unsupported effects
// uinput.add_ff(ff_device, FF_SPRING);
// uinput.add_ff(ff_device, FF_FRICTION);
// uinput.add_ff(ff_device, FF_DAMPER);
// uinput.add_ff(ff_device, FF_INERTIA);
uinput.set_ff_callback(ff_device, boost::bind(&ControllerSlotConfig::set_rumble, m_config.get(), _1, _2));
}
return m_config;
}
void
ControllerConfigSet::create_modifier(const ControllerOptions& opts, std::vector<ModifierPtr>* modifier)
ControllerSlotConfig::create_modifier(const ControllerOptions& opts, std::vector<ModifierPtr>* modifier)
{
if (!opts.calibration_map.empty())
{
@ -180,14 +229,15 @@ ControllerConfigSet::create_modifier(const ControllerOptions& opts, std::vector<
modifier->insert(modifier->end(), opts.modifier.begin(), opts.modifier.end());
}
ControllerConfigSet::ControllerConfigSet() :
ControllerSlotConfig::ControllerSlotConfig() :
m_config(),
m_current_config(0)
m_current_config(0),
m_rumble_callback()
{
}
void
ControllerConfigSet::next_config()
ControllerSlotConfig::next_config()
{
m_current_config += 1;
@ -198,7 +248,7 @@ ControllerConfigSet::next_config()
}
void
ControllerConfigSet::prev_config()
ControllerSlotConfig::prev_config()
{
m_current_config -= 1;
@ -209,13 +259,13 @@ ControllerConfigSet::prev_config()
}
int
ControllerConfigSet::config_count() const
ControllerSlotConfig::config_count() const
{
return static_cast<int>(m_config.size());
}
ControllerConfigPtr
ControllerConfigSet::get_config(int i) const
ControllerSlotConfig::get_config(int i) const
{
assert(i >= 0);
assert(i < static_cast<int>(m_config.size()));
@ -224,7 +274,7 @@ ControllerConfigSet::get_config(int i) const
}
ControllerConfigPtr
ControllerConfigSet::get_config() const
ControllerSlotConfig::get_config() const
{
assert(!m_config.empty());
@ -232,9 +282,24 @@ ControllerConfigSet::get_config() const
}
void
ControllerConfigSet::add_config(ControllerConfigPtr config)
ControllerSlotConfig::add_config(ControllerConfigPtr config)
{
m_config.push_back(config);
}
void
ControllerSlotConfig::set_rumble(uint8_t strong, uint8_t weak)
{
if (m_rumble_callback)
{
m_rumble_callback(strong, weak);
}
}
void
ControllerSlotConfig::set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback)
{
m_rumble_callback = callback;
}
/* EOF */

View file

@ -19,20 +19,22 @@
#ifndef HEADER_XBOXDRV_CONTROLLER_CONFIG_SET_HPP
#define HEADER_XBOXDRV_CONTROLLER_CONFIG_SET_HPP
#include <boost/function.hpp>
#include "controller_config.hpp"
#include "options.hpp"
class Options;
class UInput;
class ControllerConfigSet;
class ControllerSlotConfig;
typedef boost::shared_ptr<ControllerConfigSet> ControllerConfigSetPtr;
typedef boost::shared_ptr<ControllerSlotConfig> ControllerSlotConfigPtr;
class ControllerConfigSet
class ControllerSlotConfig
{
public:
/** Creates a ControllerConfigSet from the Options object and connects it to UInput */
static ControllerConfigSetPtr create(UInput& uinput, int slot, bool extra_devices,
/** Creates a ControllerSlotConfig from the Options object and connects it to UInput */
static ControllerSlotConfigPtr create(UInput& uinput, int slot, bool extra_devices,
const ControllerSlotOptions& opts);
private:
@ -41,9 +43,10 @@ private:
private:
std::vector<ControllerConfigPtr> m_config;
int m_current_config;
boost::function<void (uint8_t, uint8_t)> m_rumble_callback;
public:
ControllerConfigSet();
ControllerSlotConfig();
void add_config(ControllerConfigPtr config);
@ -55,9 +58,12 @@ public:
bool empty() const { return m_config.empty(); }
void set_rumble(uint8_t strong, uint8_t weak);
void set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback);
private:
ControllerConfigSet(const ControllerConfigSet&);
ControllerConfigSet& operator=(const ControllerConfigSet&);
ControllerSlotConfig(const ControllerSlotConfig&);
ControllerSlotConfig& operator=(const ControllerSlotConfig&);
};
#endif

View file

@ -24,7 +24,8 @@
ControllerSlotOptions::ControllerSlotOptions() :
m_options(),
m_match_rules()
m_match_rules(),
m_force_feedback(false)
{
}

View file

@ -41,9 +41,15 @@ public:
const std::vector<ControllerMatchRule>& get_match_rules() const;
const std::map<int, ControllerOptions>& get_options() const;
void set_force_feedback(bool value) { m_force_feedback = value; }
bool get_force_feedback() const { return m_force_feedback; }
int get_ff_device() const { return 0; }
private:
std::map<int, ControllerOptions> m_options;
std::vector<ControllerMatchRule> m_match_rules;
bool m_force_feedback;
};
#endif

View file

@ -21,12 +21,15 @@
#include "log.hpp"
#include "uinput.hpp"
DefaultMessageProcessor::DefaultMessageProcessor(UInput& uinput, ControllerConfigSetPtr config,
DefaultMessageProcessor::DefaultMessageProcessor(UInput& uinput,
ControllerSlotConfigPtr config,
const Options& opts) :
m_uinput(uinput),
m_config(config),
m_oldmsg(),
m_config_toggle_button(opts.config_toggle_button)
m_config_toggle_button(opts.config_toggle_button),
m_rumble_gain(opts.rumble_gain),
m_rumble_callback()
{
memset(&m_oldmsg, 0, sizeof(m_oldmsg));
}
@ -86,4 +89,22 @@ DefaultMessageProcessor::send(const XboxGenericMsg& msg_in, int msec_delta)
}
}
void
DefaultMessageProcessor::set_rumble(uint8_t lhs, uint8_t rhs)
{
if (m_rumble_callback)
{
lhs = std::min(lhs * m_rumble_gain / 255, 255);
rhs = std::min(rhs * m_rumble_gain / 255, 255);
m_rumble_callback(lhs, rhs);
}
}
void
DefaultMessageProcessor::set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback)
{
m_config->set_ff_callback(callback);
}
/* EOF */

View file

@ -19,7 +19,7 @@
#ifndef HEADER_XBOXDRV_DEFAULT_MESSAGE_PROCESSOR_HPP
#define HEADER_XBOXDRV_DEFAULT_MESSAGE_PROCESSOR_HPP
#include "controller_config_set.hpp"
#include "controller_slot_config.hpp"
#include "message_processor.hpp"
class UInput;
@ -30,17 +30,22 @@ class DefaultMessageProcessor : public MessageProcessor
{
private:
UInput& m_uinput;
ControllerConfigSetPtr m_config;
ControllerSlotConfigPtr m_config;
XboxGenericMsg m_oldmsg; /// last data send to uinput
XboxButton m_config_toggle_button;
int m_rumble_gain;
boost::function<void (uint8_t, uint8_t)> m_rumble_callback;
public:
DefaultMessageProcessor(UInput& uinput, ControllerConfigSetPtr config,
DefaultMessageProcessor(UInput& uinput, ControllerSlotConfigPtr config,
const Options& opts);
~DefaultMessageProcessor();
void send(const XboxGenericMsg& msg, int msec_delta);
void set_rumble(uint8_t lhs, uint8_t rhs);
void set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback);
private:
DefaultMessageProcessor(const DefaultMessageProcessor&);

View file

@ -31,4 +31,9 @@ DummyMessageProcessor::send(const XboxGenericMsg& msg, int msec_delta)
log_info << msg << std::endl;
}
void
DummyMessageProcessor::set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback)
{
}
/* EOF */

View file

@ -26,7 +26,9 @@ class DummyMessageProcessor : public MessageProcessor
private:
public:
DummyMessageProcessor();
void send(const XboxGenericMsg& msg, int msec_delta);
void set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback);
private:
DummyMessageProcessor(const DummyMessageProcessor&);

View file

@ -19,6 +19,8 @@
#ifndef HEADER_XBOXDRV_MESSAGE_PROCESSOR_HPP
#define HEADER_XBOXDRV_MESSAGE_PROCESSOR_HPP
#include <boost/function.hpp>
struct XboxGenericMsg;
class MessageProcessor
@ -28,6 +30,7 @@ public:
virtual ~MessageProcessor() {}
virtual void send(const XboxGenericMsg& msg, int msec_delta) =0;
virtual void set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback) =0;
private:
MessageProcessor(const MessageProcessor&);

View file

@ -25,54 +25,6 @@ UInput::UInput() :
rel_repeat_lst(),
m_mutex()
{
#ifdef FIXME
if (cfg.force_feedback)
{
create_uinput_device(DEVICEID_JOYSTICK);
}
// LED
//ioctl(fd, UI_SET_EVBIT, EV_LED);
//ioctl(fd, UI_SET_LEDBIT, LED_MISC);
if (cfg.force_feedback)
{
//
get_force_feedback_uinput()->add_ff(FF_RUMBLE);
get_force_feedback_uinput()->add_ff(FF_PERIODIC);
get_force_feedback_uinput()->add_ff(FF_CONSTANT);
get_force_feedback_uinput()->add_ff(FF_RAMP);
// Periodic effect subtypes
get_force_feedback_uinput()->add_ff(FF_SINE);
get_force_feedback_uinput()->add_ff(FF_TRIANGLE);
get_force_feedback_uinput()->add_ff(FF_SQUARE);
get_force_feedback_uinput()->add_ff(FF_SAW_UP);
get_force_feedback_uinput()->add_ff(FF_SAW_DOWN);
get_force_feedback_uinput()->add_ff(FF_CUSTOM);
// Gain support
get_force_feedback_uinput()->add_ff(FF_GAIN);
// Unsupported effects
// get_force_feedback_uinput()->add_ff(FF_SPRING);
// get_force_feedback_uinput()->add_ff(FF_FRICTION);
// get_force_feedback_uinput()->add_ff(FF_DAMPER);
// get_force_feedback_uinput()->add_ff(FF_INERTIA);
// FF_GAIN - relative strength of rumble
// FF_RUMBLE - basic rumble (delay, time)
// FF_CONSTANT - envelope, emulate with rumble
// FF_RAMP - same as constant, except strength grows
// FF_PERIODIC - envelope
// |- FF_SINE types of periodic effects
// |- FF_TRIANGLE
// |- FF_SQUARE
// |- FF_SAW_UP
// |- FF_SAW_DOWN
// '- FF_CUSTOM
}
#endif
}
LinuxUinput*
@ -150,6 +102,13 @@ UInput::add_abs(uint32_t device_id, int ev_code, int min, int max, int fuzz, int
dev->add_abs(ev_code, min, max, fuzz, flat);
}
void
UInput::add_ff(uint32_t device_id, uint16_t code)
{
LinuxUinput* dev = create_uinput_device(device_id);
dev->add_ff(code);
}
void
UInput::finish()
{
@ -255,16 +214,10 @@ UInput::get_uinput(uint32_t device_id) const
}
}
LinuxUinput*
UInput::get_force_feedback_uinput() const
{
return get_uinput(0);
}
void
UInput::set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback)
UInput::set_ff_callback(int device_id, const boost::function<void (uint8_t, uint8_t)>& callback)
{
get_force_feedback_uinput()->set_ff_callback(callback);
get_uinput(device_id)->set_ff_callback(callback);
}
/* EOF */

View file

@ -61,13 +61,14 @@ public:
void update(int msec_delta);
void set_ff_callback(const boost::function<void (uint8_t, uint8_t)>& callback);
void set_ff_callback(int device_id, const boost::function<void (uint8_t, uint8_t)>& callback);
/** Device construction functions
@{*/
void add_rel(uint32_t device_id, int ev_code);
void add_abs(uint32_t device_id, int ev_code, int min, int max, int fuzz, int flat);
void add_key(uint32_t device_id, int ev_code);
void add_ff(uint32_t device_id, uint16_t code);
/** needs to be called to finish device creation and create the
device in the kernel */
@ -86,8 +87,6 @@ public:
void sync();
/** @} */
LinuxUinput* get_force_feedback_uinput() const;
boost::mutex& get_mutex() { return m_mutex; }
private:

View file

@ -233,10 +233,28 @@ Xbox360Controller::read(XboxGenericMsg& msg, bool verbose, int timeout)
}
else if (len == 3 && data[0] == 0x08 && data[1] == 0x03)
{
// FIXME: maybe a proper indicator for the actvity on the chatpad
// port, so that we don't have to send chatpad init
if (data[2] == 0x00)
log_info << "headset: none" << std::endl;
{
log_info << "peripheral: none" << std::endl;
}
else if (data[2] == 0x01)
{
log_info << "peripheral: chatpad" << std::endl;
}
else if (data[2] == 0x02)
log_info << "headset: none" << std::endl;
{
log_info << "peripheral: headset" << std::endl;
}
else if (data[2] == 0x03)
{
log_info << "peripheral: headset, chatpad" << std::endl;
}
else
{
log_info << "peripheral: unknown: " << int(data[2]) << std::endl;
}
}
else if (len == 20 && data[0] == 0x00 && data[1] == 0x14)
{

View file

@ -336,19 +336,6 @@ Xboxdrv::find_controller(libusb_device** dev,
}
}
// FIXME: duplicate code
namespace {
void set_rumble(XboxGenericController* controller, int gain, uint8_t lhs, uint8_t rhs)
{
lhs = std::min(lhs * gain / 255, 255);
rhs = std::min(rhs * gain / 255, 255);
//std::cout << (int)lhs << " " << (int)rhs << std::endl;
controller->set_rumble(lhs, rhs);
}
} // namespace
void
Xboxdrv::print_copyright() const
{
@ -444,10 +431,6 @@ Xboxdrv::run_main(const Options& opts)
if (!opts.quiet)
std::cout << "Starting with uinput" << std::endl;
uinput = std::auto_ptr<UInput>(new UInput());
if (opts.get_controller_options().uinput.force_feedback) // FIXME: wrong
{
uinput->set_ff_callback(boost::bind(&set_rumble, controller.get(), opts.rumble_gain, _1, _2));
}
}
else
{
@ -473,15 +456,16 @@ Xboxdrv::run_main(const Options& opts)
global_exit_xboxdrv = false;
ControllerConfigSetPtr config_set = ControllerConfigSet::create(*uinput,
0, opts.extra_devices,
opts.get_controller_slot());
ControllerSlotConfigPtr config_set = ControllerSlotConfig::create(*uinput,
0, opts.extra_devices,
opts.get_controller_slot());
// After all the ControllerConfig registered their events, finish up
// the device creation
uinput->finish();
std::auto_ptr<MessageProcessor> message_proc(new DefaultMessageProcessor(*uinput, config_set, opts));
XboxdrvThread loop(message_proc, controller, opts);
loop.controller_loop(opts);

View file

@ -138,7 +138,7 @@ XboxdrvDaemon::cleanup_threads()
void
XboxdrvDaemon::process_match(const Options& opts, struct udev_device* device)
{
if (false)
if (true)
{
print_info(device);
}
@ -206,14 +206,6 @@ XboxdrvDaemon::init_uinput(const Options& opts)
m_uinput.reset(new UInput());
// FIXME:
/* must setup this callback later when we have a controller
if (opts.uinput_config.force_feedback)
{
uinput->set_ff_callback(boost::bind(&set_rumble, controller.get(), opts.rumble_gain, _1, _2));
}
*/
// create controller slots
int slot_count = 0;
@ -222,9 +214,9 @@ XboxdrvDaemon::init_uinput(const Options& opts)
{
log_info << "creating slot: " << slot_count << std::endl;
m_controller_slots.push_back(ControllerSlot(m_controller_slots.size(),
ControllerConfigSet::create(*m_uinput, slot_count,
opts.extra_devices,
controller->second),
ControllerSlotConfig::create(*m_uinput, slot_count,
opts.extra_devices,
controller->second),
controller->second.get_match_rules()));
slot_count += 1;
}

View file

@ -23,7 +23,7 @@
#include <stdint.h>
#include <vector>
#include "controller_config_set.hpp"
#include "controller_slot_config.hpp"
#include "controller_match_rule.hpp"
class Options;
@ -40,7 +40,7 @@ private:
struct ControllerSlot
{
int id;
ControllerConfigSetPtr config;
ControllerSlotConfigPtr config;
std::vector<ControllerMatchRule> rules;
XboxdrvThread* thread;
@ -52,7 +52,7 @@ private:
{}
ControllerSlot(int id_,
ControllerConfigSetPtr config_,
ControllerSlotConfigPtr config_,
std::vector<ControllerMatchRule> rules_,
XboxdrvThread* thread_ = 0) :
id(id_),

View file

@ -43,6 +43,9 @@ XboxdrvThread::XboxdrvThread(std::auto_ptr<MessageProcessor> processor,
m_timeout(opts.timeout)
{
memset(&m_oldrealmsg, 0, sizeof(m_oldrealmsg));
// connect the processor to the controller to allow rumble
m_processor->set_ff_callback(boost::bind(&XboxGenericController::set_rumble, m_controller.get(), _1, _2));
}
XboxdrvThread::~XboxdrvThread()

View file

@ -24,7 +24,7 @@
#include "xboxmsg.hpp"
#include "modifier.hpp"
#include "controller_config_set.hpp"
#include "controller_slot_config.hpp"
class Options;
class XboxGenericController;