From a823cef71a565b6df1ef21c7d0aa6b18b0d5fb70 Mon Sep 17 00:00:00 2001
From: Ingo Ruhnke <grumbel@gmx.de>
Date: Thu, 18 Jun 2009 22:14:30 +0200
Subject: [PATCH] Added some code for 'Firestorm Dual Power 3 vs b'

---
 src/firestorm_dual_controller.cpp | 118 ++++++++++++++++++++++++++++++
 src/firestorm_dual_controller.hpp |   2 +
 2 files changed, 120 insertions(+)

diff --git a/src/firestorm_dual_controller.cpp b/src/firestorm_dual_controller.cpp
index d31d8bb..19582bf 100644
--- a/src/firestorm_dual_controller.cpp
+++ b/src/firestorm_dual_controller.cpp
@@ -21,8 +21,38 @@
 #include <stdexcept>
 #include <sstream>
 #include <string.h>
+#include <boost/format.hpp>
+
 #include "firestorm_dual_controller.hpp"
 
+// 044f:b312
+struct Firestorm_vsb_Msg
+{
+  unsigned int a   :1;
+  unsigned int x   :1;
+  unsigned int b   :1;
+  unsigned int y   :1;
+
+  unsigned int lb  :1;
+  unsigned int lt  :1;
+  unsigned int rb  :1;
+  unsigned int rt  :1;
+
+  unsigned int back  :1;
+  unsigned int start :1;
+  
+  unsigned int thumb_l :1;
+  unsigned int thumb_r :1;
+
+  unsigned int dpad :4; // 0xf == center, 0x00 == up, clockwise + 1 each
+
+  int x1 :8;
+  int y1 :8;
+  int x2 :8;
+  unsigned int y2 :8;  
+};
+
+// 044f:b304
 struct FirestormMsg
 {
   unsigned int a   :1;
@@ -121,6 +151,94 @@ inline int16_t scale_8to16(int8_t a)
 
 bool
 FirestormDualController::read(XboxGenericMsg& msg, bool verbose, int timeout)
+{
+  //return read_vsb(msg, verbose, timeout);
+  return read_default(msg, verbose, timeout);
+}
+
+bool
+FirestormDualController::read_vsb(XboxGenericMsg& msg, bool verbose, int timeout)
+{
+  Firestorm_vsb_Msg data;
+  int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)&data, sizeof(data), timeout);
+
+  if (ret == -ETIMEDOUT)
+    {
+      return false;
+    }
+  else if (ret < 0)
+    { // Error
+      std::ostringstream str;
+      str << "USBError: " << ret << "\n" << usb_strerror();
+      throw std::runtime_error(str.str());
+    }
+  else if (ret == sizeof(data))
+    {
+      if (0)
+        { // debug output
+          for(size_t i = 0; i < sizeof(data); ++i)
+            {
+              uint8_t v = reinterpret_cast<char*>(&data)[i];
+              std::cout << boost::format("0x%02x ") % (int)v;
+            }
+          std::cout << std::endl;
+        }
+
+      memset(&msg, 0, sizeof(msg));
+      msg.type    = XBOX_MSG_XBOX360;
+
+      msg.xbox360.a = data.a;
+      msg.xbox360.b = data.b;
+      msg.xbox360.x = data.x;
+      msg.xbox360.y = data.y;
+
+      msg.xbox360.lb = data.lb;
+      msg.xbox360.rb = data.rb;
+
+      msg.xbox360.lt = data.lt * 255;
+      msg.xbox360.rt = data.rt * 255;
+
+      msg.xbox360.start = data.start;
+      msg.xbox360.back  = data.back;
+
+      msg.xbox360.thumb_l = data.thumb_l;
+      msg.xbox360.thumb_r = data.thumb_r;
+      
+      msg.xbox360.x1 = scale_8to16(data.x1);
+      msg.xbox360.y1 = scale_8to16(data.y1);
+
+      msg.xbox360.x2 = scale_8to16(data.x2);
+      msg.xbox360.y2 = scale_8to16(data.y2 - 128);
+
+      // Invert the axis
+      msg.xbox360.y1 = negate_16(msg.xbox360.y1);
+      msg.xbox360.y2 = negate_16(msg.xbox360.y2);
+
+      // data.dpad == 0xf0 -> dpad centered
+      // data.dpad == 0xe0 -> dpad-only mode is enabled
+
+      if (data.dpad == 0x0 || data.dpad == 0x7 || data.dpad == 0x1)
+        msg.xbox360.dpad_up   = 1;
+
+      if (data.dpad == 0x1 || data.dpad == 0x2 || data.dpad == 0x3)
+        msg.xbox360.dpad_right = 1;
+
+      if (data.dpad == 0x3 || data.dpad == 0x4 || data.dpad == 0x5)
+        msg.xbox360.dpad_down = 1;
+      
+      if (data.dpad == 0x5 || data.dpad == 0x6 || data.dpad == 0x7)
+        msg.xbox360.dpad_left  = 1;
+
+      return true;
+    }
+  else
+    {
+      return false;
+    }  
+}
+
+bool
+FirestormDualController::read_default(XboxGenericMsg& msg, bool verbose, int timeout)
 {
   FirestormMsg data;
   int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, (char*)&data, sizeof(data), timeout);
diff --git a/src/firestorm_dual_controller.hpp b/src/firestorm_dual_controller.hpp
index db0a2e9..ad7e6d0 100644
--- a/src/firestorm_dual_controller.hpp
+++ b/src/firestorm_dual_controller.hpp
@@ -41,6 +41,8 @@ public:
 
   /** @param timeout   timeout in msec, 0 means forever */
   bool read(XboxGenericMsg& msg, bool verbose, int timeout);
+  bool read_default(XboxGenericMsg& msg, bool verbose, int timeout);
+  bool read_vsb(XboxGenericMsg& msg, bool verbose, int timeout);
 };
 
 #endif