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;