early-access version 2835
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -53,6 +53,7 @@ typedef struct {
|
||||
/* Without this variable, hid_write starts to lag a TON */
|
||||
SDL_bool rumbleUpdate;
|
||||
SDL_bool m_bUseButtonLabels;
|
||||
SDL_bool useRumbleBrake;
|
||||
} SDL_DriverGameCube_Context;
|
||||
|
||||
static SDL_bool
|
||||
@@ -70,7 +71,7 @@ HIDAPI_DriverGameCube_IsSupportedDevice(const char *name, SDL_GameControllerType
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverGameCube_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverGameCube_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return "Nintendo GameCube Controller";
|
||||
}
|
||||
@@ -92,6 +93,14 @@ static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata,
|
||||
ctx->m_bUseButtonLabels = SDL_GetStringBoolean(hint, SDL_TRUE);
|
||||
}
|
||||
|
||||
static void SDLCALL SDL_JoystickGameCubeRumbleBrakeHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||
{
|
||||
if (hint) {
|
||||
SDL_DriverGameCube_Context *ctx = (SDL_DriverGameCube_Context *)userdata;
|
||||
ctx->useRumbleBrake = SDL_GetStringBoolean(hint, SDL_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static Uint8 RemapButton(SDL_DriverGameCube_Context *ctx, Uint8 button)
|
||||
{
|
||||
if (!ctx->m_bUseButtonLabels) {
|
||||
@@ -142,6 +151,7 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
|
||||
ctx->joysticks[2] = -1;
|
||||
ctx->joysticks[3] = -1;
|
||||
ctx->rumble[0] = rumbleMagic;
|
||||
ctx->useRumbleBrake = SDL_FALSE;
|
||||
|
||||
if (device->vendor_id != USB_VENDOR_NINTENDO) {
|
||||
ctx->pc_mode = SDL_TRUE;
|
||||
@@ -195,6 +205,8 @@ HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
|
||||
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
|
||||
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||
|
||||
@@ -439,12 +451,22 @@ HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo
|
||||
for (i = 0; i < MAX_CONTROLLERS; i += 1) {
|
||||
if (joystick->instance_id == ctx->joysticks[i]) {
|
||||
if (ctx->wireless[i]) {
|
||||
return SDL_SetError("Ninteno GameCube WaveBird controllers do not support rumble");
|
||||
return SDL_SetError("Nintendo GameCube WaveBird controllers do not support rumble");
|
||||
}
|
||||
if (!ctx->rumbleAllowed[i]) {
|
||||
return SDL_SetError("Second USB cable for WUP-028 not connected");
|
||||
}
|
||||
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
|
||||
if (ctx->useRumbleBrake) {
|
||||
if (low_frequency_rumble == 0 && high_frequency_rumble > 0) {
|
||||
val = 0; /* if only low is 0 we want to do a regular stop*/
|
||||
} else if (low_frequency_rumble == 0 && high_frequency_rumble == 0) {
|
||||
val = 2; /* if both frequencies are 0 we want to do a hard stop */
|
||||
} else {
|
||||
val = 1; /* normal rumble */
|
||||
}
|
||||
} else {
|
||||
val = (low_frequency_rumble > 0 || high_frequency_rumble > 0);
|
||||
}
|
||||
if (val != ctx->rumble[i + 1]) {
|
||||
ctx->rumble[i + 1] = val;
|
||||
ctx->rumbleUpdate = SDL_TRUE;
|
||||
@@ -454,8 +476,7 @@ HIDAPI_DriverGameCube_RumbleJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *jo
|
||||
}
|
||||
|
||||
/* Should never get here! */
|
||||
SDL_SetError("Couldn't find joystick");
|
||||
return -1;
|
||||
return SDL_SetError("Couldn't find joystick");
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -523,6 +544,8 @@ HIDAPI_DriverGameCube_FreeDevice(SDL_HIDAPI_Device *device)
|
||||
|
||||
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||
SDL_DelHintCallback(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE,
|
||||
SDL_JoystickGameCubeRumbleBrakeHintChanged, ctx);
|
||||
|
||||
SDL_LockMutex(device->dev_lock);
|
||||
{
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -54,7 +54,7 @@ HIDAPI_DriverLuna_IsSupportedDevice(const char *name, SDL_GameControllerType typ
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverLuna_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverLuna_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return "Amazon Luna Controller";
|
||||
}
|
||||
@@ -267,16 +267,16 @@ HIDAPI_DriverLuna_HandleBluetoothStatePacket(SDL_Joystick *joystick, SDL_DriverL
|
||||
/* Battery level report */
|
||||
int level = data[1] * 100 / 0xFF;
|
||||
if (level == 0) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
|
||||
}
|
||||
else if (level <= 20) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
|
||||
}
|
||||
else if (level <= 70) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
|
||||
}
|
||||
else {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -155,7 +155,7 @@ HIDAPI_DriverPS4_IsSupportedDevice(const char *name, SDL_GameControllerType type
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverPS4_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverPS4_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_SONY) {
|
||||
return "PS4 Controller";
|
||||
@@ -177,6 +177,12 @@ static SDL_bool HIDAPI_DriverPS4_CanRumble(Uint16 vendor_id, Uint16 product_id)
|
||||
(product_id == USB_PRODUCT_RAZER_PANTHERA || product_id == USB_PRODUCT_RAZER_PANTHERA_EVO)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* The Victrix Pro FS v2 will hang on reboot if we send output reports */
|
||||
if (vendor_id == USB_VENDOR_PDP && product_id == USB_PRODUCT_VICTRIX_FS_PRO_V2) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
@@ -795,18 +801,18 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev,
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
||||
|
||||
if (packet->ucBatteryLevel & 0x10) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
|
||||
} else {
|
||||
/* Battery level ranges from 0 to 10 */
|
||||
int level = (packet->ucBatteryLevel & 0xF);
|
||||
if (level == 0) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
|
||||
} else if (level <= 2) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
|
||||
} else if (level <= 7) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
|
||||
} else {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -59,6 +59,7 @@ typedef enum
|
||||
{
|
||||
k_EPS5FeatureReportIdCalibration = 0x05,
|
||||
k_EPS5FeatureReportIdSerialNumber = 0x09,
|
||||
k_EPS5FeatureReportIdFirmwareInfo = 0x20,
|
||||
} EPS5FeatureReportId;
|
||||
|
||||
typedef struct
|
||||
@@ -184,7 +185,7 @@ HIDAPI_DriverPS5_IsSupportedDevice(const char *name, SDL_GameControllerType type
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverPS5_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverPS5_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
if (vendor_id == USB_VENDOR_SONY) {
|
||||
return "PS5 Controller";
|
||||
@@ -601,6 +602,13 @@ HIDAPI_DriverPS5_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
|
||||
data[6], data[5], data[4], data[3], data[2], data[1]);
|
||||
joystick->serial = SDL_strdup(serial);
|
||||
}
|
||||
|
||||
/* Read the firmware version
|
||||
This will also enable enhanced reports over Bluetooth
|
||||
*/
|
||||
if (ReadFeatureReport(device->dev, k_EPS5FeatureReportIdFirmwareInfo, data, USB_PACKET_LENGTH) >= 46) {
|
||||
joystick->firmware_version = (Uint16)data[44] | ((Uint16)data[45] << 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (!joystick->serial && device->serial && SDL_strlen(device->serial) == 12) {
|
||||
@@ -747,7 +755,11 @@ HIDAPI_DriverPS5_SendJoystickEffect(SDL_HIDAPI_Device *device, SDL_Joystick *joy
|
||||
}
|
||||
}
|
||||
|
||||
return SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size);
|
||||
if (SDL_HIDAPI_SendRumbleAndUnlock(device, data, report_size) != report_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -957,7 +969,10 @@ HIDAPI_DriverPS5_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev,
|
||||
axis = ((int)packet->ucRightJoystickY * 257) - 32768;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
||||
|
||||
if (packet->ucBatteryLevel & 0x10) {
|
||||
/* A check of packet->ucBatteryLevel & 0x10 should work as a check for BT vs USB but doesn't
|
||||
* seem to always work. Possibly related to being 100% charged?
|
||||
*/
|
||||
if (!ctx->is_bluetooth) {
|
||||
/* 0x20 set means fully charged */
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
|
||||
} else {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -53,7 +53,7 @@ typedef struct SDL_HIDAPI_RumbleContext
|
||||
|
||||
static SDL_HIDAPI_RumbleContext rumble_context;
|
||||
|
||||
static int SDL_HIDAPI_RumbleThread(void *data)
|
||||
static int SDLCALL SDL_HIDAPI_RumbleThread(void *data)
|
||||
{
|
||||
SDL_HIDAPI_RumbleContext *ctx = (SDL_HIDAPI_RumbleContext *)data;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -55,7 +55,7 @@ HIDAPI_DriverStadia_IsSupportedDevice(const char *name, SDL_GameControllerType t
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverStadia_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverStadia_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return "Google Stadia Controller";
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -1004,7 +1004,7 @@ HIDAPI_DriverSteam_IsSupportedDevice(const char *name, SDL_GameControllerType ty
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverSteam_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverSteam_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return "Steam Controller";
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -63,6 +63,11 @@
|
||||
#define SWITCH_GYRO_SCALE 14.2842f
|
||||
#define SWITCH_ACCEL_SCALE 4096.f
|
||||
|
||||
#define SWITCH_GYRO_SCALE_OFFSET 13371.0f
|
||||
#define SWITCH_GYRO_SCALE_MULT 936.0f
|
||||
#define SWITCH_ACCEL_SCALE_OFFSET 16384.0f
|
||||
#define SWITCH_ACCEL_SCALE_MULT 4.0f
|
||||
|
||||
typedef enum {
|
||||
k_eSwitchInputReportIDs_SubcommandReply = 0x21,
|
||||
k_eSwitchInputReportIDs_FullControllerState = 0x30,
|
||||
@@ -114,6 +119,14 @@ typedef enum {
|
||||
#define k_unSPIStickCalibrationEndOffset 0x604E
|
||||
#define k_unSPIStickCalibrationLength (k_unSPIStickCalibrationEndOffset - k_unSPIStickCalibrationStartOffset + 1)
|
||||
|
||||
#define k_unSPIIMUScaleStartOffset 0x6020
|
||||
#define k_unSPIIMUScaleEndOffset 0x6037
|
||||
#define k_unSPIIMUScaleLength (k_unSPIIMUScaleEndOffset - k_unSPIIMUScaleStartOffset + 1)
|
||||
|
||||
#define k_unSPIIMUUserScaleStartOffset 0x8026
|
||||
#define k_unSPIIMUUserScaleEndOffset 0x8039
|
||||
#define k_unSPIIMUUserScaleLength (k_unSPIIMUUserScaleEndOffset - k_unSPIIMUUserScaleStartOffset + 1)
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
@@ -266,6 +279,16 @@ typedef struct {
|
||||
Sint16 sMax;
|
||||
} axis[2];
|
||||
} m_StickExtents[2];
|
||||
|
||||
struct IMUScaleData {
|
||||
float fAccelScaleX;
|
||||
float fAccelScaleY;
|
||||
float fAccelScaleZ;
|
||||
|
||||
float fGyroScaleX;
|
||||
float fGyroScaleY;
|
||||
float fGyroScaleZ;
|
||||
} m_IMUScaleData;
|
||||
} SDL_DriverSwitch_Context;
|
||||
|
||||
|
||||
@@ -282,9 +305,29 @@ HasHomeLED(int vendor_id, int product_id)
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* The Nintendo Online classic controllers don't have a Home LED */
|
||||
if (vendor_id == USB_VENDOR_NINTENDO &&
|
||||
(product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER ||
|
||||
product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER ||
|
||||
product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER)) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
AlwaysUsesLabels(int vendor_id, int product_id)
|
||||
{
|
||||
/* These controllers don't have a diamond button configuration, so always use labels */
|
||||
if (vendor_id == USB_VENDOR_NINTENDO &&
|
||||
(product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER ||
|
||||
product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER)) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
IsGameCubeFormFactor(int vendor_id, int product_id)
|
||||
{
|
||||
@@ -319,7 +362,7 @@ HIDAPI_DriverSwitch_IsSupportedDevice(const char *name, SDL_GameControllerType t
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverSwitch_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverSwitch_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
/* Give a user friendly name for this controller */
|
||||
if (vendor_id == USB_VENDOR_NINTENDO) {
|
||||
@@ -332,8 +375,24 @@ HIDAPI_DriverSwitch_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
}
|
||||
|
||||
if (product_id == USB_PRODUCT_NINTENDO_SWITCH_JOY_CON_RIGHT) {
|
||||
/* Use the given name for the Nintendo Online NES Controllers */
|
||||
if (SDL_strncmp(name, "NES Controller", 14) == 0) {
|
||||
return name;
|
||||
}
|
||||
return "Nintendo Switch Joy-Con Right";
|
||||
}
|
||||
|
||||
if (product_id == USB_PRODUCT_NINTENDO_N64_CONTROLLER) {
|
||||
return "Nintendo N64 Controller";
|
||||
}
|
||||
|
||||
if (product_id == USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER) {
|
||||
return "Nintendo SEGA Genesis Controller";
|
||||
}
|
||||
|
||||
if (product_id == USB_PRODUCT_NINTENDO_SNES_CONTROLLER) {
|
||||
return "Nintendo SNES Controller";
|
||||
}
|
||||
}
|
||||
|
||||
return "Nintendo Switch Pro Controller";
|
||||
@@ -769,6 +828,72 @@ static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx, Uint8 input_
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static SDL_bool LoadIMUCalibration(SDL_DriverSwitch_Context* ctx)
|
||||
{
|
||||
Uint8* pIMUScale;
|
||||
SwitchSubcommandInputPacket_t* reply = NULL;
|
||||
Sint16 sAccelRawX, sAccelRawY, sAccelRawZ, sGyroRawX, sGyroRawY, sGyroRawZ;
|
||||
|
||||
/* Read Calibration Info */
|
||||
SwitchSPIOpData_t readParams;
|
||||
readParams.unAddress = k_unSPIIMUScaleStartOffset;
|
||||
readParams.ucLength = k_unSPIIMUScaleLength;
|
||||
|
||||
if (!WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t*)&readParams, sizeof(readParams), &reply)) {
|
||||
const float accelScale = SDL_STANDARD_GRAVITY / SWITCH_ACCEL_SCALE;
|
||||
const float gyroScale = (float)M_PI / 180.0f / SWITCH_GYRO_SCALE;
|
||||
|
||||
ctx->m_IMUScaleData.fAccelScaleX = accelScale;
|
||||
ctx->m_IMUScaleData.fAccelScaleY = accelScale;
|
||||
ctx->m_IMUScaleData.fAccelScaleZ = accelScale;
|
||||
|
||||
ctx->m_IMUScaleData.fGyroScaleX = gyroScale;
|
||||
ctx->m_IMUScaleData.fGyroScaleY = gyroScale;
|
||||
ctx->m_IMUScaleData.fGyroScaleZ = gyroScale;
|
||||
|
||||
return SDL_FALSE;
|
||||
}
|
||||
|
||||
/* IMU scale gives us multipliers for converting raw values to real world values */
|
||||
pIMUScale = reply->spiReadData.rgucReadData;
|
||||
|
||||
sAccelRawX = ((pIMUScale[1] << 8) & 0xF00) | pIMUScale[0];
|
||||
sAccelRawY = ((pIMUScale[3] << 8) & 0xF00) | pIMUScale[2];
|
||||
sAccelRawZ = ((pIMUScale[5] << 8) & 0xF00) | pIMUScale[4];
|
||||
|
||||
sGyroRawX = ((pIMUScale[13] << 8) & 0xF00) | pIMUScale[12];
|
||||
sGyroRawY = ((pIMUScale[15] << 8) & 0xF00) | pIMUScale[14];
|
||||
sGyroRawZ = ((pIMUScale[17] << 8) & 0xF00) | pIMUScale[16];
|
||||
|
||||
/* Check for user calibration data. If it's present and set, it'll override the factory settings */
|
||||
readParams.unAddress = k_unSPIIMUUserScaleStartOffset;
|
||||
readParams.ucLength = k_unSPIIMUUserScaleLength;
|
||||
if (WriteSubcommand(ctx, k_eSwitchSubcommandIDs_SPIFlashRead, (uint8_t*)&readParams, sizeof(readParams), &reply) && (pIMUScale[0] | pIMUScale[1] << 8) == 0xA1B2) {
|
||||
pIMUScale = reply->spiReadData.rgucReadData;
|
||||
|
||||
sAccelRawX = ((pIMUScale[3] << 8) & 0xF00) | pIMUScale[2];
|
||||
sAccelRawY = ((pIMUScale[5] << 8) & 0xF00) | pIMUScale[4];
|
||||
sAccelRawZ = ((pIMUScale[7] << 8) & 0xF00) | pIMUScale[6];
|
||||
|
||||
sGyroRawX = ((pIMUScale[15] << 8) & 0xF00) | pIMUScale[14];
|
||||
sGyroRawY = ((pIMUScale[17] << 8) & 0xF00) | pIMUScale[16];
|
||||
sGyroRawZ = ((pIMUScale[19] << 8) & 0xF00) | pIMUScale[18];
|
||||
}
|
||||
|
||||
/* Accelerometer scale */
|
||||
ctx->m_IMUScaleData.fAccelScaleX = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawX) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleY = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawY) * SDL_STANDARD_GRAVITY;
|
||||
ctx->m_IMUScaleData.fAccelScaleZ = SWITCH_ACCEL_SCALE_MULT / (float)(SWITCH_ACCEL_SCALE_OFFSET - (float)sAccelRawZ) * SDL_STANDARD_GRAVITY;
|
||||
|
||||
/* Gyro scale */
|
||||
ctx->m_IMUScaleData.fGyroScaleX = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawX) * (float)M_PI / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleY = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawY) * (float)M_PI / 180.0f;
|
||||
ctx->m_IMUScaleData.fGyroScaleZ = SWITCH_GYRO_SCALE_MULT / (float)(SWITCH_GYRO_SCALE_OFFSET - (float)sGyroRawZ) * (float)M_PI / 180.0f;
|
||||
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
static Sint16 ApplyStickCalibrationCentered(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue, Sint16 sCenter)
|
||||
{
|
||||
sRawValue -= sCenter;
|
||||
@@ -914,6 +1039,11 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!LoadIMUCalibration(ctx)) {
|
||||
SDL_SetError("Couldn't load sensor calibration");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!SetVibrationEnabled(ctx, 1)) {
|
||||
SDL_SetError("Couldn't enable vibration");
|
||||
goto error;
|
||||
@@ -967,8 +1097,12 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
|
||||
ctx->m_bIsGameCube = SDL_TRUE;
|
||||
}
|
||||
|
||||
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||
if (AlwaysUsesLabels(device->vendor_id, device->product_id)) {
|
||||
ctx->m_bUseButtonLabels = SDL_TRUE;
|
||||
} else {
|
||||
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||
}
|
||||
|
||||
/* Initialize the joystick capabilities */
|
||||
if (ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft ||
|
||||
@@ -1023,8 +1157,7 @@ HIDAPI_DriverSwitch_ActuallyRumbleJoystick(SDL_DriverSwitch_Context *ctx, Uint16
|
||||
ctx->m_bRumbleActive = (low_frequency_rumble || high_frequency_rumble) ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
if (!WriteRumble(ctx)) {
|
||||
SDL_SetError("Couldn't send rumble packet");
|
||||
return -1;
|
||||
return SDL_SetError("Couldn't send rumble packet");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1147,20 +1280,6 @@ HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joy
|
||||
return 0;
|
||||
}
|
||||
|
||||
static float
|
||||
HIDAPI_DriverSwitch_ScaleGyro(Sint16 value)
|
||||
{
|
||||
float result = (value / SWITCH_GYRO_SCALE) * (float)M_PI / 180.0f;
|
||||
return result;
|
||||
}
|
||||
|
||||
static float
|
||||
HIDAPI_DriverSwitch_ScaleAccel(Sint16 value)
|
||||
{
|
||||
float result = (value / SWITCH_ACCEL_SCALE) * SDL_STANDARD_GRAVITY;
|
||||
return result;
|
||||
}
|
||||
|
||||
static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchInputOnlyControllerStatePacket_t *packet)
|
||||
{
|
||||
Sint16 axis;
|
||||
@@ -1358,13 +1477,13 @@ static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *c
|
||||
* users will want consistent axis mappings across devices.
|
||||
*/
|
||||
if (type == SDL_SENSOR_GYRO) {
|
||||
data[0] = -HIDAPI_DriverSwitch_ScaleGyro(values[1]);
|
||||
data[1] = HIDAPI_DriverSwitch_ScaleGyro(values[2]);
|
||||
data[2] = -HIDAPI_DriverSwitch_ScaleGyro(values[0]);
|
||||
data[0] = -(ctx->m_IMUScaleData.fGyroScaleY * (float)values[1]);
|
||||
data[1] = ctx->m_IMUScaleData.fGyroScaleZ * (float)values[2];
|
||||
data[2] = -(ctx->m_IMUScaleData.fGyroScaleX * (float)values[0]);
|
||||
} else {
|
||||
data[0] = -HIDAPI_DriverSwitch_ScaleAccel(values[1]);
|
||||
data[1] = HIDAPI_DriverSwitch_ScaleAccel(values[2]);
|
||||
data[2] = -HIDAPI_DriverSwitch_ScaleAccel(values[0]);
|
||||
data[0] = -(ctx->m_IMUScaleData.fAccelScaleY * (float)values[1]);
|
||||
data[1] = ctx->m_IMUScaleData.fAccelScaleZ * (float)values[2];
|
||||
data[2] = -(ctx->m_IMUScaleData.fAccelScaleX * (float)values[0]);
|
||||
}
|
||||
|
||||
/* Right Joy-Con flips some axes, so let's flip them back for consistency */
|
||||
@@ -1441,20 +1560,20 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
||||
* LSB of connection nibble is USB/Switch connection status
|
||||
*/
|
||||
if (packet->controllerState.ucBatteryAndConnection & 0x1) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_WIRED;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_WIRED);
|
||||
} else {
|
||||
/* LSB of the battery nibble is used to report charging.
|
||||
* The battery level is reported from 0(empty)-8(full)
|
||||
*/
|
||||
int level = (packet->controllerState.ucBatteryAndConnection & 0xE0) >> 4;
|
||||
if (level == 0) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
|
||||
} else if (level <= 2) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
|
||||
} else if (level <= 6) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
|
||||
} else {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -83,7 +83,7 @@ HIDAPI_DriverXbox360_IsSupportedDevice(const char *name, SDL_GameControllerType
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverXbox360_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverXbox360_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -57,7 +57,7 @@ HIDAPI_DriverXbox360W_IsSupportedDevice(const char *name, SDL_GameControllerType
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverXbox360W_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverXbox360W_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return "Xbox 360 Wireless Controller";
|
||||
}
|
||||
@@ -81,13 +81,13 @@ UpdatePowerLevel(SDL_Joystick *joystick, Uint8 level)
|
||||
float normalized_level = (float)level / 255.0f;
|
||||
|
||||
if (normalized_level <= 0.05f) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_EMPTY;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_EMPTY);
|
||||
} else if (normalized_level <= 0.20f) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_LOW;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_LOW);
|
||||
} else if (normalized_level <= 0.70f) {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_MEDIUM;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_MEDIUM);
|
||||
} else {
|
||||
joystick->epowerlevel = SDL_JOYSTICK_POWER_FULL;
|
||||
SDL_PrivateJoystickBatteryLevel(joystick, SDL_JOYSTICK_POWER_FULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -43,6 +43,10 @@
|
||||
#define CONTROLLER_NEGOTIATION_TIMEOUT_MS 300
|
||||
#define CONTROLLER_PREPARE_INPUT_TIMEOUT_MS 50
|
||||
|
||||
/* Deadzone thresholds */
|
||||
#define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
|
||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD -25058 /* Uint8 30 scaled to Sint16 full range */
|
||||
|
||||
/* Start controller */
|
||||
static const Uint8 xboxone_init0[] = {
|
||||
@@ -281,7 +285,7 @@ HIDAPI_DriverXboxOne_IsSupportedDevice(const char *name, SDL_GameControllerType
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_DriverXboxOne_GetDeviceName(Uint16 vendor_id, Uint16 product_id)
|
||||
HIDAPI_DriverXboxOne_GetDeviceName(const char *name, Uint16 vendor_id, Uint16 product_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
@@ -822,15 +826,6 @@ HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, SDL_Driv
|
||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_DPAD_LEFT, dpad_left);
|
||||
}
|
||||
|
||||
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
|
||||
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
|
||||
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
||||
|
||||
axis = ((int)*(Sint16*)(&data[9]) * 64) - 32768;
|
||||
if (axis == 32704) {
|
||||
axis = 32767;
|
||||
@@ -843,6 +838,15 @@ HIDAPI_DriverXboxOneBluetooth_HandleStatePacket(SDL_Joystick *joystick, SDL_Driv
|
||||
}
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
||||
|
||||
axis = (int)*(Uint16*)(&data[1]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTX, axis);
|
||||
axis = (int)*(Uint16*)(&data[3]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_LEFTY, axis);
|
||||
axis = (int)*(Uint16*)(&data[5]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTX, axis);
|
||||
axis = (int)*(Uint16*)(&data[7]) - 0x8000;
|
||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
|
||||
|
||||
SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -110,11 +110,96 @@ HIDAPI_RemapVal(float val, float val_min, float val_max, float output_min, float
|
||||
static void HIDAPI_JoystickDetect(void);
|
||||
static void HIDAPI_JoystickClose(SDL_Joystick *joystick);
|
||||
|
||||
static SDL_GameControllerType
|
||||
SDL_GetJoystickGameControllerProtocol(const char *name, Uint16 vendor, Uint16 product, int interface_number, int interface_class, int interface_subclass, int interface_protocol)
|
||||
{
|
||||
static const int LIBUSB_CLASS_VENDOR_SPEC = 0xFF;
|
||||
static const int XB360_IFACE_SUBCLASS = 93;
|
||||
static const int XB360_IFACE_PROTOCOL = 1; /* Wired */
|
||||
static const int XB360W_IFACE_PROTOCOL = 129; /* Wireless */
|
||||
static const int XBONE_IFACE_SUBCLASS = 71;
|
||||
static const int XBONE_IFACE_PROTOCOL = 208;
|
||||
|
||||
SDL_GameControllerType type = SDL_CONTROLLER_TYPE_UNKNOWN;
|
||||
|
||||
/* This code should match the checks in libusb/hid.c and HIDDeviceManager.java */
|
||||
if (interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
interface_subclass == XB360_IFACE_SUBCLASS &&
|
||||
(interface_protocol == XB360_IFACE_PROTOCOL ||
|
||||
interface_protocol == XB360W_IFACE_PROTOCOL)) {
|
||||
|
||||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x0079, /* GPD Win 2 */
|
||||
0x044f, /* Thrustmaster */
|
||||
0x045e, /* Microsoft */
|
||||
0x046d, /* Logitech */
|
||||
0x056e, /* Elecom */
|
||||
0x06a3, /* Saitek */
|
||||
0x0738, /* Mad Catz */
|
||||
0x07ff, /* Mad Catz */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1038, /* SteelSeries */
|
||||
0x11c9, /* Nacon */
|
||||
0x12ab, /* Unknown */
|
||||
0x1430, /* RedOctane */
|
||||
0x146b, /* BigBen */
|
||||
0x1532, /* Razer */
|
||||
0x15e4, /* Numark */
|
||||
0x162e, /* Joytech */
|
||||
0x1689, /* Razer Onza */
|
||||
0x1949, /* Lab126, Inc. */
|
||||
0x1bad, /* Harmonix */
|
||||
0x20d6, /* PowerA */
|
||||
0x24c6, /* PowerA */
|
||||
0x2c22, /* Qanba */
|
||||
};
|
||||
|
||||
int i;
|
||||
for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
|
||||
if (vendor == SUPPORTED_VENDORS[i]) {
|
||||
type = SDL_CONTROLLER_TYPE_XBOX360;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (interface_number == 0 &&
|
||||
interface_class == LIBUSB_CLASS_VENDOR_SPEC &&
|
||||
interface_subclass == XBONE_IFACE_SUBCLASS &&
|
||||
interface_protocol == XBONE_IFACE_PROTOCOL) {
|
||||
|
||||
static const int SUPPORTED_VENDORS[] = {
|
||||
0x045e, /* Microsoft */
|
||||
0x0738, /* Mad Catz */
|
||||
0x0e6f, /* PDP */
|
||||
0x0f0d, /* Hori */
|
||||
0x1532, /* Razer */
|
||||
0x20d6, /* PowerA */
|
||||
0x24c6, /* PowerA */
|
||||
0x2e24, /* Hyperkin */
|
||||
};
|
||||
|
||||
int i;
|
||||
for (i = 0; i < SDL_arraysize(SUPPORTED_VENDORS); ++i) {
|
||||
if (vendor == SUPPORTED_VENDORS[i]) {
|
||||
type = SDL_CONTROLLER_TYPE_XBOXONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == SDL_CONTROLLER_TYPE_UNKNOWN) {
|
||||
type = SDL_GetJoystickGameControllerTypeFromVIDPID(vendor, product, name, SDL_FALSE);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
HIDAPI_IsDeviceSupported(Uint16 vendor_id, Uint16 product_id, Uint16 version, const char *name)
|
||||
{
|
||||
int i;
|
||||
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(name, vendor_id, product_id, -1, 0, 0, 0);
|
||||
SDL_GameControllerType type = SDL_GetJoystickGameControllerProtocol(name, vendor_id, product_id, -1, 0, 0, 0);
|
||||
|
||||
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||
@@ -134,14 +219,8 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
|
||||
const Uint16 USAGE_MULTIAXISCONTROLLER = 0x0008;
|
||||
int i;
|
||||
SDL_GameControllerType type;
|
||||
SDL_JoystickGUID check_guid;
|
||||
|
||||
/* Make sure we have a generic GUID here, otherwise if we pass a HIDAPI
|
||||
guid, this call will create a game controller mapping for the device.
|
||||
*/
|
||||
check_guid = device->guid;
|
||||
check_guid.data[14] = 0;
|
||||
if (SDL_ShouldIgnoreJoystick(device->name, check_guid)) {
|
||||
if (SDL_ShouldIgnoreJoystick(device->name, device->guid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -154,7 +233,7 @@ HIDAPI_GetDeviceDriver(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
}
|
||||
|
||||
type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
|
||||
type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
|
||||
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
||||
SDL_HIDAPI_DeviceDriver *driver = SDL_HIDAPI_drivers[i];
|
||||
if (driver->enabled && driver->IsSupportedDevice(device->name, type, device->vendor_id, device->product_id, device->version, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
|
||||
@@ -206,8 +285,8 @@ HIDAPI_SetupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||
|
||||
device->driver = HIDAPI_GetDeviceDriver(device);
|
||||
if (device->driver) {
|
||||
const char *name = device->driver->GetDeviceName(device->vendor_id, device->product_id);
|
||||
if (name) {
|
||||
const char *name = device->driver->GetDeviceName(device->name, device->vendor_id, device->product_id);
|
||||
if (name && name != device->name) {
|
||||
SDL_free(device->name);
|
||||
device->name = SDL_strdup(name);
|
||||
}
|
||||
@@ -227,7 +306,7 @@ HIDAPI_CleanupDeviceDriver(SDL_HIDAPI_Device *device)
|
||||
}
|
||||
|
||||
/* Disconnect any joysticks */
|
||||
while (device->num_joysticks) {
|
||||
while (device->num_joysticks && device->joysticks) {
|
||||
HIDAPI_JoystickDisconnected(device, device->joysticks[0]);
|
||||
}
|
||||
|
||||
@@ -309,8 +388,7 @@ HIDAPI_JoystickInit(void)
|
||||
#endif
|
||||
|
||||
if (SDL_hid_init() < 0) {
|
||||
SDL_SetError("Couldn't initialize hidapi");
|
||||
return -1;
|
||||
return SDL_SetError("Couldn't initialize hidapi");
|
||||
}
|
||||
|
||||
for (i = 0; i < SDL_arraysize(SDL_HIDAPI_drivers); ++i) {
|
||||
@@ -464,38 +542,6 @@ HIDAPI_AddDevice(struct SDL_hid_device_info *info)
|
||||
char *serial_number = HIDAPI_ConvertString(info->serial_number);
|
||||
|
||||
device->name = SDL_CreateJoystickName(device->vendor_id, device->product_id, manufacturer_string, product_string);
|
||||
if (SDL_strncmp(device->name, "0x", 2) == 0) {
|
||||
/* Couldn't find a controller name, try to give it one based on device type */
|
||||
const char *name = NULL;
|
||||
|
||||
switch (SDL_GetJoystickGameControllerType(NULL, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol)) {
|
||||
case SDL_CONTROLLER_TYPE_XBOX360:
|
||||
name = "Xbox 360 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_XBOXONE:
|
||||
name = "Xbox One Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS3:
|
||||
name = "PS3 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS4:
|
||||
name = "PS4 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_PS5:
|
||||
name = "PS5 Controller";
|
||||
break;
|
||||
case SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO:
|
||||
name = "Nintendo Switch Pro Controller";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (name) {
|
||||
SDL_free(device->name);
|
||||
device->name = SDL_strdup(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (manufacturer_string) {
|
||||
SDL_free(manufacturer_string);
|
||||
@@ -628,13 +674,13 @@ HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Devi
|
||||
|
||||
/* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */
|
||||
if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER &&
|
||||
SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
|
||||
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
/* If we're looking for an XInput controller, match it against any other Xbox controller */
|
||||
if (product_id == USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER) {
|
||||
SDL_GameControllerType type = SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
|
||||
SDL_GameControllerType type = SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol);
|
||||
if (type == SDL_CONTROLLER_TYPE_XBOX360 || type == SDL_CONTROLLER_TYPE_XBOXONE) {
|
||||
return SDL_TRUE;
|
||||
}
|
||||
@@ -663,7 +709,7 @@ HIDAPI_IsDeviceTypePresent(SDL_GameControllerType type)
|
||||
device = SDL_HIDAPI_devices;
|
||||
while (device) {
|
||||
if (device->driver &&
|
||||
SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
|
||||
SDL_GetJoystickGameControllerProtocol(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == type) {
|
||||
result = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -784,6 +830,21 @@ HIDAPI_JoystickGetDeviceName(int device_index)
|
||||
return name;
|
||||
}
|
||||
|
||||
static const char *
|
||||
HIDAPI_JoystickGetDevicePath(int device_index)
|
||||
{
|
||||
SDL_HIDAPI_Device *device;
|
||||
const char *path = NULL;
|
||||
|
||||
device = HIDAPI_GetDeviceByIndex(device_index, NULL);
|
||||
if (device) {
|
||||
/* FIXME: The device could be freed after this path is returned... */
|
||||
path = device->path;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static int
|
||||
HIDAPI_JoystickGetDevicePlayerIndex(int device_index)
|
||||
{
|
||||
@@ -871,8 +932,7 @@ HIDAPI_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint1
|
||||
|
||||
result = device->driver->RumbleJoystick(device, joystick, low_frequency_rumble, high_frequency_rumble);
|
||||
} else {
|
||||
SDL_SetError("Rumble failed, device disconnected");
|
||||
result = -1;
|
||||
result = SDL_SetError("Rumble failed, device disconnected");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -888,8 +948,7 @@ HIDAPI_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16
|
||||
|
||||
result = device->driver->RumbleJoystickTriggers(device, joystick, left_rumble, right_rumble);
|
||||
} else {
|
||||
SDL_SetError("Rumble failed, device disconnected");
|
||||
result = -1;
|
||||
result = SDL_SetError("Rumble failed, device disconnected");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -919,8 +978,7 @@ HIDAPI_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue
|
||||
|
||||
result = device->driver->SetJoystickLED(device, joystick, red, green, blue);
|
||||
} else {
|
||||
SDL_SetError("SetLED failed, device disconnected");
|
||||
result = -1;
|
||||
result = SDL_SetError("SetLED failed, device disconnected");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -936,8 +994,7 @@ HIDAPI_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size)
|
||||
|
||||
result = device->driver->SendJoystickEffect(device, joystick, data, size);
|
||||
} else {
|
||||
SDL_SetError("SendEffect failed, device disconnected");
|
||||
result = -1;
|
||||
result = SDL_SetError("SendEffect failed, device disconnected");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -953,8 +1010,7 @@ HIDAPI_JoystickSetSensorsEnabled(SDL_Joystick *joystick, SDL_bool enabled)
|
||||
|
||||
result = device->driver->SetJoystickSensorsEnabled(device, joystick, enabled);
|
||||
} else {
|
||||
SDL_SetError("SetSensorsEnabled failed, device disconnected");
|
||||
result = -1;
|
||||
result = SDL_SetError("SetSensorsEnabled failed, device disconnected");
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1036,6 +1092,7 @@ SDL_JoystickDriver SDL_HIDAPI_JoystickDriver =
|
||||
HIDAPI_JoystickGetCount,
|
||||
HIDAPI_JoystickDetect,
|
||||
HIDAPI_JoystickGetDeviceName,
|
||||
HIDAPI_JoystickGetDevicePath,
|
||||
HIDAPI_JoystickGetDevicePlayerIndex,
|
||||
HIDAPI_JoystickSetDevicePlayerIndex,
|
||||
HIDAPI_JoystickGetDeviceGUID,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org>
|
||||
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
@@ -90,7 +90,7 @@ typedef struct _SDL_HIDAPI_DeviceDriver
|
||||
SDL_bool enabled;
|
||||
SDL_bool enabled_default;
|
||||
SDL_bool (*IsSupportedDevice)(const char *name, SDL_GameControllerType type, Uint16 vendor_id, Uint16 product_id, Uint16 version, int interface_number, int interface_class, int interface_subclass, int interface_protocol);
|
||||
const char *(*GetDeviceName)(Uint16 vendor_id, Uint16 product_id);
|
||||
const char *(*GetDeviceName)(const char *name, Uint16 vendor_id, Uint16 product_id);
|
||||
SDL_bool (*InitDevice)(SDL_HIDAPI_Device *device);
|
||||
int (*GetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id);
|
||||
void (*SetDevicePlayerIndex)(SDL_HIDAPI_Device *device, SDL_JoystickID instance_id, int player_index);
|
||||
|
Reference in New Issue
Block a user