mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-23 07:59:42 +00:00
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:
parent
6001d6bacd
commit
09f3c3ca77
@ -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)
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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 = {
|
||||
|
@ -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_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;
|
||||
int ss_shutdown() {
|
||||
int i;
|
||||
for (i = 0;i < _slots; i++) {
|
||||
_ss_close(&_ss_dev_list[i]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->connected && dev->enabled)
|
||||
return 1;
|
||||
|
||||
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);
|
||||
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_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);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user