diff --git a/chatpad/SConstruct b/chatpad/SConstruct
index d293270..b1486f8 100644
--- a/chatpad/SConstruct
+++ b/chatpad/SConstruct
@@ -1,10 +1,13 @@
-env = Environment(CXXFLAGS=["-Werror", "-Wall"], LIBS=["usb", "boost_thread"])
+env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb", "boost_thread"])
 env.Program("chatpad", ["chatpad.cpp"])
 
-env = Environment(CXXFLAGS=["-Werror", "-Wall"], LIBS=["usb-1.0", "boost_thread"])
+env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
 env.Program("chatpad2", ["chatpad2.cpp"])
 
-env = Environment(CXXFLAGS=["-Werror", "-Wall"], LIBS=["usb-1.0", "boost_thread"])
+env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
+env.Program("chatpad3", ["chatpad3.cpp"])
+
+env = Environment(CXXFLAGS=["-Werror", "-Wall", "-g", "-O0"], LIBS=["usb-1.0", "boost_thread"])
 env.Program("reset", ["reset.cpp"])
 
 # EOF #
diff --git a/chatpad/chatpad2.cpp b/chatpad/chatpad2.cpp
index 44a3ad9..0807e31 100644
--- a/chatpad/chatpad2.cpp
+++ b/chatpad/chatpad2.cpp
@@ -15,12 +15,15 @@ private:
   uint8_t old_buttons;
   uint8_t old_dpad;
 
+  bool m_running;
+
 public:
   Main() :
     m_ctx(0),
     m_handle(0),
     old_buttons(0),
-    old_dpad(0)
+    old_dpad(0),
+    m_running(false)
   {}
 
   ~Main()
@@ -42,6 +45,8 @@ public:
   {
     m_handle = libusb_open_device_with_vid_pid(m_ctx, 0x045e, 0x028e);
 
+    set_configuration();
+
     std::cout << "handle: " << m_handle << std::endl;
     if (!m_handle)
     {
@@ -53,6 +58,39 @@ public:
 
     err = libusb_claim_interface(m_handle, 0);
     std::cout << "Claim: " << err << std::endl;
+
+    m_running = true;
+  }
+
+  void set_configuration()
+  {
+    old_buttons = 0;
+    old_dpad    = 0;
+
+    if (m_running)
+    {
+      libusb_release_interface(m_handle, 0);
+      libusb_release_interface(m_handle, 2);
+    }
+
+    int ret = libusb_set_configuration(m_handle, 1);
+
+    switch(ret)
+    {
+      case 0:
+        std::cout << "set_configuration(): success" << std::endl;
+        break;
+
+      default:
+        std::cout << "set_configuration(): " << ret << std::endl;
+        break;
+    }
+
+    if (m_running)
+    {
+      libusb_claim_interface(m_handle, 0);
+      libusb_claim_interface(m_handle, 2);
+    }
   }
 
   void reset()
@@ -60,9 +98,13 @@ public:
     std::cout << "reset()" << std::endl;
     libusb_reset_device(m_handle);
     libusb_close(m_handle);
+    libusb_exit(m_ctx);
     m_handle = 0;
-    sleep(1);
-    init_device_handle();
+    m_ctx    = 0;
+    old_buttons = 0;
+    old_dpad    = 0;
+
+    execl("./chatpad2", "./chatpad2", NULL);
   }
 
   void ctrl_msg(uint8_t value)
@@ -153,6 +195,9 @@ public:
             {
               callback(data.get());
             }
+            
+            //            if (endpoint == 6)
+            //  std::cout << "Clear Halt: " << libusb_clear_halt(m_handle, endpoint) << std::endl;
           }
           break;
 
@@ -172,6 +217,10 @@ public:
           std::cout << "read_thread: no device" << std::endl;
           break;
         
+        case LIBUSB_ERROR_OTHER: // happens on reset
+          std::cout << "read_thread: other error" << std::endl;
+          break;
+
         default:
           std::cout << "read_thread: unknown: " << ret << std::endl;
           break;
@@ -194,21 +243,26 @@ public:
     switch(dpad)
     {
       case 0x04: // left
+        ctrl_msg(0x08);
         break;
 
       case 0x08: // right
+        ctrl_msg(0x09);
         break;
 
       case 0x01: // up        
+        ctrl_msg(0x0a);
         break;
 
       case 0x02: // down
+        ctrl_msg(0x0b);
         break;
 
       case 0x20: // back
         break;
 
       case 0x10: // start
+        set_configuration();
         break;
 
       case 0x40: // left stick
@@ -245,7 +299,7 @@ public:
         break;
 
       case 0x04: // guide
-        ctrl_msg(0x17);
+        reset();
         break;
     }
   }
