SDL: The `timestamp_us` member of the sensor events has been renamed `sensor_timestamp` and now represents nanoseconds.

From b8760a3ffe809321f4a2db128c06b227eba52bd0 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 4 Dec 2022 08:31:19 -0800
Subject: [PATCH] The `timestamp_us` member of the sensor events has been
 renamed `sensor_timestamp` and now represents nanoseconds.

---
 docs/README-migration.md                     |  2 +
 include/SDL3/SDL_events.h                    |  4 +-
 include/SDL3/SDL_gamecontroller.h            |  4 +-
 include/SDL3/SDL_sensor.h                    |  4 +-
 src/joystick/SDL_gamecontroller.c            |  2 +-
 src/joystick/SDL_joystick.c                  |  6 +--
 src/joystick/SDL_joystick_c.h                |  2 +-
 src/joystick/SDL_sysjoystick.h               |  2 +-
 src/joystick/apple/SDL_mfijoystick.m         |  4 +-
 src/joystick/hidapi/SDL_hidapi_ps3.c         |  2 +-
 src/joystick/hidapi/SDL_hidapi_ps4.c         | 34 ++++++--------
 src/joystick/hidapi/SDL_hidapi_ps5.c         | 40 +++++++---------
 src/joystick/hidapi/SDL_hidapi_steam.c       |  8 ++--
 src/joystick/hidapi/SDL_hidapi_switch.c      | 48 ++++++++++----------
 src/joystick/hidapi/SDL_hidapi_wii.c         |  6 +--
 src/joystick/windows/SDL_rawinputjoystick.c  |  4 +-
 src/sensor/SDL_sensor.c                      | 10 ++--
 src/sensor/SDL_sensor_c.h                    |  2 +-
 src/sensor/SDL_syssensor.h                   | 12 ++---
 src/sensor/android/SDL_androidsensor.c       |  3 +-
 src/sensor/coremotion/SDL_coremotionsensor.m |  6 ++-
 src/sensor/n3ds/SDL_n3dssensor.c             |  6 ++-
 src/sensor/vita/SDL_vitasensor.c             | 27 +++++------
 src/sensor/vita/SDL_vitasensor.h             |  4 +-
 src/sensor/windows/SDL_windowssensor.c       | 18 +++++++-
 test/testgamecontroller.c                    |  2 +-
 26 files changed, 134 insertions(+), 128 deletions(-)

diff --git a/docs/README-migration.md b/docs/README-migration.md
index cb0b4159db5d..0ee436feea98 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -35,6 +35,8 @@ The SDL3main and SDL3test libraries have been renamed SDL3_main and SDL3_test, r
 
 The `timestamp` member of the SDL_Event structure now represents nanoseconds, and is populated with `SDL_GetTicksNS()`
 
+The `timestamp_us` member of the sensor events has been renamed `sensor_timestamp` and now represents nanoseconds. This value is filled in from the hardware, if available, and may not be synchronized with values returned from SDL_GetTicksNS().
+
 You should set the `event.common.timestamp` field before passing an event to `SDL_PushEvent()`. If the timestamp is 0 it will be filled in with `SDL_GetTicksNS()`.
 
 
diff --git a/include/SDL3/SDL_events.h b/include/SDL3/SDL_events.h
index 2d4d712b9fff..6ce016db3407 100644
--- a/include/SDL3/SDL_events.h
+++ b/include/SDL3/SDL_events.h
@@ -476,7 +476,7 @@ typedef struct SDL_ControllerSensorEvent
     SDL_JoystickID which; /**< The joystick instance id */
     Sint32 sensor;      /**< The type of the sensor, one of the values of ::SDL_SensorType */
     float data[3];      /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
-    Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */
+    Uint64 sensor_timestamp; /**< The timestamp of the sensor reading in nanoseconds, not necessarily synchronized with the system clock */
 } SDL_ControllerSensorEvent;
 
 /**
@@ -568,7 +568,7 @@ typedef struct SDL_SensorEvent
     Uint64 timestamp;   /**< In nanoseconds, populated using SDL_GetTicksNS() */
     SDL_SensorID which;       /**< The instance ID of the sensor */
     float data[6];      /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
