Further work on Playstation3 controller support

This commit is contained in:
Ingo Ruhnke 2011-01-22 16:31:56 +01:00
parent 6d7a3b8744
commit eca4762cbb
7 changed files with 474 additions and 37 deletions

1
NEWS
View file

@ -13,6 +13,7 @@ xboxdrv 0.6.5 - (??/Jan/2011)
* renamed --ui-new to --next
* renamed --ui-toggle to --toggle
* fixed incorrect endpoint detection for Xbox1 controller
* native Playstation 3 USB controller support
xboxdrv 0.6.4 - (13/Jan/2011)

2
TODO
View file

@ -141,6 +141,8 @@ round=X1:Y1
Stuff to do before 0.7.x release:
=================================
* get rid of set_button()/get_button(), turn the message objects into full classes
* document common problems, such as lack of deadzone handling in games
* give a warning when the user uses X as axis, instead of X1 (X is the

View file

@ -92,32 +92,32 @@ Playstation3USBController::read(XboxGenericMsg& msg, bool verbose, int timeout)
}
else
{
if (true)
msg.type = XBOX_MSG_PS3USB;
memcpy(&msg.ps3usb, data, sizeof(msg.ps3usb));
bitswap(msg.ps3usb.accl_x);
bitswap(msg.ps3usb.accl_y);
bitswap(msg.ps3usb.accl_z);
if (false)
{
Playstation3Msg ps3_msg;
memcpy(&ps3_msg, data, sizeof(ps3_msg));
bitswap(ps3_msg.accl_x);
bitswap(ps3_msg.accl_y);
bitswap(ps3_msg.accl_z);
if (false)
{
std::cout << boost::format("X:%5d Y:%5d Z:%5d\n")
% (static_cast<int>(ps3_msg.accl_x) - 512)
% (static_cast<int>(ps3_msg.accl_y) - 512)
% (static_cast<int>(ps3_msg.accl_z) - 512);
% (static_cast<int>(msg.ps3usb.accl_x) - 512)
% (static_cast<int>(msg.ps3usb.accl_y) - 512)
% (static_cast<int>(msg.ps3usb.accl_z) - 512);
}
else
else if (false)
{
std::cout << boost::format("X:%6.3f Y:%6.3f Z:%6.3f\n")
% ((static_cast<int>(ps3_msg.accl_x) - 512) / 116.0f)
% ((static_cast<int>(ps3_msg.accl_y) - 512) / 116.0f)
% ((static_cast<int>(ps3_msg.accl_z) - 512) / 116.0f);
% ((static_cast<int>(msg.ps3usb.accl_x) - 512) / 116.0f)
% ((static_cast<int>(msg.ps3usb.accl_y) - 512) / 116.0f)
% ((static_cast<int>(msg.ps3usb.accl_z) - 512) / 116.0f);
}
// -116 is gravity
}
else
else if (false)
{
std::cout << len << ": ";
for(int i = 0; i < len; ++i)
@ -127,7 +127,8 @@ Playstation3USBController::read(XboxGenericMsg& msg, bool verbose, int timeout)
}
std::cout << std::endl;
}
return false;
return true;
}
}

View file

