switch: handle single joycons

This commit is contained in:
cpasjuste 2022-04-11 13:44:35 +02:00
parent c29f5893c8
commit 0705288edd
1 changed files with 171 additions and 110 deletions

View File

@ -26,88 +26,152 @@
#include "SDL_events.h" #include "SDL_events.h"
#include "../SDL_sysjoystick.h" #include "../SDL_sysjoystick.h"
#include "SDL_hints.h"
#include <switch.h> #include <switch.h>
#define JOYSTICK_COUNT 8 #define JOYSTICK_COUNT 8
typedef struct SWITCHJoystickState typedef struct SWITCHJoystickState {
{
PadState pad; PadState pad;
HidAnalogStickState sticks_old[2]; HidAnalogStickState sticks_old[2];
HidVibrationDeviceHandle vibrationDeviceHandles; HidVibrationDeviceHandle vibrationDeviceHandles;
HidVibrationValue vibrationValues; HidVibrationValue vibrationValues;
HidNpadButton *pad_mapping;
u32 pad_type;
u32 pad_type_prev;
HidNpadStyleTag pad_style;
HidNpadStyleTag pad_style_prev;
} SWITCHJoystickState; } SWITCHJoystickState;
static SWITCHJoystickState state[JOYSTICK_COUNT]; static SWITCHJoystickState state[JOYSTICK_COUNT];
static const HidNpadButton pad_mapping[] = { static const HidNpadButton pad_mapping_default[] = {
HidNpadButton_A, HidNpadButton_B, HidNpadButton_X, HidNpadButton_Y, HidNpadButton_A, HidNpadButton_B, HidNpadButton_X, HidNpadButton_Y,
HidNpadButton_StickL, HidNpadButton_StickR, HidNpadButton_StickL, HidNpadButton_StickR,
HidNpadButton_L, HidNpadButton_R, HidNpadButton_L, HidNpadButton_R,
HidNpadButton_ZL, HidNpadButton_ZR, HidNpadButton_ZL, HidNpadButton_ZR,
HidNpadButton_Plus, HidNpadButton_Minus, HidNpadButton_Plus, HidNpadButton_Minus,
HidNpadButton_Left, HidNpadButton_Up, HidNpadButton_Right, HidNpadButton_Down, HidNpadButton_Left, HidNpadButton_Up, HidNpadButton_Right, HidNpadButton_Down,
HidNpadButton_StickLLeft, HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown, HidNpadButton_StickLLeft, HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown,
HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight, HidNpadButton_StickRDown, HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight, HidNpadButton_StickRDown,
HidNpadButton_LeftSL, HidNpadButton_LeftSR, HidNpadButton_RightSL, HidNpadButton_RightSR HidNpadButton_LeftSL, HidNpadButton_LeftSR, HidNpadButton_RightSL, HidNpadButton_RightSR
}; };
// left single joycon mapping (start = left stick, select = minus)
static const HidNpadButton pad_mapping_left_joy[] = {
HidNpadButton_Down, HidNpadButton_Left, HidNpadButton_Right, HidNpadButton_Up,
BIT(31), BIT(31),
BIT(31), BIT(31),
HidNpadButton_LeftSL, HidNpadButton_LeftSR,
HidNpadButton_StickL, HidNpadButton_Minus,
HidNpadButton_StickLUp, HidNpadButton_StickLRight, HidNpadButton_StickLDown, HidNpadButton_StickLLeft,
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31)
};
// right single joycon mapping (start = right stick, select = plus)
static const HidNpadButton pad_mapping_right_joy[] = {
HidNpadButton_X, HidNpadButton_A, HidNpadButton_Y, HidNpadButton_B,
BIT(31), BIT(31),
BIT(31), BIT(31),
HidNpadButton_RightSL, HidNpadButton_RightSR,
HidNpadButton_StickR, HidNpadButton_Plus,
HidNpadButton_StickRDown, HidNpadButton_StickRLeft, HidNpadButton_StickRUp, HidNpadButton_StickRRight,
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31),
BIT(31), BIT(31), BIT(31), BIT(31)
};
static void SWITCH_ShowControllerSupport(void) {
HidLaControllerSupportResultInfo info;
HidLaControllerSupportArg args;
hidLaCreateControllerSupportArg(&args);
args.hdr.player_count_max = JOYSTICK_COUNT;
hidLaShowControllerSupportForSystem(&info, &args, false);
// update pads states
for (int i = 0; i < JOYSTICK_COUNT; i++) {
SDL_Joystick *joy = SDL_JoystickFromInstanceID(i);
if (joy) {
padUpdate(&state[i].pad);
state[i].pad_type = state[i].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) i);
state[i].pad_style = state[i].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) i);
// update pad mapping
if (!(state[i].pad_style & HidNpadStyleTag_NpadJoyDual) &&
(state[i].pad_type & HidDeviceTypeBits_JoyLeft)) {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_left_joy;
} else if (!(state[i].pad_style & HidNpadStyleTag_NpadJoyDual) &&
(state[i].pad_type & HidDeviceTypeBits_JoyRight)) {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_right_joy;
} else {
state[i].pad_mapping = (HidNpadButton *) &pad_mapping_default;
}
// update vibration stuff ?
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles, 1,
HidNpadIdType_No1 + i, state[i].pad_style);
// reset sdl joysticks states
SDL_PrivateJoystickAxis(joy, 0, 0);
SDL_PrivateJoystickAxis(joy, 1, 0);
SDL_PrivateJoystickAxis(joy, 2, 0);
SDL_PrivateJoystickAxis(joy, 3, 0);
state[i].pad.buttons_cur = 0;
state[i].pad.buttons_old = 0;
for (int j = 0; j < joy->nbuttons; j++) {
SDL_PrivateJoystickButton(joy, j, SDL_RELEASED);
}
}
}
}
/* Function to scan the system for joysticks. /* Function to scan the system for joysticks.
* It should return 0, or -1 on an unrecoverable fatal error. * It should return 0, or -1 on an unrecoverable fatal error.
*/ */
static int static int SWITCH_JoystickInit(void) {
SWITCH_JoystickInit(void)
{
padConfigureInput(JOYSTICK_COUNT, HidNpadStyleSet_NpadStandard); padConfigureInput(JOYSTICK_COUNT, HidNpadStyleSet_NpadStandard);
// initialize first pad to defaults // initialize first pad to defaults
padInitializeDefault(&state[0].pad); padInitializeDefault(&state[0].pad);
padUpdate(&state[0].pad); padUpdate(&state[0].pad);
state[0].pad_mapping = (HidNpadButton *) &pad_mapping_default;
state[0].pad_type = state[0].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) 0);
state[0].pad_style = state[0].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) 0);
// initialize pad and vibrations for pad 1 to 7 // initialize pad and vibrations for pad 1 to 7
for (int i = 1; i < JOYSTICK_COUNT; i++) { for (int i = 1; i < JOYSTICK_COUNT; i++) {
padInitialize(&state[i].pad, HidNpadIdType_No1 + i); padInitialize(&state[i].pad, HidNpadIdType_No1 + i);
padUpdate(&state[i].pad); padUpdate(&state[i].pad);
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles,1, state[i].pad_mapping = (HidNpadButton *) &pad_mapping_default;
HidNpadIdType_No1 + i, padGetStyleSet(&state[i].pad)); state[i].pad_type = state[i].pad_type_prev = hidGetNpadDeviceType((HidNpadIdType) i);
state[i].pad_style = state[i].pad_style_prev = hidGetNpadStyleSet((HidNpadIdType) i);
hidInitializeVibrationDevices(&state[i].vibrationDeviceHandles, 1,
HidNpadIdType_No1 + i, state[i].pad_style);
} }
return JOYSTICK_COUNT; return JOYSTICK_COUNT;
} }
static int static int SWITCH_JoystickGetCount(void) {
SWITCH_JoystickGetCount(void)
{
return JOYSTICK_COUNT; return JOYSTICK_COUNT;
} }
static void static void SWITCH_JoystickDetect(void) {
SWITCH_JoystickDetect(void)
{
} }
/* Function to get the device-dependent name of a joystick */ /* Function to get the device-dependent name of a joystick */
static const char * static const char *SWITCH_JoystickGetDeviceName(int device_index) {
SWITCH_JoystickGetDeviceName(int device_index)
{
return "Switch Controller"; return "Switch Controller";
} }
static int static int SWITCH_JoystickGetDevicePlayerIndex(int device_index) {
SWITCH_JoystickGetDevicePlayerIndex(int device_index)
{
return -1; return -1;
} }
static void static void SWITCH_JoystickSetDevicePlayerIndex(int device_index, int player_index) {
SWITCH_JoystickSetDevicePlayerIndex(int device_index, int player_index)
{
} }
static SDL_JoystickGUID static SDL_JoystickGUID SWITCH_JoystickGetDeviceGUID(int device_index) {
SWITCH_JoystickGetDeviceGUID(int device_index)
{
SDL_JoystickGUID guid; SDL_JoystickGUID guid;
/* the GUID is just the first 16 chars of the name for now */ /* the GUID is just the first 16 chars of the name for now */
const char *name = SWITCH_JoystickGetDeviceName(device_index); const char *name = SWITCH_JoystickGetDeviceName(device_index);
@ -117,9 +181,7 @@ SWITCH_JoystickGetDeviceGUID(int device_index)
} }
/* Function to perform the mapping from device index to the instance id for this index */ /* Function to perform the mapping from device index to the instance id for this index */
static SDL_JoystickID static SDL_JoystickID SWITCH_JoystickGetDeviceInstanceID(int device_index) {
SWITCH_JoystickGetDeviceInstanceID(int device_index)
{
return device_index; return device_index;
} }
@ -128,10 +190,8 @@ SWITCH_JoystickGetDeviceInstanceID(int device_index)
This should fill the nbuttons and naxes fields of the joystick structure. This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error. It returns 0, or -1 if there is an error.
*/ */
static int static int SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index) {
SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index) joystick->nbuttons = sizeof(pad_mapping_default) / sizeof(*pad_mapping_default);
{
joystick->nbuttons = sizeof(pad_mapping) / sizeof(*pad_mapping);
joystick->naxes = 4; joystick->naxes = 4;
joystick->nhats = 0; joystick->nhats = 0;
joystick->instance_id = device_index; joystick->instance_id = device_index;
@ -139,9 +199,7 @@ SWITCH_JoystickOpen(SDL_Joystick *joystick, int device_index)
return 0; return 0;
} }
static int static int SWITCH_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble) {
SWITCH_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
{
int id = joystick->instance_id; int id = joystick->instance_id;
state[id].vibrationValues.amp_low = state[id].vibrationValues.amp_low =
@ -156,27 +214,19 @@ SWITCH_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint
return 0; return 0;
} }
static int static int SWITCH_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left, Uint16 right) {
SWITCH_JoystickRumbleTriggers(SDL_Joystick * joystick, Uint16 left, Uint16 right)
{
return SDL_Unsupported(); return SDL_Unsupported();
} }
static SDL_bool static SDL_bool SWITCH_JoystickHasLED(SDL_Joystick *joystick) {
SWITCH_JoystickHasLED(SDL_Joystick * joystick)
{
return SDL_FALSE; return SDL_FALSE;
} }
static int static int SWITCH_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue) {
SWITCH_JoystickSetLED(SDL_Joystick * joystick, Uint8 red, Uint8 green, Uint8 blue)
{
return 0; return 0;
} }
static int static int SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled) {
SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
{
return SDL_Unsupported(); return SDL_Unsupported();
} }
@ -185,82 +235,93 @@ SWITCH_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
* but instead should call SDL_PrivateJoystick*() to deliver events * but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state. * and update joystick device state.
*/ */
static void static void SWITCH_JoystickUpdate(SDL_Joystick *joystick) {
SWITCH_JoystickUpdate(SDL_Joystick *joystick)
{
u64 diff; u64 diff;
int index = (int) SDL_JoystickInstanceID(joystick); int index = (int) SDL_JoystickInstanceID(joystick);
if (index > JOYSTICK_COUNT || SDL_IsTextInputActive()) { if (index >= JOYSTICK_COUNT || SDL_IsTextInputActive()) {
return; return;
} }
padUpdate(&state[index].pad); padUpdate(&state[index].pad);
if (!padIsConnected(&state[index].pad)) {
return;
}
// Axes (left) // update pad type and style, open controller support applet if needed
if (state[index].sticks_old[0].x != state[index].pad.sticks[0].x) { state[index].pad_type = hidGetNpadDeviceType((HidNpadIdType) index);
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) state[index].pad.sticks[0].x); state[index].pad_style = hidGetNpadStyleSet((HidNpadIdType) index);
state[index].sticks_old[0].x = state[index].pad.sticks[0].x; if (state[index].pad_type != state[index].pad_type_prev
|| state[index].pad_style != state[index].pad_style_prev) {
SWITCH_ShowControllerSupport();
return;
} }
if (state[index].sticks_old[0].y != state[index].pad.sticks[0].y) {
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) -state[index].pad.sticks[0].y);
state[index].sticks_old[0].y = -state[index].pad.sticks[0].y;
}
state[index].sticks_old[0] = padGetStickPos(&state[index].pad, 0);
// Axes (right)
if (state[index].sticks_old[1].x != state[index].pad.sticks[1].x) {
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) state[index].pad.sticks[1].x);
state[index].sticks_old[1].x = state[index].pad.sticks[1].x;
}
if (state[index].sticks_old[1].y != state[index].pad.sticks[1].y) {
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) -state[index].pad.sticks[1].y);
state[index].sticks_old[1].y = -state[index].pad.sticks[1].y;
}
state[index].sticks_old[1] = padGetStickPos(&state[index].pad, 1);
// Buttons // only handle axes in non-single joycon mode
if (state[index].pad_style & HidNpadStyleTag_NpadJoyDual
|| (state[index].pad_type != HidDeviceTypeBits_JoyLeft
&& state[index].pad_type != HidDeviceTypeBits_JoyRight)) {
// axis left
if (state[index].sticks_old[0].x != state[index].pad.sticks[0].x) {
SDL_PrivateJoystickAxis(joystick, 0, (Sint16) state[index].pad.sticks[0].x);
state[index].sticks_old[0].x = state[index].pad.sticks[0].x;
}
if (state[index].sticks_old[0].y != state[index].pad.sticks[0].y) {
SDL_PrivateJoystickAxis(joystick, 1, (Sint16) - state[index].pad.sticks[0].y);
state[index].sticks_old[0].y = -state[index].pad.sticks[0].y;
}
state[index].sticks_old[0] = padGetStickPos(&state[index].pad, 0);
// axis right
if (state[index].sticks_old[1].x != state[index].pad.sticks[1].x) {
SDL_PrivateJoystickAxis(joystick, 2, (Sint16) state[index].pad.sticks[1].x);
state[index].sticks_old[1].x = state[index].pad.sticks[1].x;
}
if (state[index].sticks_old[1].y != state[index].pad.sticks[1].y) {
SDL_PrivateJoystickAxis(joystick, 3, (Sint16) - state[index].pad.sticks[1].y);
state[index].sticks_old[1].y = -state[index].pad.sticks[1].y;
}
state[index].sticks_old[1] = padGetStickPos(&state[index].pad, 1);
}
// handle buttons
diff = state[index].pad.buttons_old ^ state[index].pad.buttons_cur; diff = state[index].pad.buttons_old ^ state[index].pad.buttons_cur;
if (diff) { if (diff) {
for (int i = 0; i < joystick->nbuttons; i++) { for (int i = 0; i < joystick->nbuttons; i++) {
if (diff & pad_mapping[i]) { if (diff & state[index].pad_mapping[i]) {
SDL_PrivateJoystickButton(joystick, i, SDL_PrivateJoystickButton(
state[index].pad.buttons_cur & pad_mapping[i] ? joystick, i,
SDL_PRESSED : SDL_RELEASED); state[index].pad.buttons_cur & state[index].pad_mapping[i] ?
SDL_PRESSED : SDL_RELEASED);
} }
} }
} }
} }
/* Function to close a joystick after use */ /* Function to close a joystick after use */
static void static void SWITCH_JoystickClose(SDL_Joystick *joystick) {
SWITCH_JoystickClose(SDL_Joystick *joystick)
{
} }
/* Function to perform any system-specific joystick related cleanup */ /* Function to perform any system-specific joystick related cleanup */
static void static void SWITCH_JoystickQuit(void) {
SWITCH_JoystickQuit(void)
{
} }
SDL_JoystickDriver SDL_SWITCH_JoystickDriver = SDL_JoystickDriver SDL_SWITCH_JoystickDriver = {
{ SWITCH_JoystickInit,
SWITCH_JoystickInit, SWITCH_JoystickGetCount,
SWITCH_JoystickGetCount, SWITCH_JoystickDetect,
SWITCH_JoystickDetect, SWITCH_JoystickGetDeviceName,
SWITCH_JoystickGetDeviceName, SWITCH_JoystickGetDevicePlayerIndex,
SWITCH_JoystickGetDevicePlayerIndex, SWITCH_JoystickSetDevicePlayerIndex,
SWITCH_JoystickSetDevicePlayerIndex, SWITCH_JoystickGetDeviceGUID,
SWITCH_JoystickGetDeviceGUID, SWITCH_JoystickGetDeviceInstanceID,
SWITCH_JoystickGetDeviceInstanceID, SWITCH_JoystickOpen,
SWITCH_JoystickOpen, SWITCH_JoystickRumble,
SWITCH_JoystickRumble, SWITCH_JoystickRumbleTriggers,
SWITCH_JoystickRumbleTriggers, SWITCH_JoystickHasLED,
SWITCH_JoystickHasLED, SWITCH_JoystickSetLED,
SWITCH_JoystickSetLED, SWITCH_JoystickSetSensorsEnabled,
SWITCH_JoystickSetSensorsEnabled, SWITCH_JoystickUpdate,
SWITCH_JoystickUpdate, SWITCH_JoystickClose,
SWITCH_JoystickClose, SWITCH_JoystickQuit,
SWITCH_JoystickQuit,
}; };
#endif /* SDL_JOYSTICK_SWITCH */ #endif /* SDL_JOYSTICK_SWITCH */