Merge pull request #1959 from netux79/master

Fixed nunchuk controller support, it was not correctly detected.
This commit is contained in:
Twinaphex 2015-07-14 06:03:34 +02:00
commit f2ee781e92
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_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;
}

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