@ -22,6 +22,22 @@
#include "uinput.hpp"
namespace {
// FIXME: duplicate code
int16_t u8_to_s16(uint8_t value)
{
// FIXME: verify this
if (value < 128)
{
return -32768 + (value * 32768 / 128);
}
else
{
return (value-128) * 32767 / 127;
}
}
} // namespace
UInputConfig::UInputConfig(uInput& uinput, const UInputOptions& opts) :
m_uinput(uinput),
m_btn_map(opts.get_btn_map()),
@ -49,6 +65,10 @@ UInputConfig::send(XboxGenericMsg& msg)
case XBOX_MSG_XBOX360:
send(msg.xbox360);
break;
case XBOX_MSG_PS3USB:
send(msg.ps3usb);
break;
default:
std::cout << "XboxGenericMsg type: " << msg.type << std::endl;
@ -172,6 +192,66 @@ UInputConfig::send(XboxMsg& msg)
send_axis(XBOX_AXIS_WHITE, msg.white);
}
void
UInputConfig::send(Playstation3USBMsg& msg)
{
// analog stick button
send_button(XBOX_BTN_THUMB_L, msg.l3);
send_button(XBOX_BTN_THUMB_R, msg.r3);
// start/back button
send_button(XBOX_BTN_START, msg.start);
send_button(XBOX_BTN_GUIDE, msg.playstation);
send_button(XBOX_BTN_BACK, msg.select);
// face button
send_button(XBOX_BTN_A, msg.cross);
send_button(XBOX_BTN_B, msg.circle);
send_button(XBOX_BTN_X, msg.square);
send_button(XBOX_BTN_Y, msg.triangle);
send_button(XBOX_BTN_LB, msg.l1);
send_button(XBOX_BTN_RB, msg.r1);
// trigger
send_button(XBOX_BTN_LT, msg.l2);
send_button(XBOX_BTN_RT, msg.r2);
// dpad as button
send_button(XBOX_DPAD_UP, msg.dpad_up);
send_button(XBOX_DPAD_DOWN, msg.dpad_down);
send_button(XBOX_DPAD_LEFT, msg.dpad_left);
send_button(XBOX_DPAD_RIGHT, msg.dpad_right);
send_axis(XBOX_AXIS_LT, msg.a_l2);
send_axis(XBOX_AXIS_RT, msg.a_r2);
send_axis(XBOX_AXIS_TRIGGER, (int(msg.a_r2) - int(msg.a_l1)));
// analog sticks
send_axis(XBOX_AXIS_X1, u8_to_s16(msg.x1));
send_axis(XBOX_AXIS_Y1, u8_to_s16(msg.y1));
send_axis(XBOX_AXIS_X2, u8_to_s16(msg.x2));
send_axis(XBOX_AXIS_Y2, u8_to_s16(msg.y2));
// dpad as axis
if (msg.dpad_up) send_axis(XBOX_AXIS_DPAD_Y, -1);
else if (msg.dpad_down) send_axis(XBOX_AXIS_DPAD_Y, 1);
else send_axis(XBOX_AXIS_DPAD_Y, 0);
if (msg.dpad_left) send_axis(XBOX_AXIS_DPAD_X, -1);
else if (msg.dpad_right) send_axis(XBOX_AXIS_DPAD_X, 1);
else send_axis(XBOX_AXIS_DPAD_X, 0);
send_axis(XBOX_AXIS_A, msg.a_cross);
send_axis(XBOX_AXIS_B, msg.a_circle);
send_axis(XBOX_AXIS_X, msg.a_square);
send_axis(XBOX_AXIS_Y, msg.a_triangle);
send_axis(XBOX_AXIS_BLACK, msg.a_l1);
send_axis(XBOX_AXIS_WHITE, msg.a_r1);
}
void
UInputConfig::update(int msec_delta)
{

View file

@ -26,6 +26,7 @@
struct Xbox360Msg;
struct XboxGenericMsg;
struct Playstation3USBMsg;
struct XboxMsg;
class UInputOptions;
@ -53,6 +54,7 @@ public:
private:
void send(Xbox360Msg& msg);
void send(XboxMsg& msg);
void send(Playstation3USBMsg& msg);
void send_button(XboxButton code, bool value);
void send_axis(XboxAxis code, int32_t value);

View file

@ -22,6 +22,19 @@
#include "helper.hpp"
#include "options.hpp"
int16_t u8_to_s16(uint8_t value)
{
// FIXME: verify this
if (value < 128)
{
return -32768 + (value * 32768 / 128);
}
else
{
return (value-128) * 32767 / 127;
}
}
std::string gamepadtype_to_string(const GamepadType& type)
{
@ -130,12 +143,51 @@ std::ostream& operator<<(std::ostream& out, const XboxGenericMsg& msg)
case XBOX_MSG_XBOX360:
return out << msg.xbox360;
case XBOX_MSG_PS3USB:
return out << msg.ps3usb;
default:
return out << "Error: Unhandled XboxGenericMsg type: " << msg.type;
}
}
std::ostream& operator<<(std::ostream& out, const Playstation3USBMsg& msg)
{
out << boost::format("X1:%3d Y1:%3d")
% int(msg.x1) % int(msg.y1);
out << boost::format(" X2:%3d Y2:%3d")
% int(msg.x2) % int(msg.y2);
out << boost::format(" du:%3d dd:%3d dl:%3d dr:%3d")
% int(msg.a_dpad_up)
% int(msg.a_dpad_down)
% int(msg.a_dpad_left)
% int(msg.a_dpad_right);
out << " select:" << msg.select;
out << " ps:" << msg.playstation;
out << " start:" << msg.start;
out << boost::format(" L3:%d R3:%d") % static_cast<int>(msg.l3) % static_cast<int>(msg.r3);
out << boost::format(" /\\:%3d O:%3d X:%3d []:%3d L1:%3d R1:%3d")
% static_cast<int>(msg.a_triangle)
% static_cast<int>(msg.a_circle)
% static_cast<int>(msg.a_cross)
% static_cast<int>(msg.a_square)
% static_cast<int>(msg.a_l1)
% static_cast<int>(msg.a_r1);
// FIXME: include analog buttons to
out << boost::format(" L2:%3d R2:%3d")
% int(msg.a_l2) % int(msg.a_r2);
return out;
}
std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg)
{
out << boost::format("X1:%6d Y1:%6d")
@ -279,6 +331,37 @@ int get_button(XboxGenericMsg& msg, XboxButton button)
case XBOX_BTN_UNKNOWN: return 0;
}
break;
case XBOX_MSG_PS3USB:
switch(button)
{
case XBOX_BTN_START: return msg.ps3usb.start;
case XBOX_BTN_GUIDE: return msg.ps3usb.playstation;
case XBOX_BTN_BACK: return msg.ps3usb.select;
case XBOX_BTN_A: return msg.ps3usb.cross;
case XBOX_BTN_B: return msg.ps3usb.circle;
case XBOX_BTN_X: return msg.ps3usb.square;
case XBOX_BTN_Y: return msg.ps3usb.triangle;
case XBOX_BTN_LB: return msg.ps3usb.l1;
case XBOX_BTN_RB: return msg.ps3usb.r1;
case XBOX_BTN_LT: return msg.ps3usb.l2;
case XBOX_BTN_RT: return msg.ps3usb.r2;
case XBOX_BTN_THUMB_L: return msg.ps3usb.l3;
case XBOX_BTN_THUMB_R: return msg.ps3usb.r3;
case XBOX_DPAD_UP: return msg.ps3usb.dpad_up;
case XBOX_DPAD_DOWN: return msg.ps3usb.dpad_down;
case XBOX_DPAD_LEFT: return msg.ps3usb.dpad_left;
case XBOX_DPAD_RIGHT: return msg.ps3usb.dpad_right;
case XBOX_BTN_MAX:
case XBOX_BTN_UNKNOWN: return 0;
}
break;
}
return 0;
}
@ -349,6 +432,38 @@ void set_button(XboxGenericMsg& msg, XboxButton button, bool v)
break;
}
break;
case XBOX_MSG_PS3USB:
switch(button)
{
case XBOX_BTN_START: msg.ps3usb.start = v; break;
case XBOX_BTN_GUIDE: msg.ps3usb.playstation = v; break;
case XBOX_BTN_BACK: msg.ps3usb.select = v; break;
case XBOX_BTN_A: msg.ps3usb.cross = v; break;
case XBOX_BTN_B: msg.ps3usb.circle = v; break;
case XBOX_BTN_X: msg.ps3usb.square = v; break;
case XBOX_BTN_Y: msg.ps3usb.triangle = v; break;
case XBOX_BTN_LB: msg.ps3usb.l1 = v; break;
case XBOX_BTN_RB: msg.ps3usb.r1 = v; break;
case XBOX_BTN_LT: msg.ps3usb.l2 = v; break;
case XBOX_BTN_RT: msg.ps3usb.r2 = v; break;
case XBOX_BTN_THUMB_L: msg.ps3usb.l3 = v; break;
case XBOX_BTN_THUMB_R: msg.ps3usb.r3 = v; break;
case XBOX_DPAD_UP: msg.ps3usb.dpad_up = v; break;
case XBOX_DPAD_DOWN: msg.ps3usb.dpad_down = v; break;
case XBOX_DPAD_LEFT: msg.ps3usb.dpad_left = v; break;
case XBOX_DPAD_RIGHT: msg.ps3usb.dpad_right = v; break;
case XBOX_BTN_MAX:
case XBOX_BTN_UNKNOWN:
break;
}
break;
}
}
@ -462,6 +577,59 @@ int get_axis(XboxGenericMsg& msg, XboxAxis axis)
case XBOX_AXIS_WHITE: return msg.xbox.white;
}
break;
case XBOX_MSG_PS3USB:
switch(axis)
{
case XBOX_AXIS_MAX:
case XBOX_AXIS_UNKNOWN:
break;
case XBOX_AXIS_DPAD_X:
if (msg.ps3usb.dpad_left)
{
return -1;
}
else if (msg.ps3usb.dpad_right)
{
return 1;
}
else
{
return 0;
}
case XBOX_AXIS_DPAD_Y:
if (msg.ps3usb.dpad_up)
{
return -1;
}
else if (msg.ps3usb.dpad_down)
{
return 1;
}
else
{
return 0;
}
case XBOX_AXIS_TRIGGER: return msg.ps3usb.a_r2 - msg.ps3usb.a_l2;
case XBOX_AXIS_X1: return u8_to_s16(msg.ps3usb.x1);
case XBOX_AXIS_Y1: return u8_to_s16(msg.ps3usb.y1);
case XBOX_AXIS_X2: return u8_to_s16(msg.ps3usb.x2);
case XBOX_AXIS_Y2: return u8_to_s16(msg.ps3usb.y2);
case XBOX_AXIS_LT: return msg.ps3usb.a_l2;
case XBOX_AXIS_RT: return msg.ps3usb.a_r2;
case XBOX_AXIS_A: return msg.ps3usb.a_cross;
case XBOX_AXIS_B: return msg.ps3usb.a_circle;
case XBOX_AXIS_X: return msg.ps3usb.a_square;
case XBOX_AXIS_Y: return msg.ps3usb.a_triangle;
case XBOX_AXIS_BLACK: return msg.ps3usb.a_l1;
case XBOX_AXIS_WHITE: return msg.ps3usb.a_r1;
}
break;
}
return 0;
}
@ -486,6 +654,7 @@ float u8_to_float(uint8_t value)
{
return static_cast<float>(value) / 255.0f * 2.0f - 1.0f;
}
int16_t float_to_s16(float v)
{
@ -617,6 +786,58 @@ float get_axis_float(XboxGenericMsg& msg, XboxAxis axis)
case XBOX_AXIS_WHITE: return u8_to_float(msg.xbox.white);
}
break;
case XBOX_MSG_PS3USB:
switch(axis)
{
case XBOX_AXIS_MAX:
case XBOX_AXIS_UNKNOWN:
break;
case XBOX_AXIS_DPAD_X:
if (msg.ps3usb.dpad_left)
{
return -1.0f;
}
else if (msg.ps3usb.dpad_right)
{
return 1.0f;
}
else
{
return 0.0f;
}
case XBOX_AXIS_DPAD_Y:
if (msg.ps3usb.dpad_up)
{
return -1.0f;
}
else if (msg.ps3usb.dpad_down)
{
return 1.0f;
}
else
{
return 0.0f;
}
case XBOX_AXIS_TRIGGER: return static_cast<float>(msg.ps3usb.r2 - msg.ps3usb.l2)/512.0f;
case XBOX_AXIS_X1: return u8_to_float(msg.ps3usb.x1);
case XBOX_AXIS_Y1: return u8_to_float(msg.ps3usb.y1);
case XBOX_AXIS_X2: return u8_to_float(msg.ps3usb.x2);
case XBOX_AXIS_Y2: return u8_to_float(msg.ps3usb.y2);
case XBOX_AXIS_LT: return u8_to_float(msg.ps3usb.a_l2);
case XBOX_AXIS_RT: return u8_to_float(msg.ps3usb.a_r2);
case XBOX_AXIS_A: return u8_to_float(msg.ps3usb.a_cross);
case XBOX_AXIS_B: return u8_to_float(msg.ps3usb.a_circle);
case XBOX_AXIS_X: return u8_to_float(msg.ps3usb.a_square);
case XBOX_AXIS_Y: return u8_to_float(msg.ps3usb.a_triangle);
case XBOX_AXIS_BLACK: return u8_to_float(msg.ps3usb.a_l1);
case XBOX_AXIS_WHITE: return u8_to_float(msg.ps3usb.a_r1);
}
}
return 0;
}
@ -744,12 +965,76 @@ void set_axis_float(XboxGenericMsg& msg, XboxAxis axis, float v)
case XBOX_AXIS_LT: msg.xbox.lt = float_to_u8(v); break;
case XBOX_AXIS_RT: msg.xbox.rt = float_to_u8(v); break;
case XBOX_AXIS_A: msg.xbox.a = float_to_u8(v);
case XBOX_AXIS_B: msg.xbox.b = float_to_u8(v);
case XBOX_AXIS_X: msg.xbox.x = float_to_u8(v);
case XBOX_AXIS_Y: msg.xbox.y = float_to_u8(v);
case XBOX_AXIS_BLACK: msg.xbox.black = float_to_u8(v);
case XBOX_AXIS_WHITE: msg.xbox.white = float_to_u8(v);
case XBOX_AXIS_A: msg.xbox.a = float_to_u8(v); break;
case XBOX_AXIS_B: msg.xbox.b = float_to_u8(v); break;
case XBOX_AXIS_X: msg.xbox.x = float_to_u8(v); break;
case XBOX_AXIS_Y: msg.xbox.y = float_to_u8(v); break;
case XBOX_AXIS_BLACK: msg.xbox.black = float_to_u8(v); break;
case XBOX_AXIS_WHITE: msg.xbox.white = float_to_u8(v); break;
}
break;
case XBOX_MSG_PS3USB:
switch(axis)
{
case XBOX_AXIS_MAX:
case XBOX_AXIS_UNKNOWN:
break;
case XBOX_AXIS_TRIGGER:
msg.ps3usb.a_l2 = v < 0 ? int(v*255) : 0;
msg.ps3usb.a_r2 = v > 0 ? int(v*255) : 0;
break;
case XBOX_AXIS_DPAD_X:
if (v > 0.5f)
{
msg.ps3usb.dpad_left = false;
msg.ps3usb.dpad_right = true;
}
else if (v < -0.5f)
{
msg.ps3usb.dpad_left = true;
msg.ps3usb.dpad_right = false;
}
else
{
msg.ps3usb.dpad_left = false;
msg.ps3usb.dpad_right = false;
}
break;
case XBOX_AXIS_DPAD_Y:
if (v > 0.5f)
{
msg.ps3usb.dpad_up = false;
msg.ps3usb.dpad_down = true;
}
else if (v < -0.5f)
{
msg.ps3usb.dpad_up = true;
msg.ps3usb.dpad_down = false;
}
else
{
msg.ps3usb.dpad_down = false;
msg.ps3usb.dpad_up = false;
}
break;
case XBOX_AXIS_X1: msg.ps3usb.x1 = float_to_s16(v); break;
case XBOX_AXIS_Y1: msg.ps3usb.y1 = float_to_s16(v); break;
case XBOX_AXIS_X2: msg.ps3usb.x2 = float_to_s16(v); break;
case XBOX_AXIS_Y2: msg.ps3usb.y2 = float_to_s16(v); break;
case XBOX_AXIS_LT: msg.ps3usb.a_l2 = float_to_u8(v); break;
case XBOX_AXIS_RT: msg.ps3usb.a_r2 = float_to_u8(v); break;
case XBOX_AXIS_A: msg.ps3usb.a_cross = float_to_u8(v); break;
case XBOX_AXIS_B: msg.ps3usb.a_circle = float_to_u8(v); break;
case XBOX_AXIS_X: msg.ps3usb.a_square = float_to_u8(v); break;
case XBOX_AXIS_Y: msg.ps3usb.a_triangle = float_to_u8(v); break;
case XBOX_AXIS_BLACK: msg.ps3usb.a_l1 = float_to_u8(v); break;
case XBOX_AXIS_WHITE: msg.ps3usb.a_r1 = float_to_u8(v); break;
}
break;
}
@ -886,6 +1171,70 @@ void set_axis(XboxGenericMsg& msg, XboxAxis axis, int v)
case XBOX_AXIS_WHITE: msg.xbox.white = v; break;
}
break;
case XBOX_MSG_PS3USB:
switch(axis)
{
case XBOX_AXIS_MAX:
case XBOX_AXIS_UNKNOWN:
break;
case XBOX_AXIS_TRIGGER:
msg.ps3usb.a_l2 = v < 0 ? v : 0;
msg.ps3usb.a_r2 = v > 0 ? v : 0;
break;
case XBOX_AXIS_DPAD_X:
if (v > 0)
{
msg.ps3usb.dpad_left = false;
msg.ps3usb.dpad_right = true;
}
else if (v < 0)
{
msg.ps3usb.dpad_left = true;
msg.ps3usb.dpad_right = false;
}
else
{
msg.ps3usb.dpad_left = false;
msg.ps3usb.dpad_right = false;
}
break;
case XBOX_AXIS_DPAD_Y:
if (v > 0)
{
msg.ps3usb.dpad_up = false;
msg.ps3usb.dpad_down = true;
}
else if (v < 0)
{
msg.ps3usb.dpad_up = true;
msg.ps3usb.dpad_down = false;
}
else
{
msg.ps3usb.dpad_down = false;
msg.ps3usb.dpad_up = false;
}
break;
case XBOX_AXIS_X1: msg.ps3usb.x1 = v; break;
case XBOX_AXIS_Y1: msg.ps3usb.y1 = v; break;
case XBOX_AXIS_X2: msg.ps3usb.x2 = v; break;
case XBOX_AXIS_Y2: msg.ps3usb.y2 = v; break;
case XBOX_AXIS_LT: msg.ps3usb.a_l2 = v; break;
case XBOX_AXIS_RT: msg.ps3usb.a_r2 = v; break;
case XBOX_AXIS_A: msg.ps3usb.a_cross = v; break;
case XBOX_AXIS_B: msg.ps3usb.a_circle = v; break;
case XBOX_AXIS_X: msg.ps3usb.a_square = v; break;
case XBOX_AXIS_Y: msg.ps3usb.a_triangle = v; break;
case XBOX_AXIS_BLACK: msg.ps3usb.a_l1 = v; break;
case XBOX_AXIS_WHITE: msg.ps3usb.a_r1 = v; break;
}
break;
}
}