-    Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */
+    Uint64 sensor_timestamp; /**< The timestamp of the sensor reading in nanoseconds, not necessarily synchronized with the system clock */
 } SDL_SensorEvent;
 
 /**
diff --git a/include/SDL3/SDL_gamecontroller.h b/include/SDL3/SDL_gamecontroller.h
index 976ae17f2300..d992470252d7 100644
--- a/include/SDL3/SDL_gamecontroller.h
+++ b/include/SDL3/SDL_gamecontroller.h
@@ -904,8 +904,8 @@ extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *
  *
  * \param gamecontroller The controller to query
  * \param type The type of sensor to query
- * \param timestamp A pointer filled with the timestamp in microseconds of the
- *                  current sensor reading if available, or 0 if not
+ * \param timestamp A pointer filled with the timestamp in nanoseconds of the
+ *                  current sensor reading, which may not be synchronized with the system clock
  * \param data A pointer filled with the current sensor state
  * \param num_values The number of values to write to data
  * \return 0 or -1 if an error occurred.
diff --git a/include/SDL3/SDL_sensor.h b/include/SDL3/SDL_sensor.h
index 0f31e43cd1a8..d99c25fa85d5 100644
--- a/include/SDL3/SDL_sensor.h
+++ b/include/SDL3/SDL_sensor.h
@@ -276,8 +276,8 @@ extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor *sensor, float *data, i
  * The number of values and interpretation of the data is sensor dependent.
  *
  * \param sensor The SDL_Sensor object to query
- * \param timestamp A pointer filled with the timestamp in microseconds of the
- *                  current sensor reading if available, or 0 if not
+ * \param timestamp A pointer filled with the timestamp in nanoseconds of the
+ *                  current sensor reading, which may not be synchronized with the system clock
  * \param data A pointer filled with the current sensor state
  * \param num_values The number of values to write to data
  * \returns 0 or -1 if an error occurred.
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 0d62e24c90f2..95519d41be5c 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -2454,7 +2454,7 @@ int SDL_GameControllerGetSensorDataWithTimestamp(SDL_GameController *gamecontrol
             num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
             SDL_memcpy(data, sensor->data, num_values * sizeof(*data));
             if (timestamp) {
-                *timestamp = sensor->timestamp_us;
+                *timestamp = sensor->sensor_timestamp;
             }
             return 0;
         }
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 25bc84109b76..44effda6a20c 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -2960,7 +2960,7 @@ int SDL_PrivateJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick, int to
     return posted;
 }
 
-int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorType type, Uint64 timestamp_us, const float *data, int num_values)
+int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values)
 {
     int i;
     int posted = 0;
@@ -2981,7 +2981,7 @@ int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_Sens
 
                 /* Update internal sensor state */
                 SDL_memcpy(sensor->data, data, num_values * sizeof(*data));
-                sensor->timestamp_us = timestamp_us;
+                sensor->sensor_timestamp = sensor_timestamp;
 
                 /* Post the event, if desired */
 #if !SDL_EVENTS_DISABLED
@@ -2994,7 +2994,7 @@ int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick, SDL_Sens
                     num_values = SDL_min(num_values, SDL_arraysize(event.csensor.data));
                     SDL_memset(event.csensor.data, 0, sizeof(event.csensor.data));
                     SDL_memcpy(event.csensor.data, data, num_values * sizeof(*data));
-                    event.csensor.timestamp_us = timestamp_us;
+                    event.csensor.sensor_timestamp = sensor_timestamp;
                     posted = SDL_PushEvent(&event) == 1;
                 }
 #endif /* !SDL_EVENTS_DISABLED */
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index f5e6a6278144..d3e4076cab19 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -162,7 +162,7 @@ extern int SDL_PrivateJoystickButton(Uint64 timestamp, SDL_Joystick *joystick,
 extern int SDL_PrivateJoystickTouchpad(Uint64 timestamp, SDL_Joystick *joystick,
                                        int touchpad, int finger, Uint8 state, float x, float y, float pressure);
 extern int SDL_PrivateJoystickSensor(Uint64 timestamp, SDL_Joystick *joystick,
-                                     SDL_SensorType type, Uint64 timestamp_us, const float *data, int num_values);
+                                     SDL_SensorType type, Uint64 sensor_timestamp, const float *data, int num_values);
 extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick,
                                             SDL_JoystickPowerLevel ePowerLevel);
 
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index 7bde2d77d3ae..fc840b4403b9 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -63,7 +63,7 @@ typedef struct _SDL_JoystickSensorInfo
     SDL_bool enabled;
     float rate;
     float data[3]; /* If this needs to expand, update SDL_ControllerSensorEvent */
