diff --git a/SConstruct b/SConstruct
index ce25c82..055a441 100644
--- a/SConstruct
+++ b/SConstruct
@@ -53,6 +53,7 @@ env.Program('xboxdrv', ['src/xboxdrv.cpp',
                         'src/button_event.cpp',
                         'src/axis_event.cpp',
                         'src/arg_parser.cpp',
+                        'src/button_map.cpp',
                         'src/pretty_printer.cpp',
                         'src/helper.cpp',
                         'src/modifier.cpp',
diff --git a/src/button_map.cpp b/src/button_map.cpp
new file mode 100644
index 0000000..39aaa6e
--- /dev/null
+++ b/src/button_map.cpp
@@ -0,0 +1,62 @@
+/*
+**  Xbox360 USB Gamepad Userspace Driver
+**  Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
+**
+**  This program is free software: you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation, either version 3 of the License, or
+**  (at your option) any later version.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "button_map.hpp"
+
+ButtonMap::ButtonMap()
+{
+  clear();
+}
+
+void
+ButtonMap::bind(int code, const ButtonEvent& event)
+{
+  btn_map[XBOX_BTN_UNKNOWN][code] = event;
+}
+
+void
+ButtonMap::bind(int shift_code, int code, const ButtonEvent& event)
+{
+  btn_map[shift_code][code] = event;
+}
+
+ButtonEvent
+ButtonMap::lookup(int code) const
+{
+  return btn_map[XBOX_BTN_UNKNOWN][code];
+}
+
+ButtonEvent
+ButtonMap::lookup_shift(int shift_code, int code) const
+{
+  return btn_map[shift_code][code];
+}
+
+void
+ButtonMap::clear()
+{
+  for(int shift_code = 0; shift_code < XBOX_BTN_MAX; ++shift_code)
+  {
+    for(int code = 0; code < XBOX_BTN_MAX; ++code)
+    {
+      btn_map[shift_code][code] = ButtonEvent::invalid();
+    }
+  }
+}
+
+/* EOF */
diff --git a/src/button_map.hpp b/src/button_map.hpp
new file mode 100644
index 0000000..70240a8
--- /dev/null
+++ b/src/button_map.hpp
@@ -0,0 +1,126 @@
+/*
+**  Xbox360 USB Gamepad Userspace Driver
+**  Copyright (C) 2010 Ingo Ruhnke <grumbel@gmx.de>
+**
+**  This program is free software: you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation, either version 3 of the License, or
+**  (at your option) any later version.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HEADER_XBOXDRV_BUTTON_MAP_HPP
+#define HEADER_XBOXDRV_BUTTON_MAP_HPP
+
+#include <assert.h>
+#include <iostream>
+
+#include "button_event.hpp"
+#include "xboxmsg.hpp"
+
+class ButtonMap
+{
+private:
+  ButtonEvent btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
+  
+public:
+  ButtonMap();
+
+  void bind(int code, const ButtonEvent& event);
+  void bind(int shift_code, int code, const ButtonEvent& event);
+
+  ButtonEvent lookup(int code) const;
+  ButtonEvent lookup_shift(int shift_code, int code) const;
+
+  void clear();
+
+  template<class Pred>
+  bool contains(const Pred& pred) 
+  {
+    for(int shift_code = 0; shift_code < XBOX_BTN_MAX; ++shift_code)
+    {
+      for(int code = 0; code < XBOX_BTN_MAX; ++code)
+      {
+        if (pred(btn_map[shift_code][code]))
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  struct iterator 
+  {
+    friend class ButtonMap;
+  private:
+    ButtonMap& btn_map;
+    int j;
+    int i;
+
+    iterator(ButtonMap& btn_map_) :
+      btn_map(btn_map_), 
+      j(0), 
+      i(0)
+    {}
+
+    iterator(ButtonMap& btn_map_, int j_, int i_) :
+      btn_map(btn_map_), 
+      j(j_), 
+      i(i_)
+    {}
+
+  public:
+    void operator++()
+    {
+      assert(j < XBOX_BTN_MAX);
+
+      i += 1;
+      if (i == XBOX_BTN_MAX)
+      {
+        i  = 0;
+        j += 1;
+      }
+    }
+
+    const ButtonEvent& operator*() const
+    {
+      return btn_map.btn_map[j][i];
+    }
+
+    const ButtonEvent& operator->() const
+    {
+      return btn_map.btn_map[j][i];
+    }
+
+    ButtonEvent& operator*()
+    {
+      return btn_map.btn_map[j][i];
+    }
+
+    ButtonEvent& operator->()
+    {
+      return btn_map.btn_map[j][i];
+    }
+
+    bool operator!=(const iterator& rhs) const
+    {
+      assert(&btn_map == &rhs.btn_map);
+      return (j != rhs.j || i != rhs.i);
+    }
+  };
+
+  iterator begin() { return iterator(*this); }
+  iterator end()   { return iterator(*this, XBOX_BTN_MAX, 0); }
+};
+
+#endif
+
+/* EOF */
diff --git a/src/command_line_options.cpp b/src/command_line_options.cpp
index adca14e..5996c31 100644
--- a/src/command_line_options.cpp
+++ b/src/command_line_options.cpp
@@ -180,7 +180,7 @@ CommandLineOptions::CommandLineOptions() :
     .add_text("Report bugs to Ingo Ruhnke <grumbel@gmx.de>");
 }
 
-void set_ui_button_map(ButtonEvent* ui_button_map, const std::string& str)
+void set_ui_button_map(ButtonMap& ui_button_map, const std::string& str)
 {
   std::string::size_type i = str.find_first_of('=');
   if (i == std::string::npos)
@@ -196,7 +196,7 @@ void set_ui_button_map(ButtonEvent* ui_button_map, const std::string& str)
       
     if (btn != XBOX_BTN_UNKNOWN)
     {
-      ui_button_map[btn] = event;
+      ui_button_map.bind(btn, event);
     }
     else
     {
@@ -367,8 +367,7 @@ CommandLineOptions::parse_args(int argc, char** argv)
 
       case OPTION_UI_CLEAR:
         std::fill_n(opts.uinput_config.axis_map, static_cast<int>(XBOX_AXIS_MAX), AxisEvent::invalid());
-        for(int i = 0; i < XBOX_BTN_MAX; ++i)
-          std::fill_n(opts.uinput_config.btn_map[i],  static_cast<int>(XBOX_BTN_MAX),  ButtonEvent::invalid());
+        opts.uinput_config.btn_map.clear();
         break;
 
       case OPTION_UI_AXISMAP:
@@ -376,7 +375,7 @@ CommandLineOptions::parse_args(int argc, char** argv)
         break;
 
       case OPTION_UI_BUTTONMAP:
-        arg2apply(opt.argument, boost::bind(&set_ui_button_map, opts.uinput_config.btn_map[XBOX_BTN_UNKNOWN], _1));
+        arg2apply(opt.argument, boost::bind(&set_ui_button_map, opts.uinput_config.btn_map, _1));
         break;
 
       case OPTION_ID:
diff --git a/src/uinput.cpp b/src/uinput.cpp
index f9947af..e61e45b 100644
--- a/src/uinput.cpp
+++ b/src/uinput.cpp
@@ -33,19 +33,40 @@
 #include "uinput.hpp"
 #include "uinput_deviceid.hpp"
 
+bool is_keyboard_event(const ButtonEvent& event)
+{
+  if (event.type == EV_KEY && uInput::is_keyboard_button(event.code))
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool is_mouse_event(const ButtonEvent& event)
+{
+  if (event.type == EV_KEY && uInput::is_mouse_button(event.code))
+  {
+    return true;
+  }
+  else if (event.type == EV_REL)
+  {
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
 bool
 uInput::need_keyboard_device()
 {
-  for(int j = 0; j < XBOX_BTN_MAX; ++j)
+  if (cfg.btn_map.contains(is_keyboard_event))
   {
-    for(int i = 0; i < XBOX_BTN_MAX; ++i)
-    {
-      if (cfg.btn_map[j][i].type == EV_KEY &&
-          is_keyboard_button(cfg.btn_map[j][i].code))
-      {
-        return true;
-      }
-    }
+    return true;
   }
 
   for(int i = 0; i < XBOX_AXIS_MAX; ++i)
@@ -64,20 +85,9 @@ uInput::need_keyboard_device()
 bool
 uInput::need_mouse_device()
 {
-  for(int j = 0; j < XBOX_BTN_MAX; ++j)
+  if (cfg.btn_map.contains(is_mouse_event))
   {
-    for(int i = 0; i < XBOX_BTN_MAX; ++i)
-    {
-      if (cfg.btn_map[j][i].type == EV_KEY &&
-          is_mouse_button(cfg.btn_map[j][i].code))
-      {
-        return true;
-      }
-      else if (cfg.btn_map[j][i].type == EV_REL)
-      {
-        return true;
-      }
-    }
+    return true;
   }
 
   for(int i = 0; i < XBOX_AXIS_MAX; ++i)
@@ -131,12 +141,9 @@ uInput::uInput(const XPadDevice& dev, uInputCfg config_) :
     create_uinput_device(0);
   }
 
-  for(int j = 0; j < XBOX_BTN_MAX; ++j)
+  for(ButtonMap::iterator i = cfg.btn_map.begin(); i != cfg.btn_map.end(); ++i)
   {
-    for(int i = 0; i < XBOX_BTN_MAX; ++i)
-    {
-      cfg.btn_map[j][i].device_id = create_uinput_device(cfg.btn_map[j][i]);
-    }
+    (*i).device_id = create_uinput_device(*i);
   }
 
   for(int i = 0; i < XBOX_AXIS_MAX; ++i)
@@ -657,9 +664,9 @@ uInput::update(int msec_delta)
 
     if (i->time >= i->next_time)
     {
-      get_mouse_uinput()->send(EV_REL, cfg.btn_map[XBOX_BTN_UNKNOWN][i->button].code, 
-                               static_cast<int>(cfg.btn_map[XBOX_BTN_UNKNOWN][i->button].rel.value * button_state[i->button]));
-      i->next_time += cfg.btn_map[XBOX_BTN_UNKNOWN][i->button].rel.repeat;
+      get_mouse_uinput()->send(EV_REL, cfg.btn_map.lookup(i->button).code, 
+                               static_cast<int>(cfg.btn_map.lookup(i->button).rel.value * button_state[i->button]));
+      i->next_time += cfg.btn_map.lookup(i->button).rel.repeat;
       needs_syncronization = true;
     }
   }
@@ -680,7 +687,7 @@ uInput::send_button(int code, bool value)
   {
     button_state[code] = value;
 
-    const ButtonEvent& event = cfg.btn_map[XBOX_BTN_UNKNOWN][code];
+    const ButtonEvent& event = cfg.btn_map.lookup(code);
   
     send_key(event.device_id, event.code, value);
   }
@@ -803,7 +810,7 @@ uInput::add_axis(int code, int min, int max)
 void
 uInput::add_button(int code)
 {
-  const ButtonEvent& event = cfg.btn_map[XBOX_BTN_UNKNOWN][code];
+  const ButtonEvent& event = cfg.btn_map.lookup(code);
 
   if (event.type == EV_KEY)
   {
diff --git a/src/uinput.hpp b/src/uinput.hpp
index c7930c2..e6f58d6 100644
--- a/src/uinput.hpp
+++ b/src/uinput.hpp
@@ -102,8 +102,9 @@ private:
   bool need_keyboard_device();
   bool need_joystick_device();
 
-  bool is_mouse_button(int ev_code);
-  bool is_keyboard_button(int ev_code);
+public:
+  static bool is_mouse_button(int ev_code);
+  static bool is_keyboard_button(int ev_code);
 };
 
 #endif
diff --git a/src/uinput_cfg.cpp b/src/uinput_cfg.cpp
index c8ed687..fa72c13 100644
--- a/src/uinput_cfg.cpp
+++ b/src/uinput_cfg.cpp
@@ -29,44 +29,41 @@ uInputCfg::uInputCfg() :
   force_feedback(false),
   extra_devices(true)
 {
-  for(int i = 0; i < XBOX_BTN_MAX; ++i)
-    std::fill_n(btn_map[i],  static_cast<int>(XBOX_BTN_MAX),  ButtonEvent::invalid());
+  btn_map.clear();
   std::fill_n(axis_map, static_cast<int>(XBOX_AXIS_MAX), AxisEvent::invalid());
 
-  ButtonEvent* bmap = btn_map[XBOX_BTN_UNKNOWN]; // FIXME: little hacky to abuse XBOX_BTN_UNKNOWN
-
   // Button Mapping
-  bmap[XBOX_BTN_START] = ButtonEvent::create(EV_KEY, BTN_START);
-  bmap[XBOX_BTN_GUIDE] = ButtonEvent::create(EV_KEY, BTN_MODE);
-  bmap[XBOX_BTN_BACK]  = ButtonEvent::create(EV_KEY, BTN_SELECT);
+  btn_map.bind(XBOX_BTN_START, ButtonEvent::create(EV_KEY, BTN_START));
+  btn_map.bind(XBOX_BTN_GUIDE, ButtonEvent::create(EV_KEY, BTN_MODE));
+  btn_map.bind(XBOX_BTN_BACK, ButtonEvent::create(EV_KEY, BTN_SELECT));
 
-  bmap[XBOX_BTN_A] = ButtonEvent::create(EV_KEY, BTN_A);
-  bmap[XBOX_BTN_B] = ButtonEvent::create(EV_KEY, BTN_B);
-  bmap[XBOX_BTN_X] = ButtonEvent::create(EV_KEY, BTN_X);
-  bmap[XBOX_BTN_Y] = ButtonEvent::create(EV_KEY, BTN_Y);
+  btn_map.bind(XBOX_BTN_A, ButtonEvent::create(EV_KEY, BTN_A));
+  btn_map.bind(XBOX_BTN_B, ButtonEvent::create(EV_KEY, BTN_B));
+  btn_map.bind(XBOX_BTN_X, ButtonEvent::create(EV_KEY, BTN_X));
+  btn_map.bind(XBOX_BTN_Y, ButtonEvent::create(EV_KEY, BTN_Y));
 
-  bmap[XBOX_BTN_GREEN]  = ButtonEvent::create(EV_KEY, BTN_0);
-  bmap[XBOX_BTN_RED]    = ButtonEvent::create(EV_KEY, BTN_1);
-  bmap[XBOX_BTN_YELLOW] = ButtonEvent::create(EV_KEY, BTN_2);
-  bmap[XBOX_BTN_BLUE]   = ButtonEvent::create(EV_KEY, BTN_3);
-  bmap[XBOX_BTN_ORANGE] = ButtonEvent::create(EV_KEY, BTN_4);
+  btn_map.bind(XBOX_BTN_GREEN, ButtonEvent::create(EV_KEY, BTN_0));
+  btn_map.bind(XBOX_BTN_RED, ButtonEvent::create(EV_KEY, BTN_1));
+  btn_map.bind(XBOX_BTN_YELLOW, ButtonEvent::create(EV_KEY, BTN_2));
+  btn_map.bind(XBOX_BTN_BLUE, ButtonEvent::create(EV_KEY, BTN_3));
+  btn_map.bind(XBOX_BTN_ORANGE, ButtonEvent::create(EV_KEY, BTN_4));
 
-  bmap[XBOX_BTN_WHITE] = ButtonEvent::create(EV_KEY, BTN_TL);
-  bmap[XBOX_BTN_BLACK] = ButtonEvent::create(EV_KEY, BTN_TR);
+  btn_map.bind(XBOX_BTN_WHITE, ButtonEvent::create(EV_KEY, BTN_TL));
+  btn_map.bind(XBOX_BTN_BLACK, ButtonEvent::create(EV_KEY, BTN_TR));
 
-  bmap[XBOX_BTN_LB] = ButtonEvent::create(EV_KEY, BTN_TL);
-  bmap[XBOX_BTN_RB] = ButtonEvent::create(EV_KEY, BTN_TR);
+  btn_map.bind(XBOX_BTN_LB, ButtonEvent::create(EV_KEY, BTN_TL));
+  btn_map.bind(XBOX_BTN_RB, ButtonEvent::create(EV_KEY, BTN_TR));
 
-  bmap[XBOX_BTN_LT] = ButtonEvent::create(EV_KEY, BTN_TL2);
-  bmap[XBOX_BTN_RT] = ButtonEvent::create(EV_KEY, BTN_TR2);
+  btn_map.bind(XBOX_BTN_LT, ButtonEvent::create(EV_KEY, BTN_TL2));
+  btn_map.bind(XBOX_BTN_RT, ButtonEvent::create(EV_KEY, BTN_TR2));
 
-  bmap[XBOX_BTN_THUMB_L] = ButtonEvent::create(EV_KEY, BTN_THUMBL);
-  bmap[XBOX_BTN_THUMB_R] = ButtonEvent::create(EV_KEY, BTN_THUMBR);
+  btn_map.bind(XBOX_BTN_THUMB_L, ButtonEvent::create(EV_KEY, BTN_THUMBL));
+  btn_map.bind(XBOX_BTN_THUMB_R, ButtonEvent::create(EV_KEY, BTN_THUMBR));
   
-  bmap[XBOX_DPAD_UP]    = ButtonEvent::create(EV_KEY, BTN_BASE);
-  bmap[XBOX_DPAD_DOWN]  = ButtonEvent::create(EV_KEY, BTN_BASE2);
-  bmap[XBOX_DPAD_LEFT]  = ButtonEvent::create(EV_KEY, BTN_BASE3);
-  bmap[XBOX_DPAD_RIGHT] = ButtonEvent::create(EV_KEY, BTN_BASE4);
+  btn_map.bind(XBOX_DPAD_UP, ButtonEvent::create(EV_KEY, BTN_BASE));
+  btn_map.bind(XBOX_DPAD_DOWN, ButtonEvent::create(EV_KEY, BTN_BASE2));
+  btn_map.bind(XBOX_DPAD_LEFT, ButtonEvent::create(EV_KEY, BTN_BASE3));
+  btn_map.bind(XBOX_DPAD_RIGHT, ButtonEvent::create(EV_KEY, BTN_BASE4));
 
   // Axis Mapping
   axis_map[XBOX_AXIS_X1]      = AxisEvent::create(EV_ABS, ABS_X); 
@@ -87,39 +84,37 @@ uInputCfg::mimic_xpad()
 
   extra_devices = false;
 
-  ButtonEvent* bmap = btn_map[XBOX_BTN_UNKNOWN]; // FIXME: little hacky to abuse XBOX_BTN_UNKNOWN
+  btn_map.bind(XBOX_BTN_START, ButtonEvent::create(EV_KEY, BTN_START));
+  btn_map.bind(XBOX_BTN_GUIDE, ButtonEvent::create(EV_KEY, BTN_MODE));
+  btn_map.bind(XBOX_BTN_BACK, ButtonEvent::create(EV_KEY, BTN_BACK));
 
-  bmap[XBOX_BTN_START] = ButtonEvent::create(EV_KEY, BTN_START);
-  bmap[XBOX_BTN_GUIDE] = ButtonEvent::create(EV_KEY, BTN_MODE);
-  bmap[XBOX_BTN_BACK]  = ButtonEvent::create(EV_KEY, BTN_BACK);
+  btn_map.bind(XBOX_BTN_A, ButtonEvent::create(EV_KEY, BTN_A));
+  btn_map.bind(XBOX_BTN_B, ButtonEvent::create(EV_KEY, BTN_B));
+  btn_map.bind(XBOX_BTN_X, ButtonEvent::create(EV_KEY, BTN_X));
+  btn_map.bind(XBOX_BTN_Y, ButtonEvent::create(EV_KEY, BTN_Y));
 
-  bmap[XBOX_BTN_A] = ButtonEvent::create(EV_KEY, BTN_A);
-  bmap[XBOX_BTN_B] = ButtonEvent::create(EV_KEY, BTN_B);
-  bmap[XBOX_BTN_X] = ButtonEvent::create(EV_KEY, BTN_X);
-  bmap[XBOX_BTN_Y] = ButtonEvent::create(EV_KEY, BTN_Y);
+  btn_map.bind(XBOX_BTN_GREEN, ButtonEvent::create(EV_KEY, BTN_0));
+  btn_map.bind(XBOX_BTN_RED, ButtonEvent::create(EV_KEY, BTN_1));
+  btn_map.bind(XBOX_BTN_YELLOW, ButtonEvent::create(EV_KEY, BTN_2));
+  btn_map.bind(XBOX_BTN_BLUE, ButtonEvent::create(EV_KEY, BTN_3));
+  btn_map.bind(XBOX_BTN_ORANGE, ButtonEvent::create(EV_KEY, BTN_4));
 
-  bmap[XBOX_BTN_GREEN]  = ButtonEvent::create(EV_KEY, BTN_0);
-  bmap[XBOX_BTN_RED]    = ButtonEvent::create(EV_KEY, BTN_1);
-  bmap[XBOX_BTN_YELLOW] = ButtonEvent::create(EV_KEY, BTN_2);
-  bmap[XBOX_BTN_BLUE]   = ButtonEvent::create(EV_KEY, BTN_3);
-  bmap[XBOX_BTN_ORANGE] = ButtonEvent::create(EV_KEY, BTN_4);
+  btn_map.bind(XBOX_BTN_WHITE, ButtonEvent::create(EV_KEY, BTN_TL));
+  btn_map.bind(XBOX_BTN_BLACK, ButtonEvent::create(EV_KEY, BTN_TR));
 
-  bmap[XBOX_BTN_WHITE] = ButtonEvent::create(EV_KEY, BTN_TL);
-  bmap[XBOX_BTN_BLACK] = ButtonEvent::create(EV_KEY, BTN_TR);
-
-  bmap[XBOX_BTN_LB] = ButtonEvent::create(EV_KEY, BTN_TL);
-  bmap[XBOX_BTN_RB] = ButtonEvent::create(EV_KEY, BTN_TR);
+  btn_map.bind(XBOX_BTN_LB, ButtonEvent::create(EV_KEY, BTN_TL));
+  btn_map.bind(XBOX_BTN_RB, ButtonEvent::create(EV_KEY, BTN_TR));
             
-  bmap[XBOX_BTN_LT] = ButtonEvent::create(EV_KEY, BTN_TL2);
-  bmap[XBOX_BTN_RT] = ButtonEvent::create(EV_KEY, BTN_TR2);
+  btn_map.bind(XBOX_BTN_LT, ButtonEvent::create(EV_KEY, BTN_TL2));
+  btn_map.bind(XBOX_BTN_RT, ButtonEvent::create(EV_KEY, BTN_TR2));
             
-  bmap[XBOX_BTN_THUMB_L] = ButtonEvent::create(EV_KEY, BTN_THUMBL);
-  bmap[XBOX_BTN_THUMB_R] = ButtonEvent::create(EV_KEY, BTN_THUMBR);
+  btn_map.bind(XBOX_BTN_THUMB_L, ButtonEvent::create(EV_KEY, BTN_THUMBL));
+  btn_map.bind(XBOX_BTN_THUMB_R, ButtonEvent::create(EV_KEY, BTN_THUMBR));
             
-  bmap[XBOX_DPAD_UP]    = ButtonEvent::create(EV_KEY, BTN_BASE);
-  bmap[XBOX_DPAD_DOWN]  = ButtonEvent::create(EV_KEY, BTN_BASE2);
-  bmap[XBOX_DPAD_LEFT]  = ButtonEvent::create(EV_KEY, BTN_BASE3);
-  bmap[XBOX_DPAD_RIGHT] = ButtonEvent::create(EV_KEY, BTN_BASE4);
+  btn_map.bind(XBOX_DPAD_UP, ButtonEvent::create(EV_KEY, BTN_BASE));
+  btn_map.bind(XBOX_DPAD_DOWN, ButtonEvent::create(EV_KEY, BTN_BASE2));
+  btn_map.bind(XBOX_DPAD_LEFT, ButtonEvent::create(EV_KEY, BTN_BASE3));
+  btn_map.bind(XBOX_DPAD_RIGHT, ButtonEvent::create(EV_KEY, BTN_BASE4));
 
   // Axis Mapping
   axis_map[XBOX_AXIS_X1]      = AxisEvent::create(EV_ABS, ABS_X, 16, 128);
diff --git a/src/uinput_cfg.hpp b/src/uinput_cfg.hpp
index 607e6e7..44c1f97 100644
--- a/src/uinput_cfg.hpp
+++ b/src/uinput_cfg.hpp
@@ -21,6 +21,7 @@
 
 #include "axis_event.hpp"
 #include "button_event.hpp"
+#include "button_map.hpp"
 #include "xboxmsg.hpp"
 
 class uInputCfg
@@ -34,8 +35,8 @@ public:
   bool force_feedback;
   bool extra_devices;
 
-  ButtonEvent btn_map[XBOX_BTN_MAX][XBOX_BTN_MAX];
-  AxisEvent   axis_map[XBOX_AXIS_MAX];
+  ButtonMap btn_map;
+  AxisEvent axis_map[XBOX_AXIS_MAX];
 
   uInputCfg();