From 4018f35ef2787a3a177f28ec5100510e41691e8a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 7 Sep 2022 00:00:27 -0700
Subject: [PATCH] Added left and right sensors for Nintendo Joy-Con and Wii
controllers
---
include/SDL_sensor.h | 6 ++-
src/joystick/hidapi/SDL_hidapi_switch.c | 54 +++++++++++++++++++------
src/joystick/hidapi/SDL_hidapi_wii.c | 7 ++--
test/testgamecontroller.c | 49 ++++++++++++++++------
4 files changed, 87 insertions(+), 29 deletions(-)
diff --git a/include/SDL_sensor.h b/include/SDL_sensor.h
index a2f30e0f8f6..6b07183eadf 100644
--- a/include/SDL_sensor.h
+++ b/include/SDL_sensor.h
@@ -71,7 +71,11 @@ typedef enum
SDL_SENSOR_INVALID = -1, /**< Returned for an invalid sensor */
SDL_SENSOR_UNKNOWN, /**< Unknown sensor type */
SDL_SENSOR_ACCEL, /**< Accelerometer */
- SDL_SENSOR_GYRO /**< Gyroscope */
+ SDL_SENSOR_GYRO, /**< Gyroscope */
+ SDL_SENSOR_ACCEL_L, /**< Accelerometer for left Joy-Con controller and Wii nunchuk */
+ SDL_SENSOR_GYRO_L, /**< Gyroscope for left Joy-Con controller */
+ SDL_SENSOR_ACCEL_R, /**< Accelerometer for right Joy-Con controller */
+ SDL_SENSOR_GYRO_R /**< Gyroscope for right Joy-Con controller */
} SDL_SensorType;
/**
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index 799dbb1cf50..727b59ce1a1 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -254,7 +254,6 @@ typedef struct {
SDL_bool m_bRumblePending;
SDL_bool m_bRumbleZeroPending;
Uint32 m_unRumblePending;
- SDL_bool m_bHasSensors;
SDL_bool m_bReportSensors;
SDL_bool m_bHasSensorData;
Uint32 m_unLastInput;
@@ -1351,7 +1350,16 @@ HIDAPI_DriverSwitch_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joysti
ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 200.0f);
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 200.0f);
- ctx->m_bHasSensors = SDL_TRUE;
+ }
+ if (device->parent &&
+ ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_L, 200.0f);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 200.0f);
+ }
+ if (device->parent &&
+ ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO_R, 200.0f);
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_R, 200.0f);
}
}
@@ -1610,10 +1618,6 @@ HIDAPI_DriverSwitch_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joy
{
SDL_DriverSwitch_Context* ctx = (SDL_DriverSwitch_Context*)device->context;
- if (!ctx->m_bHasSensors) {
- return SDL_Unsupported();
- }
-
SetIMUEnabled(ctx, enabled);
ctx->m_bReportSensors = enabled;
@@ -1816,7 +1820,7 @@ static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *c
* since that's our de facto standard from already supporting those controllers, and
* users will want consistent axis mappings across devices.
*/
- if (type == SDL_SENSOR_GYRO) {
+ if (type == SDL_SENSOR_GYRO || type == SDL_SENSOR_GYRO_L || type == SDL_SENSOR_GYRO_R ) {
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]);
@@ -2068,13 +2072,37 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
if (bHasSensorData) {
ctx->m_bHasSensorData = SDL_TRUE;
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[2].sGyroX);
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[1].sGyroX);
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[0].sGyroX);
+ if (!ctx->device->parent ||
+ ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[2].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[1].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO, &packet->imuState[0].sGyroX);
+
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[2].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[1].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[0].sAccelX);
+ }
+
+ if (ctx->device->parent &&
+ ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_L, &packet->imuState[2].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_L, &packet->imuState[1].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_L, &packet->imuState[0].sGyroX);
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[2].sAccelX);
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[1].sAccelX);
- SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL, &packet->imuState[0].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_L, &packet->imuState[2].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_L, &packet->imuState[1].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_L, &packet->imuState[0].sAccelX);
+ }
+ if (ctx->device->parent &&
+ ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_R, &packet->imuState[2].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_R, &packet->imuState[1].sGyroX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_GYRO_R, &packet->imuState[0].sGyroX);
+
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_R, &packet->imuState[2].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_R, &packet->imuState[1].sAccelX);
+ SendSensorUpdate(joystick, ctx, SDL_SENSOR_ACCEL_R, &packet->imuState[0].sAccelX);
+ }
} else if (ctx->m_bHasSensorData) {
/* Uh oh, someone turned off the IMU? */
diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c
index b000a036f96..0b9922fad67 100644
--- a/src/joystick/hidapi/SDL_hidapi_wii.c
+++ b/src/joystick/hidapi/SDL_hidapi_wii.c
@@ -809,6 +809,9 @@ HIDAPI_DriverWii_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystick *joystick)
if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_None ||
ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Nunchuk) {
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 100.0f);
+ if (ctx->m_eExtensionControllerType == k_eWiiExtensionControllerType_Nunchuk) {
+ SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL_L, 100.0f);
+ }
if (ctx->m_bMotionPlusPresent) {
SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 100.0f);
@@ -1162,7 +1165,6 @@ static void HandleNunchuckButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *j
PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[0], SDL_CONTROLLER_AXIS_LEFTX, data->rgucExtension[0]);
PostStickCalibrated(joystick, &ctx->m_StickCalibrationData[1], SDL_CONTROLLER_AXIS_LEFTY, data->rgucExtension[1]);
-#if 0 /* We'll report this when we have the concept of right/left sensors */
if (ctx->m_bReportSensors) {
const float ACCEL_RES_PER_G = 200.0f;
Sint16 x, y, z;
@@ -1190,9 +1192,8 @@ static void HandleNunchuckButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *j
values[0] = -((float)x / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
values[1] = ((float)z / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
values[2] = ((float)y / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY;
- SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3);
+ SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL_L, values, 3);
}
-#endif
}
static void HandleMotionPlusData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, const WiiButtonData *data)
diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c
index 7e51bcbfcef..2dc32d60e17 100644
--- a/test/testgamecontroller.c
+++ b/test/testgamecontroller.c
@@ -127,6 +127,26 @@ static void UpdateWindowTitle()
}
}
+static const char *GetSensorName(SDL_SensorType sensor)
+{
+ switch (sensor) {
+ case SDL_SENSOR_ACCEL:
+ return "accelerometer";
+ case SDL_SENSOR_GYRO:
+ return "gyro";
+ case SDL_SENSOR_ACCEL_L:
+ return "accelerometer (L)";
+ case SDL_SENSOR_GYRO_L:
+ return "gyro (L)";
+ case SDL_SENSOR_ACCEL_R:
+ return "accelerometer (R)";
+ case SDL_SENSOR_GYRO_R:
+ return "gyro (R)";
+ default:
+ return "UNKNOWN";
+ }
+}
+
static int FindController(SDL_JoystickID controller_id)
{
int i;
@@ -145,6 +165,15 @@ static void AddController(int device_index, SDL_bool verbose)
SDL_GameController *controller;
SDL_GameController **controllers;
Uint16 firmware_version;
+ SDL_SensorType sensors[] = {
+ SDL_SENSOR_ACCEL,
+ SDL_SENSOR_GYRO,
+ SDL_SENSOR_ACCEL_L,
+ SDL_SENSOR_GYRO_L,
+ SDL_SENSOR_ACCEL_R,
+ SDL_SENSOR_GYRO_R
+ };
+ unsigned int i;
controller_id = SDL_JoystickGetDeviceInstanceID(device_index);
if (controller_id < 0) {
@@ -187,18 +216,15 @@ static void AddController(int device_index, SDL_bool verbose)
}
}
- if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_ACCEL)) {
- if (verbose) {
- SDL_Log("Enabling accelerometer at %.2f Hz\n", SDL_GameControllerGetSensorDataRate(gamecontroller, SDL_SENSOR_ACCEL));
- }
- SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_ACCEL, SDL_TRUE);
- }
+ for (i = 0; i < SDL_arraysize(sensors); ++i) {
+ SDL_SensorType sensor = sensors[i];
- if (SDL_GameControllerHasSensor(gamecontroller, SDL_SENSOR_GYRO)) {
- if (verbose) {
- SDL_Log("Enabling gyro at %.2f Hz\n", SDL_GameControllerGetSensorDataRate(gamecontroller, SDL_SENSOR_GYRO));
+ if (SDL_GameControllerHasSensor(gamecontroller, sensor)) {
+ if (verbose) {
+ SDL_Log("Enabling %s at %.2f Hz\n", GetSensorName(sensor), SDL_GameControllerGetSensorDataRate(gamecontroller, sensor));
+ }
+ SDL_GameControllerSetSensorEnabled(gamecontroller, sensor, SDL_TRUE);
}
- SDL_GameControllerSetSensorEnabled(gamecontroller, SDL_SENSOR_GYRO, SDL_TRUE);
}
if (SDL_GameControllerHasRumble(gamecontroller)) {
@@ -565,8 +591,7 @@ loop(void *arg)
case SDL_CONTROLLERSENSORUPDATE:
SDL_Log("Controller %d sensor %s: %.2f, %.2f, %.2f\n",
event.csensor.which,
- event.csensor.sensor == SDL_SENSOR_ACCEL ? "accelerometer" :
- event.csensor.sensor == SDL_SENSOR_GYRO ? "gyro" : "unknown",
+ GetSensorName((SDL_SensorType)event.csensor.sensor),
event.csensor.data[0],
event.csensor.data[1],
event.csensor.data[2]);