diff --git a/chatpad/chatpad3.cpp b/chatpad/chatpad3.cpp
new file mode 100644
index 0000000..244a079
--- /dev/null
+++ b/chatpad/chatpad3.cpp
@@ -0,0 +1,201 @@
+#include <boost/thread.hpp>
+#include <boost/format.hpp>
+#include <boost/function.hpp>
+#include <boost/scoped_array.hpp>
+#include <libusb-1.0/libusb.h>
+#include <iostream>
+#include <stdexcept>
+#include <stdlib.h>
+
+class Main
+{
+private:
+  libusb_context*       m_ctx;
+  libusb_device_handle* m_handle;
+
+public:
+  Main() :
+    m_ctx(0),
+    m_handle(0)
+  {}
+
+  ~Main()
+  {
+  }
+
+  void init_libusb()
+  {    
+    if (libusb_init(&m_ctx) != 0)
+    {
+      throw std::runtime_error("Libusb went wrong");
+    }
+
+    std::cout << "Debug to max" << std::endl;
+    libusb_set_debug(m_ctx, 3);
+  }
+
+  void init_device_handle()
+  {
+    m_handle = libusb_open_device_with_vid_pid(m_ctx, 0x045e, 0x028e);
+
+    std::cout << "handle: " << m_handle << std::endl;
+    if (!m_handle)
+    {
+      throw std::runtime_error("Couldn't find controller");
+    }
+
+    int err = libusb_claim_interface(m_handle, 2);
+    std::cout << "Claim: " << err << std::endl;
+
+    err = libusb_claim_interface(m_handle, 0);
+    std::cout << "Claim: " << err << std::endl;
+  }
+
+  void ctrl_msg(uint8_t value)
+  {
+    int ret = libusb_control_transfer(m_handle,
+                                      LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
+                                      LIBUSB_REQUEST_GET_STATUS,
+                                      value, 0x02, NULL, 0, 0);
+    std::cout << "ctrl_msg: " << ret << boost::format(" %02x") % int(value) << std::endl;
+  }
+
+  static void callback_wrap(libusb_transfer* transfer)
+  {
+    static_cast<Main*>(transfer->user_data)->callback(transfer);
+  }
+
+  void callback(libusb_transfer* transfer)
+  {
+    if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
+      std::cout << "data transfer not completed: " << transfer->status << std::endl;
+    }
+
+    unsigned char* data = transfer->buffer;
+    std::cout << "callback(" << transfer->actual_length << "): ";
+    for(int i = 0; i < transfer->actual_length; ++i)
+    {
+      std::cout << boost::format("0x%02x ") % int(data[i]);
+    }
+    std::cout << std::endl;
+
+    // done with the transfer, so clean it up
+    // libusb_free_transfer(transfer);
+
+    // request more data
+    request_controller_data(LIBUSB_ENDPOINT_ADDRESS_MASK & transfer->endpoint);
+  }
+
+  static void control_callback_wrap(libusb_transfer* transfer)
+  {
+    static_cast<Main*>(transfer->user_data)->control_callback(transfer);
+  }
+
+  void control_callback(libusb_transfer* transfer)
+  {
+    
+  }
+
+  void request_controller_data(int endpoint)
+  {
+    libusb_transfer* transfer = libusb_alloc_transfer(0);
+    if (!transfer)
+    {
+      std::cout << "Couldn't alloc transfer" << std::endl;
+    }
+
+    unsigned char* buffer = static_cast<unsigned char*>(malloc(8+32));
+
+    libusb_fill_interrupt_transfer(transfer,
+                                   m_handle,
+                                   endpoint | LIBUSB_ENDPOINT_IN,
+                                   buffer, // buffer
+                                   8+32,    // length,
+                                   &Main::callback_wrap,
+                                   this, // userdata
+                                   0     // timeout
+      );
+
+    transfer->flags = 
+      LIBUSB_TRANSFER_FREE_BUFFER  |
+      LIBUSB_TRANSFER_FREE_TRANSFER;
+
+    int ret = libusb_submit_transfer(transfer);
+    if (ret != 0)
+    {
+      std::cout << "Error with libusb_submit_transfer: " << ret << std::endl;
+    }
+  }
+
+  void request_control(unsigned char value)
+  {
+    libusb_transfer* transfer = libusb_alloc_transfer(0);
+    if (!transfer)
+    {
+      std::cout << "Couldn't alloc transfer" << std::endl;
+    }
+
+    unsigned char* buffer = static_cast<unsigned char*>(malloc(LIBUSB_CONTROL_SETUP_SIZE));
+    libusb_fill_control_transfer(transfer, m_handle, buffer, 
+                                 &Main::control_callback_wrap, 
+                                 this,
+                                 0);
+
+    libusb_fill_control_setup(buffer, 
+                              LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_INTERFACE,
+                              LIBUSB_REQUEST_GET_STATUS,
+                              value,
+                              2,
+                              0);
+
+    transfer->flags = 
+      LIBUSB_TRANSFER_FREE_BUFFER  |
+      LIBUSB_TRANSFER_FREE_TRANSFER;
+
+    int ret = libusb_submit_transfer(transfer);
+    if (ret != 0)
+    {
+      std::cout << "Error with libusb_submit_transfer: " << ret << std::endl;
+    }
+  }
+
+  void main_loop()
+  {
+    request_controller_data(1);
+    request_controller_data(6);
+    request_control(0x1f);
+    request_control(0x1b);
+    while(true)
+    {
+      std::cout << "Handle events: " << libusb_handle_events(m_ctx) << std::endl;
+    }
+  }
+
+  void run()
+  {
+    init_libusb();
+    init_device_handle();
+
+    main_loop();
+
+    libusb_close(m_handle);
+    libusb_exit(m_ctx);
+  }
+};
+
+int main()
+{
+  try 
+  {
+    Main app;
+    app.run();
+  }
+  catch(const std::exception& err)
+  {
+    std::cout << "Error: " << err.what() << std::endl;
+  }
+  
+  return 0;
+}
+
+/* EOF */