mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-20 06:21:09 +00:00
Added support for the player LED on Nintendo Switch 2 controllers
This commit is contained in:
@@ -85,6 +85,9 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
SDL_Joystick *joystick;
|
||||
|
||||
SDL_LibUSBContext *libusb;
|
||||
libusb_device_handle *device_handle;
|
||||
bool interface_claimed;
|
||||
@@ -97,6 +100,9 @@ typedef struct
|
||||
Uint8 left_trigger_max;
|
||||
Uint8 right_trigger_max;
|
||||
|
||||
bool player_lights;
|
||||
int player_index;
|
||||
|
||||
bool vertical_mode;
|
||||
Uint8 last_state[USB_PACKET_LENGTH];
|
||||
} SDL_DriverSwitch2_Context;
|
||||
@@ -198,6 +204,37 @@ static void MapTriggerAxis(Uint64 timestamp, SDL_Joystick *joystick, Uint8 axis,
|
||||
SDL_SendJoystickAxis(timestamp, joystick, axis, mapped_value);
|
||||
}
|
||||
|
||||
static bool UpdateSlotLED(SDL_DriverSwitch2_Context *ctx)
|
||||
{
|
||||
unsigned char SET_LED_DATA[] = {
|
||||
0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
unsigned char calibration_data[0x50] = {0};
|
||||
|
||||
if (ctx->player_lights && ctx->player_index >= 0) {
|
||||
SET_LED_DATA[8] = (1 << (ctx->player_index % 4));
|
||||
}
|
||||
int res = SendBulkData(ctx, SET_LED_DATA, sizeof(SET_LED_DATA));
|
||||
if (res < 0) {
|
||||
return SDL_SetError("Couldn't set LED data: %d\n", res);
|
||||
}
|
||||
return (RecvBulkData(ctx, calibration_data, 0x40) > 0);
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_PlayerLEDHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)userdata;
|
||||
bool player_lights = SDL_GetStringBoolean(hint, true);
|
||||
|
||||
if (player_lights != ctx->player_lights) {
|
||||
ctx->player_lights = player_lights;
|
||||
|
||||
UpdateSlotLED(ctx);
|
||||
HIDAPI_UpdateDeviceProperties(ctx->device);
|
||||
}
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverSwitch2_RegisterHints(SDL_HintCallback callback, void *userdata)
|
||||
{
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH2, callback, userdata);
|
||||
@@ -300,10 +337,6 @@ static bool HIDAPI_DriverSwitch2_InitUSB(SDL_HIDAPI_Device *device)
|
||||
0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00,
|
||||
0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
const unsigned char SET_LED_DATA[] = {
|
||||
0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
unsigned char flash_read_command[] = {
|
||||
0x02, 0x91, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00
|
||||
@@ -316,12 +349,6 @@ static bool HIDAPI_DriverSwitch2_InitUSB(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
RecvBulkData(ctx, calibration_data, 0x40);
|
||||
|
||||
res = SendBulkData(ctx, SET_LED_DATA, sizeof(SET_LED_DATA));
|
||||
if (res < 0) {
|
||||
return SDL_SetError("Couldn't set LED data: %d\n", res);
|
||||
}
|
||||
RecvBulkData(ctx, calibration_data, 0x40);
|
||||
|
||||
flash_read_command[12] = 0x80;
|
||||
res = SendBulkData(ctx, flash_read_command, sizeof(flash_read_command));
|
||||
if (res < 0) {
|
||||
@@ -377,6 +404,7 @@ static bool HIDAPI_DriverSwitch2_InitDevice(SDL_HIDAPI_Device *device)
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
ctx->device = device;
|
||||
device->context = ctx;
|
||||
|
||||
if (device->is_bluetooth) {
|
||||
@@ -410,12 +438,31 @@ static int HIDAPI_DriverSwitch2_GetDevicePlayerIndex(SDL_HIDAPI_Device *device,
|
||||
|
||||
static void HIDAPI_DriverSwitch2_SetDevicePlayerIndex(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index)
|
||||
{
|
||||
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
|
||||
|
||||
if (!ctx->joystick) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->player_index = player_index;
|
||||
|
||||
UpdateSlotLED(ctx);
|
||||
}
|
||||
|
||||
static bool HIDAPI_DriverSwitch2_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
|
||||
|
||||
ctx->joystick = joystick;
|
||||
|
||||
// Initialize player index (needed for setting LEDs)
|
||||
ctx->player_index = SDL_GetJoystickPlayerIndex(joystick);
|
||||
ctx->player_lights = SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, true);
|
||||
UpdateSlotLED(ctx);
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED,
|
||||
SDL_PlayerLEDHintChanged, ctx);
|
||||
|
||||
// Initialize the joystick capabilities
|
||||
switch (device->product_id) {
|
||||
case USB_PRODUCT_NINTENDO_SWITCH2_GAMECUBE_CONTROLLER:
|
||||
@@ -453,7 +500,13 @@ static bool HIDAPI_DriverSwitch2_RumbleJoystickTriggers(SDL_HIDAPI_Device *devic
|
||||
|
||||
static Uint32 HIDAPI_DriverSwitch2_GetJoystickCapabilities(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
return 0;
|
||||
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
|
||||
Uint32 result = 0;
|
||||
|
||||
if (ctx->player_lights) {
|
||||
result |= SDL_JOYSTICK_CAP_PLAYER_LED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool HIDAPI_DriverSwitch2_SetJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
||||
@@ -886,6 +939,12 @@ static bool HIDAPI_DriverSwitch2_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||
|
||||
static void HIDAPI_DriverSwitch2_CloseJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
{
|
||||
SDL_DriverSwitch2_Context *ctx = (SDL_DriverSwitch2_Context *)device->context;
|
||||
|
||||
SDL_RemoveHintCallback(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED,
|
||||
SDL_PlayerLEDHintChanged, ctx);
|
||||
|
||||
ctx->joystick = NULL;
|
||||
}
|
||||
|
||||
static void HIDAPI_DriverSwitch2_FreeDevice(SDL_HIDAPI_Device *device)
|
||||
|
||||
Reference in New Issue
Block a user