-    Uint64 timestamp_us;
+    Uint64 sensor_timestamp;
 } SDL_JoystickSensorInfo;
 
 struct _SDL_Joystick
diff --git a/src/joystick/apple/SDL_mfijoystick.m b/src/joystick/apple/SDL_mfijoystick.m
index 9ab23edcb777..926619f84f53 100644
--- a/src/joystick/apple/SDL_mfijoystick.m
+++ b/src/joystick/apple/SDL_mfijoystick.m
@@ -1054,14 +1054,14 @@ static void IOS_MFIJoystickUpdate(SDL_Joystick *joystick)
                         data[0] = rate.x;
                         data[1] = rate.z;
                         data[2] = -rate.y;
-                        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, 0, data, 3);
+                        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp, data, 3);
                     }
                     if (motion.hasGravityAndUserAcceleration) {
                         GCAcceleration accel = motion.acceleration;
                         data[0] = -accel.x * SDL_STANDARD_GRAVITY;
                         data[1] = -accel.y * SDL_STANDARD_GRAVITY;
                         data[2] = -accel.z * SDL_STANDARD_GRAVITY;
-                        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, 0, data, 3);
+                        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, data, 3);
                     }
                 }
             }
diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c
index 258438c05aae..188231c4ef75 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps3.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps3.c
@@ -466,7 +466,7 @@ static void HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_Drive
         sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42]));
         sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46]));
         sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44]));
-        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, 0, sensor_data, SDL_arraysize(sensor_data));
+        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp, sensor_data, SDL_arraysize(sensor_data));
     }
 
     SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state)));
diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c
index 2acd5ed6ff6c..50feec2a9d20 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps4.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps4.c
@@ -145,8 +145,8 @@ typedef struct
     Uint8 led_red;
     Uint8 led_green;
     Uint8 led_blue;
-    Uint16 last_timestamp;
-    Uint64 timestamp;
+    Uint64 sensor_ticks;
+    Uint16 last_tick;
     PS4StatePacket_t last_state;
 } SDL_DriverPS4_Context;
 
@@ -807,7 +807,6 @@ static int HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device,
         HIDAPI_DriverPS4_LoadCalibrationData(device);
     }
     ctx->report_sensors = enabled;
-    ctx->timestamp = 0;
 
     return 0;
 }
@@ -947,37 +946,32 @@ static void HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_d
     }
 
     if (ctx->report_sensors) {
-        Uint16 timestamp;
-        Uint64 timestamp_us;
+        Uint16 tick;
+        Uint16 delta;
+        Uint64 sensor_timestamp;
         float data[3];
 
-        timestamp = LOAD16(packet->rgucTimestamp[0], packet->rgucTimestamp[1]);
-        if (ctx->timestamp) {
-            Uint16 delta;
-
-            if (ctx->last_timestamp > timestamp) {
-                delta = (SDL_MAX_UINT16 - ctx->last_timestamp + timestamp + 1);
-            } else {
-                delta = (timestamp - ctx->last_timestamp);
-            }
-            ctx->timestamp += delta;
+        tick = LOAD16(packet->rgucTimestamp[0], packet->rgucTimestamp[1]);
+        if (ctx->last_tick < tick) {
+            delta = (tick - ctx->last_tick);
         } else {
-            ctx->timestamp = timestamp;
+            delta = (SDL_MAX_UINT16 - ctx->last_tick + tick + 1);
         }
-        ctx->last_timestamp = timestamp;
+        ctx->sensor_ticks += delta;
+        ctx->last_tick = tick;
 
         /* Sensor timestamp is in 5.33us units */
-        timestamp_us = (ctx->timestamp * 16) / 3;
+        sensor_timestamp = (ctx->sensor_ticks * SDL_NS_PER_US * 16) / 3;
 
         data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
         data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
         data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1]));
-        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp_us, data, 3);
+        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, data, 3);
 
         data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1]));
         data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1]));
         data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1]));
-        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp_us, data, 3);
+        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, data, 3);
     }
 
     SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state));
diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index f6abc67789cd..75f7083a07e3 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -225,8 +225,8 @@ typedef struct
     Uint8 led_green;
     Uint8 led_blue;
     EDS5LEDResetState led_reset_state;
-    Uint32 last_timestamp;
-    Uint64 timestamp;
+    Uint64 sensor_ticks;
+    Uint32 last_tick;
     union
     {
         PS5SimpleStatePacket_t simple;
@@ -975,7 +975,6 @@ static int HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device,
         HIDAPI_DriverPS5_LoadCalibrationData(device);
     }
     ctx->report_sensors = enabled;
-    ctx->timestamp = 0;
 
     return 0;
 }
@@ -1167,40 +1166,35 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
     SDL_PrivateJoystickAxis(timestamp, joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
 
     if (ctx->report_sensors) {
-        Uint32 timestamp;
-        Uint64 timestamp_us;
+        Uint32 tick;
+        Uint32 delta;
+        Uint64 sensor_timestamp;
         float data[3];
 
-        timestamp = LOAD32(packet->rgucSensorTimestamp[0],
-                           packet->rgucSensorTimestamp[1],
-                           packet->rgucSensorTimestamp[2],
-                           packet->rgucSensorTimestamp[3]);
-        if (ctx->timestamp) {
-            Uint32 delta;
-
-            if (ctx->last_timestamp > timestamp) {
-                delta = (SDL_MAX_UINT32 - ctx->last_timestamp + timestamp + 1);
-            } else {
-                delta = (timestamp - ctx->last_timestamp);
-            }
-            ctx->timestamp += delta;
+        tick = LOAD32(packet->rgucSensorTimestamp[0],
+                      packet->rgucSensorTimestamp[1],
+                      packet->rgucSensorTimestamp[2],
+                      packet->rgucSensorTimestamp[3]);
+        if (ctx->last_tick < tick) {
+            delta = (tick - ctx->last_tick);
         } else {
-            ctx->timestamp = timestamp;
+            delta = (SDL_MAX_UINT32 - ctx->last_tick + tick + 1);
         }
-        ctx->last_timestamp = timestamp;
+        ctx->sensor_ticks += delta;
+        ctx->last_tick = tick;
 
         /* Sensor timestamp is in 0.33us units */
-        timestamp_us = ctx->timestamp / 3;
+        sensor_timestamp = (ctx->sensor_ticks * SDL_NS_PER_US) / 3;
 
         data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1]));
         data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1]));
         data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1]));
-        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, timestamp_us, data, 3);
+        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, sensor_timestamp, data, 3);
 
         data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1]));
         data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1]));
         data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1]));
-        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, timestamp_us, data, 3);
+        SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, sensor_timestamp, data, 3);
     }
 }
 
diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index 1c164e7082a9..d5175c091f4a 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -943,7 +943,7 @@ typedef struct
 {
     SDL_bool report_sensors;
     uint32_t update_rate_in_us;
-    Uint32 timestamp_us;
+    Uint64 sensor_timestamp;
 
     SteamControllerPacketAssembler m_assembler;
     SteamControllerStateInternal_t m_state;
@@ -1183,17 +1183,17 @@ static SDL_bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
             if (ctx->report_sensors) {
                 float values[3];
 
-                ctx->timestamp_us += ctx->update_rate_in_us;
+                ctx->sensor_timestamp += SDL_US_TO_NS(ctx->update_rate_in_us);
 
                 values[0] = (ctx->m_state.sGyroX / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
                 values[1] = (ctx->m_state.sGyroZ / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
                 values[2] = (ctx->m_state.sGyroY / 32768.0f) * (2000.0f * (SDL_PI_F / 180.0f));
-                SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, ctx->timestamp_us, values, 3);
+                SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_GYRO, ctx->sensor_timestamp, values, 3);
 
                 values[0] = (ctx->m_state.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
                 values[1] = (ctx->m_state.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
                 values[2] = (-ctx->m_state.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY;
-                SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->timestamp_us, values, 3);
+                SDL_PrivateJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp, values, 3);
             }
 
             ctx->m_last_state = ctx->m_state;
diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c
index f39c9e6bdf5d..feea3f9992e2 100644
--- a/src/joystick/hidapi/SDL_hidapi_switch.c
+++ b/src/joystick/hidapi/SDL_hidapi_switch.c
@@ -1714,7 +1714,7 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch
 }
 
 static void
-SendSensorUpdate(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SDL_SensorType type, Uint64 timestamp_us, const Sint16 *values)
+SendSensorUpdate(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SDL_SensorType type, Uint64 sensor_timestamp, const Sint16 *values)
 {
     float data[3];
 
@@ -1754,7 +1754,7 @@ SendSensorUpdate(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Cont
         data[0] = -tmp;
     }
 
-    SDL_PrivateJoystickSensor(timestamp, joystick, type, timestamp_us, data, 3);
+    SDL_PrivateJoystickSensor(timestamp, joystick, type, sensor_timestamp, data, 3);
 }
 
 static void HandleCombinedControllerStateL(Uint64 timestamp, SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet)
@@ -1983,7 +1983,7 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
                                    packet->imuState[0].sAccelX != 0);
         if (bHasSensorData) {
             const Uint32 IMU_UPDATE_RATE_SAMPLE_FREQUENCY = 1000;
-            Uint64 timestamp_us[3];
+            Uint64 sensor_timestamp[3];
 
             ctx->m_bHasSensorData = SDL_TRUE;
 
@@ -2001,45 +2001,45 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
             }
 
             ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
