Commit 495fca1517411eee45b5a4d58ea2faacb8306c38

Sam Lantinga 2023-09-18T11:50:56

Fixed sensor timestamp calculation for third-party PS5 controllers (cherry picked from commit 7059a55ccca04b75145c3d23a317fbe1eb77039e) (cherry picked from commit fff3c2573a46b685f73646dc01937a88c35b3be6)

diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c
index 081c126..48b6b99 100644
--- a/src/joystick/hidapi/SDL_hidapi_ps5.c
+++ b/src/joystick/hidapi/SDL_hidapi_ps5.c
@@ -102,7 +102,7 @@ typedef struct
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelZ[2];          /* 25 */
-    Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */
+    Uint8 rgucSensorTimestamp[2]; /* 27 - 16/32 bit little endian */
 
 } PS5StatePacketCommon_t;
 
@@ -154,7 +154,9 @@ typedef struct
     Uint8 rgucAccelX[2];          /* 21 */
     Uint8 rgucAccelY[2];          /* 23 */
     Uint8 rgucAccelZ[2];          /* 25 */
-    Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */
+    Uint8 rgucSensorTimestamp[2]; /* 27 - 16 bit little endian */
+    Uint8 ucBatteryLevel;         /* 29 */
+    Uint8 ucUnknown;              /* 30 */
     Uint8 ucTouchpadCounter1;     /* 31 - high bit clear + counter */
     Uint8 rgucTouchpadData1[3];   /* 32 - X/Y, 12 bits per axis */
     Uint8 ucTouchpadCounter2;     /* 35 - high bit clear + counter */
@@ -1229,27 +1231,50 @@ static void HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL
     SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis);
 
     if (ctx->report_sensors) {
-        Uint32 timestamp;
-        Uint64 timestamp_us;
         float data[3];
+        Uint64 timestamp_us;
+
+        if (ctx->use_alternate_report) {
+            /* 16-bit timestamp */
+            Uint16 timestamp;
 
-        timestamp = LOAD32(packet->rgucSensorTimestamp[0],
-                           packet->rgucSensorTimestamp[1],
-                           packet->rgucSensorTimestamp[2],
-                           packet->rgucSensorTimestamp[3]);
-        if (ctx->timestamp) {
-            Uint32 delta;
+            timestamp = LOAD16(packet->rgucSensorTimestamp[0],
+                               packet->rgucSensorTimestamp[1]);
+            if (ctx->timestamp) {
+                Uint16 delta;
 
-            if (ctx->last_timestamp > timestamp) {
-                delta = (SDL_MAX_UINT32 - ctx->last_timestamp + timestamp + 1);
+                if (ctx->last_timestamp > timestamp) {
+                    delta = (SDL_MAX_UINT16 - ctx->last_timestamp + timestamp + 1);
+                } else {
+                    delta = (timestamp - ctx->last_timestamp);
+                }
+                ctx->timestamp += delta;
             } else {
-                delta = (timestamp - ctx->last_timestamp);
+                ctx->timestamp = timestamp;
             }
-            ctx->timestamp += delta;
+            ctx->last_timestamp = timestamp;
         } else {
-            ctx->timestamp = timestamp;
+            /* 32-bit timestamp */
+            Uint32 timestamp;
+
+            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;
+            } else {
+                ctx->timestamp = timestamp;
+            }
+            ctx->last_timestamp = timestamp;
         }
-        ctx->last_timestamp = timestamp;
 
         /* Sensor timestamp is in 0.33us units */
         timestamp_us = ctx->timestamp / 3;