Fixed nunchuk controller support, it was not correctly detected.

Fixed classic controller's analogs, were not working at all.
Restored sixaxis controller support, now with completely rewroten library.
Changed detection order (GC, Sixaxis, Wiimote/Nunchuck/Classic, left wiimote at the end, otherwise we needed to disconnect it to be able to use GC controller or sixaxis controller.
This commit is contained in:
Jose Ernesto Ramirez Ramirez 2015-07-13 22:58:01 -05:00
parent 6001d6bacd
commit 09f3c3ca77
6 changed files with 465 additions and 619 deletions

View File

@ -122,7 +122,7 @@ HAVE_7ZIP := 1
HAVE_RPNG := 1
HAVE_RPNG := 1
HAVE_OVERLAY := 1
HAVE_LIBSICKSAXIS := 0
HAVE_LIBSICKSAXIS := 1
HAVE_BUILTIN_AUTOCONFIG := 1
else ifeq ($(platform), psp1)
CC = psp-gcc$(EXE_EXT)

View File

@ -22,13 +22,13 @@ DECL_BTN(b, 1) \
DECL_BTN(x, 2) \
DECL_BTN(y, 3) \
DECL_BTN(start, 4) \
DECL_BTN(select, 5) \
DECL_BTN(up, 8) \
DECL_BTN(down, 9) \
DECL_BTN(left, 10) \
DECL_BTN(right, 11) \
DECL_BTN(l, 6) \
DECL_BTN(r, 7) \
DECL_BTN(select, 6) \
DECL_BTN(up, 9) \
DECL_BTN(down, 10) \
DECL_BTN(left, 11) \
DECL_BTN(right, 12) \
DECL_BTN(l, 7) \
DECL_BTN(r, 8) \
DECL_AXIS(l_x_plus, +0) \
DECL_AXIS(l_x_minus, -0) \
DECL_AXIS(l_y_plus, +1) \
@ -39,50 +39,50 @@ DECL_AXIS(r_y_plus, -3) \
DECL_AXIS(r_y_minus, +3)
#define GXINPUT_WIIMOTE_DEFAULT_BINDS \
DECL_BTN(a, 46) \
DECL_BTN(b, 45) \
DECL_BTN(x, 45) \
DECL_BTN(y, 43) \
DECL_BTN(start, 47) \
DECL_BTN(select, 48) \
DECL_BTN(up, 50) \
DECL_BTN(down, 51) \
DECL_BTN(left, 52) \
DECL_BTN(right, 53)
DECL_BTN(a, 31) \
DECL_BTN(b, 30) \
DECL_BTN(x, 29) \
DECL_BTN(y, 28) \
DECL_BTN(start, 32) \
DECL_BTN(select, 33) \
DECL_BTN(up, 35) \
DECL_BTN(down, 36) \
DECL_BTN(left, 37) \
DECL_BTN(right, 38)
#define GXINPUT_NUNCHUK_DEFAULT_BINDS \
DECL_BTN(a, 43) \
DECL_BTN(b, 44) \
DECL_BTN(x, 45) \
DECL_BTN(y, 46) \
DECL_BTN(start, 47) \
DECL_BTN(select, 48) \
DECL_BTN(up, 50) \
DECL_BTN(down, 51) \
DECL_BTN(left, 52) \
DECL_BTN(right, 53) \
DECL_BTN(l, 54) \
DECL_BTN(r, 55) \
DECL_BTN(a, 28) \
DECL_BTN(b, 29) \
DECL_BTN(x, 30) \
DECL_BTN(y, 31) \
DECL_BTN(start, 32) \
DECL_BTN(select, 33) \
DECL_BTN(up, 35) \
DECL_BTN(down, 36) \
DECL_BTN(left, 37) \
DECL_BTN(right, 38) \
DECL_BTN(l, 39) \
DECL_BTN(r, 40) \
DECL_AXIS(l_x_plus, +0) \
DECL_AXIS(l_x_minus, -0) \
DECL_AXIS(l_y_plus, +1) \
DECL_AXIS(l_y_minus, -1)
#define GXINPUT_CLASSIC_DEFAULT_BINDS \
DECL_BTN(a, 20) \
DECL_BTN(b, 21) \
DECL_BTN(x, 22) \
DECL_BTN(y, 23) \
DECL_BTN(start, 24) \
DECL_BTN(select, 25) \
DECL_BTN(up, 31) \
DECL_BTN(down, 32) \
DECL_BTN(left, 33) \
DECL_BTN(right, 34) \
DECL_BTN(l, 27) \
DECL_BTN(r, 28) \
DECL_BTN(l2, 29) \
DECL_BTN(r2, 30) \
DECL_BTN(a, 13) \
DECL_BTN(b, 14) \
DECL_BTN(x, 15) \
DECL_BTN(y, 16) \
DECL_BTN(start, 17) \
DECL_BTN(select, 18) \
DECL_BTN(up, 24) \
DECL_BTN(down, 25) \
DECL_BTN(left, 26) \
DECL_BTN(right, 27) \
DECL_BTN(l, 20) \
DECL_BTN(r, 21) \
DECL_BTN(l2, 22) \
DECL_BTN(r2, 23) \
DECL_AXIS(l_x_plus, +0) \
DECL_AXIS(l_x_minus, -0) \
DECL_AXIS(l_y_plus, +1) \
@ -92,15 +92,44 @@ DECL_AXIS(r_x_minus, -2) \
DECL_AXIS(r_y_plus, -3) \
DECL_AXIS(r_y_minus, +3)
/* TODO: missing Libsicksaxis binds */
#ifdef HAVE_LIBSICKSAXIS
#define GXINPUT_SIXAXIS_DEFAULT_BINDS \
DECL_BTN(a, 45) \
DECL_BTN(b, 46) \
DECL_BTN(x, 47) \
DECL_BTN(y, 48) \
DECL_BTN(start, 55) \
DECL_BTN(select, 56) \
DECL_BTN(up, 58) \
DECL_BTN(down, 59) \
DECL_BTN(left, 60) \
DECL_BTN(right, 61) \
DECL_BTN(l, 49) \
DECL_BTN(r, 50) \
DECL_BTN(l2, 51) \
DECL_BTN(r2, 52) \
DECL_BTN(l3, 53) \
DECL_BTN(r3, 54) \
DECL_AXIS(l_x_plus, +0) \
DECL_AXIS(l_x_minus, -0) \
DECL_AXIS(l_y_plus, +1) \
DECL_AXIS(l_y_minus, -1) \
DECL_AXIS(r_x_plus, +2) \
DECL_AXIS(r_x_minus, -2) \
DECL_AXIS(r_y_plus, -3) \
DECL_AXIS(r_y_minus, +3)
#endif
const char* const input_builtin_autoconfs[] =
{
DECL_AUTOCONF_DEVICE("GameCube Controller", "gx", GXINPUT_GAMECUBE_DEFAULT_BINDS),
#ifdef HW_RVL
DECL_AUTOCONF_DEVICE("Wiimote Controller", "gx", GXINPUT_WIIMOTE_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("NunChuk Controller", "gx", GXINPUT_NUNCHUK_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Nunchuk Controller", "gx", GXINPUT_NUNCHUK_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Classic Controller", "gx", GXINPUT_CLASSIC_DEFAULT_BINDS),
#ifdef HAVE_LIBSICKSAXIS
DECL_AUTOCONF_DEVICE("Sixaxis Controller", "gx", GXINPUT_SIXAXIS_DEFAULT_BINDS),
#endif
#endif
NULL
};

View File

@ -64,51 +64,68 @@ enum
GX_GC_X = 2,
GX_GC_Y = 3,
GX_GC_START = 4,
GX_GC_Z_TRIGGER = 5,
GX_GC_L_TRIGGER = 6,
GX_GC_R_TRIGGER = 7,
GX_GC_UP = 8,
GX_GC_DOWN = 9,
GX_GC_LEFT = 10,
GX_GC_RIGHT = 11,
GX_GC_HOME = 5,/* needed on GameCube as "fake" menu button. */
GX_GC_Z_TRIGGER = 6,
GX_GC_L_TRIGGER = 7,
GX_GC_R_TRIGGER = 8,
GX_GC_UP = 9,
GX_GC_DOWN = 10,
GX_GC_LEFT = 11,
GX_GC_RIGHT = 12,
#ifdef HW_RVL
GX_CLASSIC_A = 20,
GX_CLASSIC_B = 21,
GX_CLASSIC_X = 22,
GX_CLASSIC_Y = 23,
GX_CLASSIC_PLUS = 24,
GX_CLASSIC_MINUS = 25,
GX_CLASSIC_HOME = 26,
GX_CLASSIC_L_TRIGGER = 27,
GX_CLASSIC_R_TRIGGER = 28,
GX_CLASSIC_ZL_TRIGGER = 29,
GX_CLASSIC_ZR_TRIGGER = 30,
GX_CLASSIC_UP = 31,
GX_CLASSIC_DOWN = 32,
GX_CLASSIC_LEFT = 33,
GX_CLASSIC_RIGHT = 34,
GX_WIIMOTE_A = 43,
GX_WIIMOTE_B = 44,
GX_WIIMOTE_1 = 45,
GX_WIIMOTE_2 = 46,
GX_WIIMOTE_PLUS = 47,
GX_WIIMOTE_MINUS = 48,
#if 0
GX_WIIMOTE_HOME = 49,
GX_CLASSIC_A = 13,
GX_CLASSIC_B = 14,
GX_CLASSIC_X = 15,
GX_CLASSIC_Y = 16,
GX_CLASSIC_PLUS = 17,
GX_CLASSIC_MINUS = 18,
GX_CLASSIC_HOME = 19,
GX_CLASSIC_L_TRIGGER = 20,
GX_CLASSIC_R_TRIGGER = 21,
GX_CLASSIC_ZL_TRIGGER = 22,
GX_CLASSIC_ZR_TRIGGER = 23,
GX_CLASSIC_UP = 24,
GX_CLASSIC_DOWN = 25,
GX_CLASSIC_LEFT = 26,
GX_CLASSIC_RIGHT = 27,
GX_WIIMOTE_A = 28,
GX_WIIMOTE_B = 29,
GX_WIIMOTE_1 = 30,
GX_WIIMOTE_2 = 31,
GX_WIIMOTE_PLUS = 32,
GX_WIIMOTE_MINUS = 33,
GX_WIIMOTE_HOME = 34,
GX_WIIMOTE_UP = 35,
GX_WIIMOTE_DOWN = 36,
GX_WIIMOTE_LEFT = 37,
GX_WIIMOTE_RIGHT = 38,
GX_NUNCHUK_Z = 39,
GX_NUNCHUK_C = 40,
GX_NUNCHUK_UP = 41,
GX_NUNCHUK_DOWN = 42,
GX_NUNCHUK_LEFT = 43,
GX_NUNCHUK_RIGHT = 44,
#ifdef HAVE_LIBSICKSAXIS
GX_SIXAXIS_CIRCLE = 45,
GX_SIXAXIS_CROSS = 46,
GX_SIXAXIS_TRIANGLE = 47,
GX_SIXAXIS_SQUARE = 48,
GX_SIXAXIS_L1 = 49,
GX_SIXAXIS_R1 = 50,
GX_SIXAXIS_L2 = 51,
GX_SIXAXIS_R2 = 52,
GX_SIXAXIS_L3 = 53,
GX_SIXAXIS_R3 = 54,
GX_SIXAXIS_START = 55,
GX_SIXAXIS_SELECT = 56,
GX_SIXAXIS_PS = 57,
GX_SIXAXIS_UP = 58,
GX_SIXAXIS_DOWN = 59,
GX_SIXAXIS_LEFT = 60,
GX_SIXAXIS_RIGHT = 61,
#endif
GX_WIIMOTE_UP = 50,
GX_WIIMOTE_DOWN = 51,
GX_WIIMOTE_LEFT = 52,
GX_WIIMOTE_RIGHT = 53,
GX_NUNCHUK_Z = 54,
GX_NUNCHUK_C = 55,
GX_NUNCHUK_UP = 56,
GX_NUNCHUK_DOWN = 57,
GX_NUNCHUK_LEFT = 58,
GX_NUNCHUK_RIGHT = 59,
#endif
GX_WIIMOTE_HOME = 49, /* needed on GameCube as "fake" menu button. */
GX_QUIT_KEY = 60,
GX_QUIT_KEY = 62,
};
#define GC_JOYSTICK_THRESHOLD (48 * 256)
@ -128,19 +145,8 @@ static void power_callback(void)
}
#ifdef HAVE_LIBSICKSAXIS
volatile int lol = 0;
struct ss_device dev[MAX_PADS];
int change_cb(int result, void *usrdata)
{
(*(volatile int*)usrdata)++;
return result;
}
void removal_cb(void *usrdata)
{
input_config_autoconfigure_disconnect((int)usrdata, gx_joypad.ident);
}
# define USB_SLOTS 1
struct ss_device sixaxis[USB_SLOTS];
#endif
#endif
@ -260,10 +266,10 @@ static int16_t gx_joypad_axis(unsigned port, uint32_t joyaxis)
#define PI 3.14159265f
#endif
static s8 WPAD_StickX(WPADData *data, u8 chan,u8 right)
static int16_t WPAD_StickX(WPADData *data, u8 right)
{
float mag = 0.0;
float ang = 0.0;
float mag = 0.0f;
float ang = 0.0f;
switch (data->exp.type)
{
@ -294,19 +300,19 @@ static s8 WPAD_StickX(WPADData *data, u8 chan,u8 right)
}
/* calculate X value (angle need to be converted into radian) */
if (mag > 1.0)
mag = 1.0;
else if (mag < -1.0)
mag = -1.0;
if (mag > 1.0f)
mag = 1.0f;
else if (mag < -1.0f)
mag = -1.0f;
double val = mag * sin(PI * ang/180.0f);
return (s8)(val * 128.0f);
return (int16_t)(val * 32767.0f);
}
static s8 WPAD_StickY(WPADData *data, u8 chan, u8 right)
static int16_t WPAD_StickY(WPADData *data, u8 right)
{
float mag = 0.0;
float ang = 0.0;
float mag = 0.0f;
float ang = 0.0f;
switch (data->exp.type)
{
@ -336,14 +342,14 @@ static s8 WPAD_StickY(WPADData *data, u8 chan, u8 right)
break;
}
/* calculate X value (angle need to be converted into radian) */
if (mag > 1.0)
mag = 1.0;
else if (mag < -1.0)
mag = -1.0;
double val = mag * cos(PI * ang/180.0f);
/* calculate Y value (angle need to be converted into radian) */
if (mag > 1.0f)
mag = 1.0f;
else if (mag < -1.0f)
mag = -1.0f;
double val = -mag * cos(PI * ang/180.0f);
return (s8)(val * 128.0f);
return (int16_t)(val * 32767.0f);
}
#endif
@ -368,16 +374,89 @@ static void gx_joypad_poll(void)
uint32_t down = 0, ptype = WPAD_EXP_NOCONTROLLER;
uint64_t *state_cur = &pad_state[port];
if (gcpad & (1 << port))
{
int16_t ls_x, ls_y, rs_x, rs_y;
uint64_t menu_combo = 0;
down = PAD_ButtonsHeld(port);
*state_cur |= (down & PAD_BUTTON_A) ? (UINT64_C(1) << GX_GC_A) : 0;
*state_cur |= (down & PAD_BUTTON_B) ? (UINT64_C(1) << GX_GC_B) : 0;
*state_cur |= (down & PAD_BUTTON_X) ? (UINT64_C(1) << GX_GC_X) : 0;
*state_cur |= (down & PAD_BUTTON_Y) ? (UINT64_C(1) << GX_GC_Y) : 0;
*state_cur |= (down & PAD_BUTTON_UP) ? (UINT64_C(1) << GX_GC_UP) : 0;
*state_cur |= (down & PAD_BUTTON_DOWN) ? (UINT64_C(1) << GX_GC_DOWN) : 0;
*state_cur |= (down & PAD_BUTTON_LEFT) ? (UINT64_C(1) << GX_GC_LEFT) : 0;
*state_cur |= (down & PAD_BUTTON_RIGHT) ? (UINT64_C(1) << GX_GC_RIGHT) : 0;
*state_cur |= (down & PAD_BUTTON_START) ? (UINT64_C(1) << GX_GC_START) : 0;
*state_cur |= (down & PAD_TRIGGER_Z) ? (UINT64_C(1) << GX_GC_Z_TRIGGER) : 0;
*state_cur |= ((down & PAD_TRIGGER_L) || PAD_TriggerL(port) > 127) ? (UINT64_C(1) << GX_GC_L_TRIGGER) : 0;
*state_cur |= ((down & PAD_TRIGGER_R) || PAD_TriggerR(port) > 127) ? (UINT64_C(1) << GX_GC_R_TRIGGER) : 0;
ls_x = (int16_t)PAD_StickX(port) * 256;
ls_y = (int16_t)PAD_StickY(port) * -256;
rs_x = (int16_t)PAD_SubStickX(port) * 256;
rs_y = (int16_t)PAD_SubStickY(port) * -256;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = ls_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = ls_y;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = rs_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = rs_y;
menu_combo = (UINT64_C(1) << GX_GC_START) | (UINT64_C(1) << GX_GC_Z_TRIGGER) |
(UINT64_C(1) << GX_GC_L_TRIGGER) | (UINT64_C(1) << GX_GC_R_TRIGGER);
if ((*state_cur & menu_combo) == menu_combo)
*state_cur |= (UINT64_C(1) << GX_GC_HOME);
ptype = WPAD_EXP_GAMECUBE;
}
#ifdef HW_RVL
if (WPADProbe(port, &ptype) == WPAD_ERR_NONE)
#ifdef HAVE_LIBSICKSAXIS
else if (port < USB_SLOTS && ss_is_ready(&sixaxis[port]))/* Only defined 1 port for now */
{
int16_t ls_x, ls_y, rs_x, rs_y;
ss_read_pad(&sixaxis[port]);
*state_cur |= (sixaxis[port].pad.buttons.PS) ? (UINT64_C(1) << GX_SIXAXIS_PS) : 0;
*state_cur |= (sixaxis[port].pad.buttons.cross) ? (UINT64_C(1) << GX_SIXAXIS_CROSS) : 0;
*state_cur |= (sixaxis[port].pad.buttons.square) ? (UINT64_C(1) << GX_SIXAXIS_SQUARE) : 0;
*state_cur |= (sixaxis[port].pad.buttons.select) ? (UINT64_C(1) << GX_SIXAXIS_SELECT) : 0;
*state_cur |= (sixaxis[port].pad.buttons.start) ? (UINT64_C(1) << GX_SIXAXIS_START) : 0;
*state_cur |= (sixaxis[port].pad.buttons.up) ? (UINT64_C(1) << GX_SIXAXIS_UP) : 0;
*state_cur |= (sixaxis[port].pad.buttons.down) ? (UINT64_C(1) << GX_SIXAXIS_DOWN) : 0;
*state_cur |= (sixaxis[port].pad.buttons.left) ? (UINT64_C(1) << GX_SIXAXIS_LEFT) : 0;
*state_cur |= (sixaxis[port].pad.buttons.right) ? (UINT64_C(1) << GX_SIXAXIS_RIGHT) : 0;
*state_cur |= (sixaxis[port].pad.buttons.circle) ? (UINT64_C(1) << GX_SIXAXIS_CIRCLE) : 0;
*state_cur |= (sixaxis[port].pad.buttons.triangle) ? (UINT64_C(1) << GX_SIXAXIS_TRIANGLE) : 0;
*state_cur |= (sixaxis[port].pad.buttons.L1) ? (UINT64_C(1) << GX_SIXAXIS_L1) : 0;
*state_cur |= (sixaxis[port].pad.buttons.R1) ? (UINT64_C(1) << GX_SIXAXIS_R1) : 0;
*state_cur |= (sixaxis[port].pad.buttons.L2) ? (UINT64_C(1) << GX_SIXAXIS_L2) : 0;
*state_cur |= (sixaxis[port].pad.buttons.R2) ? (UINT64_C(1) << GX_SIXAXIS_R2) : 0;
*state_cur |= (sixaxis[port].pad.buttons.L3) ? (UINT64_C(1) << GX_SIXAXIS_L3) : 0;
*state_cur |= (sixaxis[port].pad.buttons.R3) ? (UINT64_C(1) << GX_SIXAXIS_R3) : 0;
ls_x = (int16_t)(sixaxis[port].pad.left_analog.x - 128) << 8;
ls_y = (int16_t)(sixaxis[port].pad.left_analog.y - 128) << 8;
rs_x = (int16_t)(sixaxis[port].pad.right_analog.x - 128) << 8;
rs_y = (int16_t)(sixaxis[port].pad.right_analog.y - 128) << 8;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = ls_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = ls_y;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = rs_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = rs_y;
ptype = WPAD_EXP_SICKSAXIS;
}
#endif
else if (WPADProbe(port, &ptype) == WPAD_ERR_NONE)
{
WPADData *wpaddata = (WPADData*)WPAD_Data(port);
expansion_t *exp = NULL;
down = wpaddata->btns_h;
exp = (expansion_t*)&wpaddata->exp;
*state_cur |= (down & WPAD_BUTTON_A) ? (UINT64_C(1) << GX_WIIMOTE_A) : 0;
*state_cur |= (down & WPAD_BUTTON_B) ? (UINT64_C(1) << GX_WIIMOTE_B) : 0;
*state_cur |= (down & WPAD_BUTTON_1) ? (UINT64_C(1) << GX_WIIMOTE_1) : 0;
@ -395,7 +474,6 @@ static void gx_joypad_poll(void)
*state_cur |= (down & WPAD_BUTTON_RIGHT) ? (UINT64_C(1) << GX_WIIMOTE_UP) : 0;
}
if (ptype == WPAD_EXP_CLASSIC)
{
*state_cur |= (down & WPAD_CLASSIC_BUTTON_A) ? (UINT64_C(1) << GX_CLASSIC_A) : 0;
@ -414,10 +492,10 @@ static void gx_joypad_poll(void)
*state_cur |= (down & WPAD_CLASSIC_BUTTON_ZL) ? (UINT64_C(1) << GX_CLASSIC_ZL_TRIGGER) : 0;
*state_cur |= (down & WPAD_CLASSIC_BUTTON_ZR) ? (UINT64_C(1) << GX_CLASSIC_ZR_TRIGGER) : 0;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = WPAD_StickX(wpaddata, port, 0);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = WPAD_StickY(wpaddata, port, 0);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = WPAD_StickX(wpaddata, port, 1);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = WPAD_StickY(wpaddata, port, 1);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = WPAD_StickX(wpaddata, 0);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = WPAD_StickY(wpaddata, 0);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = WPAD_StickX(wpaddata, 1);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = WPAD_StickY(wpaddata, 1);
}
else if (ptype == WPAD_EXP_NUNCHUK)
{
@ -431,104 +509,11 @@ static void gx_joypad_poll(void)
*state_cur |= (down & WPAD_NUNCHUK_BUTTON_Z) ? (UINT64_C(1) << GX_NUNCHUK_Z) : 0;
*state_cur |= (down & WPAD_NUNCHUK_BUTTON_C) ? (UINT64_C(1) << GX_NUNCHUK_C) : 0;
float js_mag = exp->nunchuk.js.mag;
float js_ang = exp->nunchuk.js.ang;
if (js_mag > 1.0f)
js_mag = 1.0f;
else if (js_mag < -1.0f)
js_mag = -1.0f;
double js_val_x = js_mag * sin(M_PI * js_ang / 180.0);
double js_val_y = -js_mag * cos(M_PI * js_ang / 180.0);
int16_t x = (int16_t)(js_val_x * 32767.0f);
int16_t y = (int16_t)(js_val_y * 32767.0f);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = y;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = WPAD_StickX(wpaddata, 0);
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = WPAD_StickY(wpaddata, 0);
}
}
else
#endif
{
if (gcpad & (1 << port))
{
int16_t ls_x, ls_y, rs_x, rs_y;
uint64_t menu_combo = 0;
down = PAD_ButtonsHeld(port);
*state_cur |= (down & PAD_BUTTON_A) ? (UINT64_C(1) << GX_GC_A) : 0;
*state_cur |= (down & PAD_BUTTON_B) ? (UINT64_C(1) << GX_GC_B) : 0;
*state_cur |= (down & PAD_BUTTON_X) ? (UINT64_C(1) << GX_GC_X) : 0;
*state_cur |= (down & PAD_BUTTON_Y) ? (UINT64_C(1) << GX_GC_Y) : 0;
*state_cur |= (down & PAD_BUTTON_UP) ? (UINT64_C(1) << GX_GC_UP) : 0;
*state_cur |= (down & PAD_BUTTON_DOWN) ? (UINT64_C(1) << GX_GC_DOWN) : 0;
*state_cur |= (down & PAD_BUTTON_LEFT) ? (UINT64_C(1) << GX_GC_LEFT) : 0;
*state_cur |= (down & PAD_BUTTON_RIGHT) ? (UINT64_C(1) << GX_GC_RIGHT) : 0;
*state_cur |= (down & PAD_BUTTON_START) ? (UINT64_C(1) << GX_GC_START) : 0;
*state_cur |= (down & PAD_TRIGGER_Z) ? (UINT64_C(1) << GX_GC_Z_TRIGGER) : 0;
*state_cur |= ((down & PAD_TRIGGER_L) || PAD_TriggerL(port) > 127) ? (UINT64_C(1) << GX_GC_L_TRIGGER) : 0;
*state_cur |= ((down & PAD_TRIGGER_R) || PAD_TriggerR(port) > 127) ? (UINT64_C(1) << GX_GC_R_TRIGGER) : 0;
ls_x = (int16_t)PAD_StickX(port) * 256;
ls_y = (int16_t)PAD_StickY(port) * -256;
rs_x = (int16_t)PAD_SubStickX(port) * 256;
rs_y = (int16_t)PAD_SubStickY(port) * -256;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = ls_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = ls_y;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = rs_x;
analog_state[port][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = rs_y;
menu_combo = (UINT64_C(1) << GX_GC_START) | (UINT64_C(1) << GX_GC_Z_TRIGGER) |
(UINT64_C(1) << GX_GC_L_TRIGGER) | (UINT64_C(1) << GX_GC_R_TRIGGER);
if ((*state_cur & menu_combo) == menu_combo)
*state_cur |= (UINT64_C(1) << GX_WIIMOTE_HOME);
ptype = WPAD_EXP_GAMECUBE;
}
#ifdef HAVE_LIBSICKSAXIS
else
{
USB_DeviceChangeNotifyAsync(USB_CLASS_HID, change_cb, (void*)&lol);
if (ss_is_connected(&dev[port]))
{
ptype = WPAD_EXP_SICKSAXIS;
*state_cur |= (dev[port].pad.buttons.PS) ? (UINT64_C(1) << RARCH_MENU_TOGGLE) : 0;
*state_cur |= (dev[port].pad.buttons.cross) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_B) : 0;
*state_cur |= (dev[port].pad.buttons.square) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y) : 0;
*state_cur |= (dev[port].pad.buttons.select) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0;
*state_cur |= (dev[port].pad.buttons.start) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_START) : 0;
*state_cur |= (dev[port].pad.buttons.up) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP) : 0;
*state_cur |= (dev[port].pad.buttons.down) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0;
*state_cur |= (dev[port].pad.buttons.left) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0;
*state_cur |= (dev[port].pad.buttons.right) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0;
*state_cur |= (dev[port].pad.buttons.circle) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_A) : 0;
*state_cur |= (dev[port].pad.buttons.triangle) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_X) : 0;
*state_cur |= (dev[port].pad.buttons.L1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L) : 0;
*state_cur |= (dev[port].pad.buttons.R1) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R) : 0;
*state_cur |= (dev[port].pad.buttons.L2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L2) : 0;
*state_cur |= (dev[port].pad.buttons.R2) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R2) : 0;
*state_cur |= (dev[port].pad.buttons.L3) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_L3) : 0;
*state_cur |= (dev[port].pad.buttons.R3) ? (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_R3) : 0;
}
else
{
if (ss_open(&dev[port]) > 0)
{
ptype = WPAD_EXP_SICKSAXIS;
ss_start_reading(&dev[port]);
ss_set_removal_cb(&dev[port], removal_cb, (void*)1);
}
}
}
#endif
}
if (ptype != pad_type[port])
handle_hotplug(port, ptype);
@ -539,23 +524,27 @@ static void gx_joypad_poll(void)
analog_state[port][i][j] = -0x7fff;
}
uint64_t *state_p1 = &pad_state[0];
uint64_t *state_p1 = &pad_state[0];
BIT64_CLEAR(lifecycle_state, RARCH_MENU_TOGGLE);
if (g_menu)
{
*state_p1 |= (UINT64_C(1) << GX_WIIMOTE_HOME);
*state_p1 |= (UINT64_C(1) << GX_GC_HOME);
g_menu = false;
}
if (*state_p1 & ((UINT64_C(1) << GX_WIIMOTE_HOME)
if (*state_p1 & ((UINT64_C(1) << GX_GC_HOME)
#ifdef HW_RVL
| (UINT64_C(1) << GX_WIIMOTE_HOME)
| (UINT64_C(1) << GX_CLASSIC_HOME)
#ifdef HAVE_LIBSICKSAXIS
| (UINT64_C(1) << GX_SIXAXIS_PS)
#endif
#endif
))
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
BIT64_SET(lifecycle_state, RARCH_MENU_TOGGLE);
}
static bool gx_joypad_init(void *data)
@ -574,13 +563,9 @@ static bool gx_joypad_init(void *data)
PAD_Init();
#ifdef HW_RVL
WPADInit();
#endif
#ifdef HAVE_LIBSICKSAXIS
int i;
USB_Initialize();
ss_init();
for (i = 0; i < MAX_PADS; i++)
ss_initialize(&dev[i]);
ss_init(sixaxis, USB_SLOTS);
#endif
#endif
gx_joypad_poll();
@ -595,20 +580,18 @@ static bool gx_joypad_query_pad(unsigned pad)
static void gx_joypad_destroy(void)
{
#ifdef HW_RVL
int i;
for (i = 0; i < MAX_PADS; i++)
{
#ifdef HAVE_LIBSICKSAXIS
ss_close(&dev[i]);
USB_Deinitialize();
#endif
#ifdef HW_RVL
// Commenting this out fixes the Wii remote not reconnecting after core load, exit, etc.
// WPAD_Flush(i);
// WPADDisconnect(i);
#endif
}
#ifdef HAVE_LIBSICKSAXIS
ss_shutdown();
#endif
#endif
}
input_device_driver_t gx_joypad = {

View File

@ -1,366 +1,236 @@
#include "gx_sicksaxis.h"
#include "sicksaxis.h"
#include <gccore.h>
#include <stdio.h>
#include <string.h>
#include <retro_inline.h>
static uint8_t ATTRIBUTE_ALIGN(32) _ss_attributes_payload[] =
static uint8_t ATTRIBUTE_ALIGN(32) _ss_attributes[] =
{
0x52,
0x00, 0x00, 0x00, 0x00, //Rumble
0xff, 0x80, //Gyro
0x00, 0x00,
0x00, //* LED_1 = 0x02, LED_2 = 0x04, ... */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */
0x00,
0x00, 0x00, 0x00, 0x00, //Rumble
0x00, 0x00, //Gyro
0x00, 0x00,
0x00, //* LED_1 = 0x02, LED_2 = 0x04, ... */
0xFF, 0x27, 0x10, 0x00, 0x32, /* LED_4 */
0xFF, 0x27, 0x10, 0x00, 0x32, /* LED_3 */
0xFF, 0x27, 0x10, 0x00, 0x32, /* LED_2 */
0xFF, 0x27, 0x10, 0x00, 0x32, /* LED_1 */
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
};
static const uint8_t _ss_led_pattern[] = {0x0, 0x02, 0x04, 0x08, 0x10, 0x12, 0x14, 0x18};
static int _ss_heap_id = -1;
static int _ss_inited = 0;
static int _ss_dev_number = 1;
static int _ss_dev_id_list[SS_MAX_DEV] = {0};
static int _dev_detected = 0;
static int _slots = 0;
static int _ss_rem_cb = 0; /* helps to know if it has just removed a device from the usb iface. */
struct ss_device *_ss_dev_list = NULL; /* just hold a pointer to the dev list. */
static int _ss_initialize(struct ss_device *dev);
int _ss_open(struct ss_device *dev);
int _ss_close(struct ss_device *dev);
static int _ss_dev_id_list_exists(int id);
static int _ss_dev_id_list_add(int id);
static int _ss_dev_id_list_remove(int id);
static int _ss_removal_cb(int result, void *usrdata);
static int _ss_read_cb(int result, void *usrdata);
static int _ss_operational_cb(int result, void *usrdata);
static int _ss_read(struct ss_device *dev);
static int _ss_set_operational(struct ss_device *dev);
static int _ss_build_attributes_payload(struct ss_device *dev);
static int _ss_change_cb(int result, void *usrdata);
static int _ss_send_attributes_payload(struct ss_device *dev);
static int _ss_set_operational(struct ss_device *dev);
int ss_init(void)
{
if (!_ss_inited)
{
_ss_heap_id = iosCreateHeap(SS_HEAP_SIZE);
_ss_inited = 1;
}
return 1;
int ss_init(struct ss_device *dev_list, int slots) {
if (!_ss_inited) {
USB_Initialize();
_ss_dev_list = dev_list;
_slots = slots;
int i;
for (i = 0;i < _slots; i++) {
_ss_initialize(&_ss_dev_list[i]);
}
USB_DeviceChangeNotifyAsync(USB_CLASS_HID, _ss_change_cb, NULL);
_dev_detected = 1; /* try open any existing sixasis device */
_ss_inited = 1;
}
return _ss_inited;
}
int ss_shutdown() {
int i;
for (i = 0;i < _slots; i++) {
_ss_close(&_ss_dev_list[i]);
}
int ss_initialize(struct ss_device *dev)
{
dev->device_id = -1;
dev->fd = -1;
dev->connected = 0;
dev->enabled = 0;
dev->reading = 0;
dev->removal_callback = NULL;
dev->removal_usrdata = NULL;
dev->read_callback = NULL;
dev->read_usrdata = NULL;
memset(&dev->pad, 0x0, sizeof(struct SS_GAMEPAD));
memset(&dev->attributes, 0x0, sizeof(struct SS_ATTRIBUTES));
return 1;
USB_Deinitialize();
_ss_inited = 0;
return 1;
}
int ss_open(struct ss_device *dev)
{
usb_device_entry dev_entry[8];
unsigned char dev_count;
if (!_ss_inited)
return -1;
if (dev->connected)
ss_close(dev);
if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0)
return -2;
int i;
for (i = 0; i < dev_count; ++i)
{
if ((dev_entry[i].vid == SS_VENDOR_ID) &&
(dev_entry[i].pid == SS_PRODUCT_ID))
{
if (!_ss_dev_id_list_exists(dev_entry[i].device_id))
{
if (USB_OpenDevice(dev_entry[i].device_id,
SS_VENDOR_ID, SS_PRODUCT_ID, &dev->fd) < 0)
return -3;
dev->device_id = dev_entry[i].device_id;
dev->connected = 1;
dev->enabled = 0;
dev->reading = 0;
_ss_set_operational(dev);
ss_set_led(dev, _ss_dev_number);
_ss_dev_id_list_add(dev_entry[i].device_id);
_ss_dev_number++;
USB_DeviceRemovalNotifyAsync(dev->fd, &_ss_removal_cb, dev);
return 1;
}
}
}
return -4;
}
int ss_close(struct ss_device *dev)
{
if (dev && dev->fd > 0)
USB_CloseDevice(&dev->fd);
return 1;
}
int ss_is_connected(struct ss_device *dev)
{
return dev->connected;
}
int ss_set_read_cb(struct ss_device *dev,ss_usb_callback cb,
void *userdata)
{
dev->read_callback = cb;
dev->read_usrdata = userdata;
return 1;
}
int ss_set_removal_cb(struct ss_device *dev, ss_usb_callback cb,
void *usrdata)
{
dev->removal_callback = cb;
dev->removal_usrdata = userdata;
static int _ss_initialize(struct ss_device *dev) {
dev->device_id = -1;
dev->connected = 0;
dev->enabled = 0;
memset(&dev->pad, 0x0, sizeof(struct SS_GAMEPAD));
memset(&dev->attributes, 0x0, sizeof(struct SS_ATTRIBUTES));
return 1;
}
int ss_start_reading(struct ss_device *dev)
{
if (dev)
{
dev->reading = 1;
if (dev->enabled)
_ss_read(dev);
return 1;
}
return 0;
static int _ss_change_cb(int result, void *usrdata) {
if (!_ss_rem_cb) {
/* As it's not coming from the removal callback
then we detected a new device being inserted */
_dev_detected = 1;
}
else {
_ss_rem_cb = 0;
}
/* Re-apply the callback notification for future connections changes*/
USB_DeviceChangeNotifyAsync(USB_CLASS_HID, _ss_change_cb, NULL);
return 1;
}
int ss_stop_reading(struct ss_device *dev)
{
if (dev)
{
dev->reading = 0;
return 1;
}
return 0;
int _ss_open(struct ss_device *dev) {
/* always try to close the device first */
_ss_close(dev);
usb_device_entry dev_entry[SS_MAX_DEV];
unsigned char dev_count = 0;
if (USB_GetDeviceList(dev_entry, SS_MAX_DEV, USB_CLASS_HID, &dev_count) < 0) {
return -2;
}
int i;
for (i = 0; i < dev_count; ++i) {
if ((dev_entry[i].vid == SS_VENDOR_ID) && (dev_entry[i].pid == SS_PRODUCT_ID)) {
if (!_ss_dev_id_list_exists(dev_entry[i].device_id)) {
int fd;
if (USB_OpenDevice(dev_entry[i].device_id, SS_VENDOR_ID, SS_PRODUCT_ID, &fd) < 0) {
return -3;
}
dev->device_id = dev_entry[i].device_id;
dev->connected = 1;
dev->fd = fd;
_ss_set_operational(dev);
USB_DeviceRemovalNotifyAsync(dev->fd, &_ss_removal_cb, dev);
return 1;
}
}
}
return -4;
}
static int _ss_build_attributes_payload(struct ss_device *dev)
{
_ss_attributes_payload[1] = dev->attributes.rumble.duration_right;
_ss_attributes_payload[2] = dev->attributes.rumble.power_right;
_ss_attributes_payload[3] = dev->attributes.rumble.duration_left;
_ss_attributes_payload[4] = dev->attributes.rumble.power_left;
_ss_attributes_payload[9] = _ss_led_pattern[dev->attributes.led];
return 1;
int _ss_close(struct ss_device *dev) {
if (dev && dev->fd > 0) {
USB_CloseDevice(&dev->fd);
dev->fd = -1; /* Clear its descriptor */
}
return 1;
}
static int _ss_send_attributes_payload(struct ss_device *dev)
{
if (!dev->connected)
return 0;
int ss_is_ready(struct ss_device *dev) {
_ss_build_attributes_payload(dev);
/* if a device is detected, try to connect it. */
if (_dev_detected) {
/* As we are processing the detected device, we turn off the flag. */
_dev_detected = 0;
int i;
for(i = 0; i < _slots; i++) {
if (_ss_dev_list[i].device_id < 0) { /* found an empty slot? */
if (_ss_open(&_ss_dev_list[i]) > 0) {
ss_set_led(&_ss_dev_list[i], i+1);
}
break;
}
}
}
return USB_WriteCtrlMsgAsync(dev->fd,
USB_REQTYPE_INTERFACE_SET,
USB_REQ_SETREPORT,
(USB_REPTYPE_OUTPUT<<8) | 0x01,
0x0,
sizeof(_ss_attributes_payload),
_ss_attributes_payload,
NULL, NULL);
if (dev->connected && dev->enabled)
return 1;
return 0;
}
static INLINE int ss_set_led(struct ss_device *dev, int led)
{
dev->attributes.led = led;
return _ss_send_attributes_payload(dev);
static int _ss_send_attributes_payload(struct ss_device *dev) {
_ss_attributes[1] = dev->attributes.rumble.duration_right;
_ss_attributes[2] = dev->attributes.rumble.power_right;
_ss_attributes[3] = dev->attributes.rumble.duration_left;
_ss_attributes[4] = dev->attributes.rumble.power_left;
_ss_attributes[9] = _ss_led_pattern[dev->attributes.led];
return USB_WriteCtrlMsg(
dev->fd,
USB_REQTYPE_INTERFACE_SET,
USB_REQ_SETREPORT,
(USB_REPTYPE_OUTPUT<<8) | 0x01,
0x0,
sizeof(_ss_attributes),
_ss_attributes
);
}
static INLINE int ss_set_rumble(struct ss_device *dev, uint8_t duration_right,
uint8_t power_right, uint8_t duration_left, uint8_t power_left)
{
dev->attributes.rumble.duration_right = duration_right;
dev->attributes.rumble.power_right = power_right;
dev->attributes.rumble.duration_left = duration_left;
dev->attributes.rumble.power_left = power_left;
return _ss_send_attributes_payload(dev);
int ss_set_led(struct ss_device *dev, int led) {
/* Need to clear the data for rumble */
dev->attributes.rumble.duration_right = 0;
dev->attributes.rumble.power_right = 0;
dev->attributes.rumble.duration_left = 0;
dev->attributes.rumble.power_left = 0;
dev->attributes.led = led;
return _ss_send_attributes_payload(dev);
}
int ss_get_bd_address(struct ss_device *dev, uint8_t *mac)
{
uint8_t ATTRIBUTE_ALIGN(32) msg[17];
int ret = USB_WriteCtrlMsgAsync(dev->fd,
USB_REQTYPE_INTERFACE_GET,
USB_REQ_GETREPORT,
(USB_REPTYPE_FEATURE<<8) | 0xf2,
0,
sizeof(msg),
msg,
NULL, NULL);
mac[0] = msg[4];
mac[1] = msg[5];
mac[2] = msg[6];
mac[3] = msg[7];
mac[4] = msg[8];
mac[5] = msg[9];
return ret;
int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left) {
dev->attributes.rumble.duration_right = duration_right;
dev->attributes.rumble.power_right = power_right;
dev->attributes.rumble.duration_left = duration_left;
dev->attributes.rumble.power_left = power_left;
return _ss_send_attributes_payload(dev);
}
int ss_get_mac(struct ss_device *dev, uint8_t *mac)
{
uint8_t ATTRIBUTE_ALIGN(32) msg[8];
int ret = USB_WriteCtrlMsgAsync(dev->fd,
USB_REQTYPE_INTERFACE_GET,
USB_REQ_GETREPORT,
(USB_REPTYPE_FEATURE<<8) | 0xf5,
0,
sizeof(msg),
msg,
NULL, NULL);
mac[0] = msg[2];
mac[1] = msg[3];
mac[2] = msg[4];
mac[3] = msg[5];
mac[4] = msg[6];
mac[5] = msg[7];
return ret;
inline int ss_read_pad(struct ss_device *dev) {
return USB_ReadIntrMsg(dev->fd, 0x81, SS_PAYLOAD_SIZE, (u8 *)&dev->pad);
}
int ss_set_mac(struct ss_device *dev, const uint8_t *mac)
{
uint8_t ATTRIBUTE_ALIGN(32) msg[] = {0x01, 0x00, mac[0], mac[1],
mac[2], mac[3], mac[4], mac[5]};
int ret = USB_WriteCtrlMsgAsync(dev->fd,
USB_REQTYPE_INTERFACE_SET,
USB_REQ_SETREPORT,
(USB_REPTYPE_FEATURE<<8) | 0xf5,
0,
sizeof(msg),
msg,
NULL, NULL);
return ret;
static int _ss_removal_cb(int result, void *usrdata) {
struct ss_device *dev = (struct ss_device*)usrdata;
if (dev->device_id > 0) {
_ss_initialize(dev);
_ss_rem_cb = 1; /* inform we already pass thru the removal callback */
}
return 1;
}
static int _ss_set_operational(struct ss_device *dev) {
int r;
uint8_t ATTRIBUTE_ALIGN(32) buf[4] = {0x42, 0x0c, 0x00, 0x00}; /* Special command to enable Sixaxis */
/* Sometimes it fails so we should keep trying until success */
do {
r = USB_WriteCtrlMsg(
dev->fd,
USB_REQTYPE_INTERFACE_SET,
USB_REQ_SETREPORT,
(USB_REPTYPE_FEATURE<<8) | 0xf4,
0x0,
sizeof(buf),
buf
);
} while (r < 0);
static int _ss_read(struct ss_device *dev)
{
return USB_WriteCtrlMsgAsync(
dev->fd,
USB_REQTYPE_INTERFACE_GET,
USB_REQ_GETREPORT,
(USB_REPTYPE_INPUT<<8) | 0x01,
0x0,
SS_PAYLOAD_SIZE,
&dev->pad,
&_ss_read_cb,
dev);
dev->enabled = 1;
return 1;
}
static int _ss_removal_cb(int result, void *usrdata)
{
struct ss_device *dev = (struct ss_device*)usrdata;
if (dev->device_id > 0)
{
_ss_dev_id_list_remove(dev->device_id);
_ss_dev_number--;
if (dev->removal_callback)
dev->removal_callback(dev->removal_usrdata);
ss_initialize(dev);
return 1;
}
return 0;
}
static int _ss_set_operational(struct ss_device *dev)
{
uint8_t ATTRIBUTE_ALIGN(32) buf[17];
return USB_WriteCtrlMsgAsync(
dev->fd,
USB_REQTYPE_INTERFACE_GET,
USB_REQ_GETREPORT,
(USB_REPTYPE_FEATURE<<8) | 0xf2,
0x0,
17,
buf,
&_ss_operational_cb,
dev);
}
static int _ss_read_cb(int result, void *userdata)
{
if (userdata)
{
struct ss_device *dev = (struct ss_device*)userdata;
if (dev->reading)
{
_ss_read(dev);
if (dev->read_callback)
dev->read_callback(dev->read_usrdata);
}
}
return 1;
}
static int _ss_operational_cb(int result, void *userdata)
{
struct ss_device *dev = (struct ss_device*)userdata;
dev->enabled = 1;
if (dev->reading)
_ss_read(dev);
return 1;
}
static int _ss_dev_id_list_exists(int id)
{
int i;
for (i = 0; i < SS_MAX_DEV; ++i)
{
if (_ss_dev_id_list[i] == id)
return 1;
}
return 0;
}
static int _ss_dev_id_list_add(int id)
{
int i;
for (i = 0; i < SS_MAX_DEV; ++i)
{
if (_ss_dev_id_list[i] == 0)
{
_ss_dev_id_list[i] = id;
return 1;
}
}
return 0;
}
static int _ss_dev_id_list_remove(int id)
{
int i;
for (i = 0; i < SS_MAX_DEV; ++i)
{
if (_ss_dev_id_list[i] == id)
{
_ss_dev_id_list[i] = 0;
return 1;
}
}
return 0;
static int _ss_dev_id_list_exists(int id) {
int i;
for (i = 0; i < _slots; ++i) {
if (_ss_dev_list[i].device_id == id) return 1;
}
return 0;
}

View File

@ -3,14 +3,13 @@
#include <gccore.h>
#define SS_HEAP_SIZE 4096
#define SS_MAX_DEV 8
#define SS_VENDOR_ID 0x054C
#define SS_PRODUCT_ID 0x0268
#define SS_PAYLOAD_SIZE 49
struct SS_BUTTONS
{
struct SS_BUTTONS {
uint8_t left : 1;
uint8_t down : 1;
uint8_t right : 1;
@ -33,46 +32,40 @@ struct SS_BUTTONS
uint8_t PS : 1;
};
struct SS_ANALOG
{
struct SS_ANALOG {
uint8_t x;
uint8_t y;
};
struct SS_DPAD_SENSITIVE
{
struct SS_DPAD_SENSITIVE {
uint8_t up;
uint8_t right;
uint8_t down;
uint8_t left;
};
struct SS_SHOULDER_SENSITIVE
{
struct SS_SHOULDER_SENSITIVE {
uint8_t L2;
uint8_t R2;
uint8_t L1;
uint8_t R1;
};
struct SS_BUTTON_SENSITIVE
{
struct SS_BUTTON_SENSITIVE {
uint8_t triangle;
uint8_t circle;
uint8_t cross;
uint8_t square;
};
struct SS_MOTION
{
struct SS_MOTION {
uint16_t acc_x;
uint16_t acc_y;
uint16_t acc_z;
uint16_t z_gyro;
};
struct SS_GAMEPAD
{
struct SS_GAMEPAD {
uint8_t hid_data;
uint8_t unk0;
struct SS_BUTTONS buttons;
@ -94,63 +87,34 @@ struct SS_GAMEPAD
struct SS_MOTION motion;
}__attribute__((packed));
struct SS_ATTRIBUTE_RUMBLE
{
struct SS_ATTRIBUTE_RUMBLE {
uint8_t duration_right;
uint8_t power_right;
uint8_t duration_left;
uint8_t power_left;
};
struct SS_ATTRIBUTES
{
struct SS_ATTRIBUTES {
struct SS_ATTRIBUTE_RUMBLE rumble;
int led;
};
typedef void (*ss_usb_callback)(void *usrdata);
struct ss_device {
struct SS_GAMEPAD pad;
struct SS_ATTRIBUTES attributes;
int device_id, fd;
int connected, enabled, reading;
ss_usb_callback read_callback;
ss_usb_callback removal_callback;
void *read_usrdata, *removal_usrdata;
int device_id;
int fd;
int connected;
int enabled;
}__attribute__((aligned(32)));
int ss_init(void);
int ss_initialize(struct ss_device *dev);
int ss_open(struct ss_device *dev);
int ss_close(struct ss_device *dev);
int ss_is_connected(struct ss_device *dev);
int ss_set_read_cb(struct ss_device *dev,
ss_usb_callback cb, void *usrdata);
int ss_set_removal_cb(struct ss_device *dev,
ss_usb_callback cb, void *usrdata);
int ss_start_reading(struct ss_device *dev);
int ss_stop_reading(struct ss_device *dev);
int ss_init(struct ss_device *dev_list, int slots);
int ss_shutdown();
int ss_is_ready(struct ss_device *dev);
int ss_read_pad(struct ss_device *dev);
int ss_set_led(struct ss_device *dev, int led);
int ss_set_rumble(struct ss_device *dev, uint8_t duration_right,
uint8_t power_right, uint8_t duration_left, uint8_t power_left);
int ss_get_bd_address(struct ss_device *dev, uint8_t *mac);
int ss_get_paired_mac(struct ss_device *dev, uint8_t *mac);
int ss_set_paired_mac(struct ss_device *dev, const uint8_t *mac);
int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left);
#endif

View File

@ -83,7 +83,7 @@ static void print_help(void)
puts("-h/--help: This help.");
}
#define MAX_BUTTONS 32
#define MAX_BUTTONS 64
#define MAX_AXES 32
#define MAX_HATS 32
struct poll_data