-            timestamp_us[0] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
+            sensor_timestamp[0] = ctx->m_ulTimestampNS;
             ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
-            timestamp_us[1] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
+            sensor_timestamp[1] = ctx->m_ulTimestampNS;
             ctx->m_ulTimestampNS += ctx->m_ulIMUUpdateIntervalNS;
-            timestamp_us[2] = SDL_NS_TO_US(ctx->m_ulTimestampNS);
+            sensor_timestamp[2] = ctx->m_ulTimestampNS;
 
             if (!ctx->device->parent ||
                 ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO, timestamp_us[0], &packet->imuState[2].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL, timestamp_us[0], &packet->imuState[2].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[0], &packet->imuState[2].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[0], &packet->imuState[2].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO, timestamp_us[1], &packet->imuState[1].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL, timestamp_us[1], &packet->imuState[1].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[1], &packet->imuState[1].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[1], &packet->imuState[1].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO, timestamp_us[2], &packet->imuState[0].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL, timestamp_us[2], &packet->imuState[0].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO, sensor_timestamp[2], &packet->imuState[0].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL, sensor_timestamp[2], &packet->imuState[0].sAccelX);
             }
 
             if (ctx->device->parent &&
                 ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConLeft) {
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_L, timestamp_us[0], &packet->imuState[2].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_L, timestamp_us[0], &packet->imuState[2].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[0], &packet->imuState[2].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[0], &packet->imuState[2].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_L, timestamp_us[1], &packet->imuState[1].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_L, timestamp_us[1], &packet->imuState[1].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[1], &packet->imuState[1].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[1], &packet->imuState[1].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_L, timestamp_us[2], &packet->imuState[0].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_L, timestamp_us[2], &packet->imuState[0].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_L, sensor_timestamp[2], &packet->imuState[0].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_L, sensor_timestamp[2], &packet->imuState[0].sAccelX);
             }
             if (ctx->device->parent &&
                 ctx->m_eControllerType == k_eSwitchDeviceInfoControllerType_JoyConRight) {
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_R, timestamp_us[0], &packet->imuState[2].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_R, timestamp_us[0], &packet->imuState[2].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[0], &packet->imuState[2].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[0], &packet->imuState[2].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_R, timestamp_us[1], &packet->imuState[1].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_R, timestamp_us[1], &packet->imuState[1].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[1], &packet->imuState[1].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[1], &packet->imuState[1].sAccelX);
 
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_GYRO_R, timestamp_us[2], &packet->imuState[0].sGyroX);
-                SendSensorUpdate(0, joystick, ctx, SDL_SENSOR_ACCEL_R, timestamp_us[2], &packet->imuState[0].sAccelX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_GYRO_R, sensor_timestamp[2], &packet->imuState[0].sGyroX);
+                SendSensorUpdate(timestamp, joystick, ctx, SDL_SENSOR_ACCEL_R, sensor_timestamp[2], &packet->imuState[0].sAccelX);
             }
 
         } else if (ctx->m_bHasSensorData) {
diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c
index 9561aea8768f..9e8bafb13ebf 100644
--- a/src/joystick/hidapi/SDL_hidapi_wii.c
+++ b/src/joystick/hidapi/SDL_hidapi_wii.c
@@ -1254,7 +1254,7 @@ 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(ctx->timestamp, joystick, SDL_SENSOR_ACCEL_L, 0, values, 3);
+        SDL_PrivateJoystickSensor(ctx->timestamp, joystick, SDL_SENSOR_ACCEL_L, ctx->timestamp, values, 3);
     }
 }
 
