bool
FirestormDualController::read_vsb(XboxGenericMsg& msg, bool verbose, int timeout)
{
  Firestorm_vsb_Msg data;
  int ret = usb_interrupt_read(handle, 1 /*EndPoint*/, reinterpret_cast<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 ") % static_cast<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 = static_cast<unsigned char>(data.lt * 255);
    msg.xbox360.rt = static_cast<unsigned char>(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*/, reinterpret_cast<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))
  {
    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 == 0x00 || data.dpad == 0x70 || data.dpad == 0x10)
      msg.xbox360.dpad_up   = 1;

    if (data.dpad == 0x10 || data.dpad == 0x20 || data.dpad == 0x30)
      msg.xbox360.dpad_right = 1;

    if (data.dpad == 0x30 || data.dpad == 0x40 || data.dpad == 0x50)
      msg.xbox360.dpad_down = 1;
      
    if (data.dpad == 0x50 || data.dpad == 0x60 || data.dpad == 0x70)
      msg.xbox360.dpad_left  = 1;

    return true;
  }
  else
  {
    return false;
  }
}
bool
SaitekP2500Controller::parse(uint8_t* data, int len, XboxGenericMsg* msg_out)
{
  if (len == sizeof(SaitekP2500Msg))
  {
    SaitekP2500Msg msg_in;
    memcpy(&msg_in, data, sizeof(SaitekP2500Msg));

    memset(msg_out, 0, sizeof(*msg_out));
    msg_out->type = XBOX_MSG_XBOX360;

    msg_out->xbox360.a = msg_in.a;
    msg_out->xbox360.b = msg_in.b;
    msg_out->xbox360.x = msg_in.x;
    msg_out->xbox360.y = msg_in.y;

    msg_out->xbox360.lb = msg_in.lb;
    msg_out->xbox360.rb = msg_in.rb;

    msg_out->xbox360.lt = msg_in.lt * 255;
    msg_out->xbox360.rt = msg_in.rt * 255;

    msg_out->xbox360.start = msg_in.start;
    msg_out->xbox360.back  = msg_in.back;

    msg_out->xbox360.thumb_l = msg_in.thumb_l;
    msg_out->xbox360.thumb_r = msg_in.thumb_r;
      
    msg_out->xbox360.x1 = scale_8to16(msg_in.x1);
    msg_out->xbox360.y1 = scale_8to16(msg_in.y1);

    msg_out->xbox360.x2 = scale_8to16(msg_in.x2);
    msg_out->xbox360.y2 = scale_8to16(msg_in.y2);

    switch(msg_in.dpad)
    {
      case 0:
        msg_out->xbox360.dpad_up    = 1;
        msg_out->xbox360.dpad_down  = 0;
        msg_out->xbox360.dpad_left  = 0;
        msg_out->xbox360.dpad_right = 0;
        break;

      case 1:
        msg_out->xbox360.dpad_up    = 1;
        msg_out->xbox360.dpad_down  = 0;
        msg_out->xbox360.dpad_left  = 0;
        msg_out->xbox360.dpad_right = 1;
        break;

      case 2:
        msg_out->xbox360.dpad_up    = 0;
        msg_out->xbox360.dpad_down  = 0;
        msg_out->xbox360.dpad_left  = 0;
        msg_out->xbox360.dpad_right = 1;
        break;

      case 3:
        msg_out->xbox360.dpad_up    = 0;
        msg_out->xbox360.dpad_down  = 1;
        msg_out->xbox360.dpad_left  = 0;
        msg_out->xbox360.dpad_right = 1;
        break;

      case 4:
        msg_out->xbox360.dpad_up    = 0;
        msg_out->xbox360.dpad_down  = 1;
        msg_out->xbox360.dpad_left  = 0;
        msg_out->xbox360.dpad_right = 0;
        break;

      case 5:
        msg_out->xbox360.dpad_up    = 0;
        msg_out->xbox360.dpad_down  = 1;
        msg_out->xbox360.dpad_left  = 1;
        msg_out->xbox360.dpad_right = 0;
        break;

      case 6:
        msg_out->xbox360.dpad_up    = 0;
        msg_out->xbox360.dpad_down  = 0;
        msg_out->xbox360.dpad_left  = 1;
        msg_out->xbox360.dpad_right = 0;
        break;

      case 7:
        msg_out->xbox360.dpad_up    = 1;
        msg_out->xbox360.dpad_down  = 0;
        msg_out->xbox360.dpad_left  = 1;
        msg_out->xbox360.dpad_right = 0;
        break;
    }

    return true;
  }
  else
  {
    return false;
  }
}