diff --git a/src/controller_config_set.cpp b/src/controller_slot_config.cpp similarity index 70% rename from src/controller_config_set.cpp rename to src/controller_slot_config.cpp index b53122c..04318ce 100644 --- a/src/controller_config_set.cpp +++ b/src/controller_slot_config.cpp @@ -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 */ diff --git a/src/controller_config_set.hpp b/src/controller_slot_config.hpp similarity index 69% rename from src/controller_config_set.hpp rename to src/controller_slot_config.hpp index f813292..3f9d635 100644 --- a/src/controller_config_set.hpp +++ b/src/controller_slot_config.hpp @@ -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 diff --git a/src/controller_slot_options.cpp b/src/controller_slot_options.cpp index fff419c..fd2a53e 100644 --- a/src/controller_slot_options.cpp +++ b/src/controller_slot_options.cpp @@ -24,7 +24,8 @@ ControllerSlotOptions::ControllerSlotOptions() : m_options(), - m_match_rules() + m_match_rules(), + m_force_feedback(false) { } diff --git a/src/controller_slot_options.hpp b/src/controller_slot_options.hpp index 1e848f6..e193909 100644 --- a/src/controller_slot_options.hpp +++ b/src/controller_slot_options.hpp @@ -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 diff --git a/src/default_message_processor.cpp b/src/default_message_processor.cpp index cb6ee85..d4314c4 100644 --- a/src/default_message_processor.cpp +++ b/src/default_message_processor.cpp @@ -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 */ diff --git a/src/default_message_processor.hpp b/src/default_message_processor.hpp index 2e9aecd..28f269c 100644 --- a/src/default_message_processor.hpp +++ b/src/default_message_processor.hpp @@ -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&); diff --git a/src/dummy_message_processor.cpp b/src/dummy_message_processor.cpp index c613aef..91ff2ca 100644 --- a/src/dummy_message_processor.cpp +++ b/src/dummy_message_processor.cpp @@ -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 */ diff --git a/src/dummy_message_processor.hpp b/src/dummy_message_processor.hpp index b5ca8a5..85d27ad 100644 --- a/src/dummy_message_processor.hpp +++ b/src/dummy_message_processor.hpp @@ -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&); diff --git a/src/message_processor.hpp b/src/message_processor.hpp index e362f97..001ed44 100644 --- a/src/message_processor.hpp +++ b/src/message_processor.hpp @@ -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&); diff --git a/src/uinput.cpp b/src/uinput.cpp index 837cf8a..4fb4898 100644 --- a/src/uinput.cpp +++ b/src/uinput.cpp @@ -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 */ diff --git a/src/uinput.hpp b/src/uinput.hpp index 3b3796c..437ce49 100644 --- a/src/uinput.hpp +++ b/src/uinput.hpp @@ -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: diff --git a/src/xbox360_controller.cpp b/src/xbox360_controller.cpp index 9ff068a..0691176 100644 --- a/src/xbox360_controller.cpp +++ b/src/xbox360_controller.cpp @@ -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) { diff --git a/src/xboxdrv.cpp b/src/xboxdrv.cpp index caee43c..a69ca00 100644 --- a/src/xboxdrv.cpp +++ b/src/xboxdrv.cpp @@ -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); diff --git a/src/xboxdrv_daemon.cpp b/src/xboxdrv_daemon.cpp index 5497f83..9e307c0 100644 --- a/src/xboxdrv_daemon.cpp +++ b/src/xboxdrv_daemon.cpp @@ -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; } diff --git a/src/xboxdrv_daemon.hpp b/src/xboxdrv_daemon.hpp index bf4fdd5..74adeb3 100644 --- a/src/xboxdrv_daemon.hpp +++ b/src/xboxdrv_daemon.hpp @@ -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_), diff --git a/src/xboxdrv_thread.cpp b/src/xboxdrv_thread.cpp index ba4c89c..1ed15f2 100644 --- a/src/xboxdrv_thread.cpp +++ b/src/xboxdrv_thread.cpp @@ -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() diff --git a/src/xboxdrv_thread.hpp b/src/xboxdrv_thread.hpp index 34d450e..ef5cc02 100644 --- a/src/xboxdrv_thread.hpp +++ b/src/xboxdrv_thread.hpp @@ -24,7 +24,7 @@ #include "xboxmsg.hpp" #include "modifier.hpp" -#include "controller_config_set.hpp" +#include "controller_slot_config.hpp" class Options; class XboxGenericController;