@@ -1294,7 +1294,7 @@ static void HandleMotionPlusData(SDL_DriverWii_Context *ctx, SDL_Joystick *joyst
         values[0] = -((float)z / GYRO_RES_PER_DEGREE) * SDL_PI_F / 180.0f;
         values[1] = ((float)x / GYRO_RES_PER_DEGREE) * SDL_PI_F / 180.0f;
         values[2] = ((float)y / GYRO_RES_PER_DEGREE) * SDL_PI_F / 180.0f;
-        SDL_PrivateJoystickSensor(ctx->timestamp, joystick, SDL_SENSOR_GYRO, 0, values, 3);
+        SDL_PrivateJoystickSensor(ctx->timestamp, joystick, SDL_SENSOR_GYRO, ctx->timestamp, values, 3);
     }
 }
 
@@ -1315,7 +1315,7 @@ static void HandleWiiRemoteAccelData(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(ctx->timestamp, joystick, SDL_SENSOR_ACCEL, 0, values, 3);
+    SDL_PrivateJoystickSensor(ctx->timestamp, joystick, SDL_SENSOR_ACCEL, ctx->timestamp, values, 3);
 }
 
 static void HandleButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, WiiButtonData *data)
diff --git a/src/joystick/windows/SDL_rawinputjoystick.c b/src/joystick/windows/SDL_rawinputjoystick.c
index 46db60787eca..e6e8dc5f8eda 100644
--- a/src/joystick/windows/SDL_rawinputjoystick.c
+++ b/src/joystick/windows/SDL_rawinputjoystick.c
@@ -964,7 +964,7 @@ static void RAWINPUT_PostUpdate(void)
             if (ctx->guide_hack) {
                 int guide_button = joystick->nbuttons - 1;
 
-                SDL_PrivateJoystickButton(guide_button_candidate.joystick, guide_button, SDL_PRESSED);
+                SDL_PrivateJoystickButton(SDL_GetTicksNS(), guide_button_candidate.joystick, guide_button, SDL_PRESSED);
             }
             guide_button_candidate.last_joystick = guide_button_candidate.joystick;
         }
@@ -974,7 +974,7 @@ static void RAWINPUT_PostUpdate(void)
         if (ctx->guide_hack) {
             int guide_button = joystick->nbuttons - 1;
 
-            SDL_PrivateJoystickButton(joystick, guide_button, SDL_RELEASED);
+            SDL_PrivateJoystickButton(SDL_GetTicksNS(), joystick, guide_button, SDL_RELEASED);
         }
         guide_button_candidate.last_joystick = NULL;
     }
diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c
index 94dc333c97d2..47ab1690959e 100644
--- a/src/sensor/SDL_sensor.c
+++ b/src/sensor/SDL_sensor.c
@@ -384,7 +384,7 @@ int SDL_SensorGetDataWithTimestamp(SDL_Sensor *sensor, Uint64 *timestamp, float
     num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
     SDL_memcpy(data, sensor->data, num_values * sizeof(*data));
     if (timestamp) {
-        *timestamp = sensor->timestamp_us;
+        *timestamp = sensor->sensor_timestamp;
     }
     return 0;
 }
@@ -475,7 +475,7 @@ void SDL_SensorQuit(void)
 
 /* These are global for SDL_syssensor.c and SDL_events.c */
 
-int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, Uint64 timestamp_us, float *data, int num_values)
+int SDL_PrivateSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_timestamp, float *data, int num_values)
 {
     int posted;
 
@@ -484,7 +484,7 @@ int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, Uint64 timestamp_us, float *data
     /* Update internal sensor state */
     num_values = SDL_min(num_values, SDL_arraysize(sensor

(Patch may be truncated, please check the link at the top of this post.)