View file

@ -37,7 +37,8 @@ enum GamepadType {
enum XboxMsgType {
XBOX_MSG_XBOX,
XBOX_MSG_XBOX360
XBOX_MSG_XBOX360,
XBOX_MSG_PS3USB
};
struct Xbox360Msg
@ -124,36 +125,36 @@ struct XboxMsg
int y2 :16;
} __attribute__((__packed__));
struct Playstation3Msg
struct Playstation3USBMsg
{
unsigned int unknown00 :8; // always 01
unsigned int unknown01 :8; // always 00
// 02
unsigned int dpad_up :1;
unsigned int dpad_right :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
unsigned int select :1;
unsigned int l3 :1;
unsigned int r3 :1;
unsigned int start :1;
// 03
unsigned int triangle :1;
unsigned int circle :1;
unsigned int cross :1;
unsigned int square :1;
unsigned int dpad_up :1;
unsigned int dpad_right :1;
unsigned int dpad_down :1;
unsigned int dpad_left :1;
// 03
unsigned int l2 :1;
unsigned int r2 :1;
unsigned int l1 :1;
unsigned int r1 :1;
unsigned int triangle :1;
unsigned int circle :1;
unsigned int cross :1;
unsigned int square :1;
// 04
unsigned int unknown04 :7;
unsigned int playstation :1;
unsigned int unknown04 :7;
unsigned int unknown05 :8; // always 00
@ -215,13 +216,14 @@ struct XboxGenericMsg
union {
struct Xbox360Msg xbox360;
struct XboxMsg xbox;
struct Playstation3Msg ps3;
struct Playstation3USBMsg ps3usb;
};
};
std::ostream& operator<<(std::ostream& out, const GamepadType& type);
std::ostream& operator<<(std::ostream& out, const Xbox360Msg& msg);
std::ostream& operator<<(std::ostream& out, const XboxMsg& msg);
std::ostream& operator<<(std::ostream& out, const Playstation3USBMsg& msg);
std::ostream& operator<<(std::ostream& out, const XboxGenericMsg& msg);
enum XboxButton {