mirror of https://github.com/encounter/SDL.git
Use the asynchronous HIDAPI rumble code for Nintendo Switch Pro controllers
This commit is contained in:
parent
81256207bd
commit
8ba77b35a5
|
@ -31,9 +31,10 @@
|
||||||
#include "SDL_timer.h"
|
#include "SDL_timer.h"
|
||||||
#include "SDL_joystick.h"
|
#include "SDL_joystick.h"
|
||||||
#include "SDL_gamecontroller.h"
|
#include "SDL_gamecontroller.h"
|
||||||
|
#include "../../SDL_hints_c.h"
|
||||||
#include "../SDL_sysjoystick.h"
|
#include "../SDL_sysjoystick.h"
|
||||||
#include "SDL_hidapijoystick_c.h"
|
#include "SDL_hidapijoystick_c.h"
|
||||||
#include "../../SDL_hints_c.h"
|
#include "SDL_hidapi_rumble.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef SDL_JOYSTICK_HIDAPI_SWITCH
|
#ifdef SDL_JOYSTICK_HIDAPI_SWITCH
|
||||||
|
@ -192,7 +193,7 @@ typedef struct
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
hid_device *dev;
|
SDL_HIDAPI_Device *device;
|
||||||
SDL_bool m_bInputOnly;
|
SDL_bool m_bInputOnly;
|
||||||
SDL_bool m_bHasHomeLED;
|
SDL_bool m_bHasHomeLED;
|
||||||
SDL_bool m_bUsingBluetooth;
|
SDL_bool m_bUsingBluetooth;
|
||||||
|
@ -200,6 +201,8 @@ typedef struct {
|
||||||
Uint8 m_nCommandNumber;
|
Uint8 m_nCommandNumber;
|
||||||
SwitchCommonOutputPacket_t m_RumblePacket;
|
SwitchCommonOutputPacket_t m_RumblePacket;
|
||||||
Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
|
Uint8 m_rgucReadBuffer[k_unSwitchMaxOutputPacketLength];
|
||||||
|
SDL_bool m_bRumbleActive;
|
||||||
|
Uint32 m_unRumbleRefresh;
|
||||||
|
|
||||||
SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
|
SwitchInputOnlyControllerStatePacket_t m_lastInputOnlyState;
|
||||||
SwitchSimpleStatePacket_t m_lastSimpleState;
|
SwitchSimpleStatePacket_t m_lastSimpleState;
|
||||||
|
@ -254,12 +257,21 @@ HIDAPI_DriverSwitch_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||||
|
|
||||||
static int ReadInput(SDL_DriverSwitch_Context *ctx)
|
static int ReadInput(SDL_DriverSwitch_Context *ctx)
|
||||||
{
|
{
|
||||||
return hid_read_timeout(ctx->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
|
/* Make sure we don't try to read at the same time a write is happening */
|
||||||
|
if (SDL_AtomicGet(&ctx->device->rumble_pending) > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hid_read_timeout(ctx->device->dev, ctx->m_rgucReadBuffer, sizeof(ctx->m_rgucReadBuffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int WriteOutput(SDL_DriverSwitch_Context *ctx, Uint8 *data, int size)
|
static int WriteOutput(SDL_DriverSwitch_Context *ctx, const Uint8 *data, int size)
|
||||||
{
|
{
|
||||||
return hid_write(ctx->dev, data, size);
|
/* Use the rumble thread for general asynchronous writes */
|
||||||
|
if (SDL_HIDAPI_LockRumble() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return SDL_HIDAPI_SendRumbleAndUnlock(ctx->device, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID)
|
static SwitchSubcommandInputPacket_t *ReadSubcommandReply(SDL_DriverSwitch_Context *ctx, ESwitchSubcommandIDs expectedID)
|
||||||
|
@ -430,6 +442,16 @@ static SDL_bool WriteRumble(SDL_DriverSwitch_Context *ctx)
|
||||||
ctx->m_RumblePacket.ucPacketNumber = ctx->m_nCommandNumber;
|
ctx->m_RumblePacket.ucPacketNumber = ctx->m_nCommandNumber;
|
||||||
ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
|
ctx->m_nCommandNumber = (ctx->m_nCommandNumber + 1) & 0xF;
|
||||||
|
|
||||||
|
/* Refresh the rumble state periodically */
|
||||||
|
if (ctx->m_bRumbleActive) {
|
||||||
|
ctx->m_unRumbleRefresh = SDL_GetTicks() + 1000;
|
||||||
|
if (!ctx->m_unRumbleRefresh) {
|
||||||
|
ctx->m_unRumbleRefresh = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx->m_unRumbleRefresh = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket));
|
return WritePacket(ctx, (Uint8 *)&ctx->m_RumblePacket, sizeof(ctx->m_RumblePacket));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,9 +672,10 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
ctx->device = device;
|
||||||
device->context = ctx;
|
device->context = ctx;
|
||||||
|
|
||||||
device->dev = ctx->dev = hid_open_path(device->path, 0);
|
device->dev = hid_open_path(device->path, 0);
|
||||||
if (!device->dev) {
|
if (!device->dev) {
|
||||||
SDL_SetError("Couldn't open %s", device->path);
|
SDL_SetError("Couldn't open %s", device->path);
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -765,6 +788,8 @@ HIDAPI_DriverSwitch_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joys
|
||||||
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
|
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
|
||||||
|
|
||||||
if (!WriteRumble(ctx)) {
|
if (!WriteRumble(ctx)) {
|
||||||
SDL_SetError("Couldn't send rumble packet");
|
SDL_SetError("Couldn't send rumble packet");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1065,6 +1090,11 @@ HIDAPI_DriverSwitch_UpdateDevice(SDL_HIDAPI_Device *device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ctx->m_bRumbleActive &&
|
||||||
|
SDL_TICKS_PASSED(SDL_GetTicks(), ctx->m_unRumbleRefresh)) {
|
||||||
|
WriteRumble(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
/* Read error, device is disconnected */
|
/* Read error, device is disconnected */
|
||||||
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
HIDAPI_JoystickDisconnected(device, joystick->instance_id);
|
||||||
|
|
Loading…
Reference in New Issue