diff --git a/devices/sony/dualshock4-v2.toml b/devices/sony/dualshock4-v2.toml index 1fceef38..86dcb2be 100644 --- a/devices/sony/dualshock4-v2.toml +++ b/devices/sony/dualshock4-v2.toml @@ -28,14 +28,14 @@ left_x = { offset = 1, type = "u8", transform = "scale(-32768, 32767)" } left_y = { offset = 2, type = "u8", transform = "scale(-32768, 32767), negate" } right_x = { offset = 3, type = "u8", transform = "scale(-32768, 32767)" } right_y = { offset = 4, type = "u8", transform = "scale(-32768, 32767), negate" } -lt = { offset = 9, type = "u8" } -rt = { offset = 10, type = "u8" } -gyro_x = { offset = 14, type = "i16le" } -gyro_y = { offset = 16, type = "i16le" } -gyro_z = { offset = 18, type = "i16le" } -accel_x = { offset = 20, type = "i16le" } -accel_y = { offset = 22, type = "i16le" } -accel_z = { offset = 24, type = "i16le" } +lt = { offset = 8, type = "u8" } +rt = { offset = 9, type = "u8" } +gyro_x = { offset = 13, type = "i16le" } +gyro_y = { offset = 15, type = "i16le" } +gyro_z = { offset = 17, type = "i16le" } +accel_x = { offset = 19, type = "i16le" } +accel_y = { offset = 21, type = "i16le" } +accel_z = { offset = 23, type = "i16le" } touch0_contact = { offset = 33, type = "u8" } touch1_contact = { offset = 37, type = "u8" } battery_level = { bits = [30, 0, 4] } @@ -59,14 +59,14 @@ left_x = { offset = 3, type = "u8", transform = "scale(-32768, 32767)" } left_y = { offset = 4, type = "u8", transform = "scale(-32768, 32767), negate" } right_x = { offset = 5, type = "u8", transform = "scale(-32768, 32767)" } right_y = { offset = 6, type = "u8", transform = "scale(-32768, 32767), negate" } -lt = { offset = 11, type = "u8" } -rt = { offset = 12, type = "u8" } -gyro_x = { offset = 16, type = "i16le" } -gyro_y = { offset = 18, type = "i16le" } -gyro_z = { offset = 20, type = "i16le" } -accel_x = { offset = 22, type = "i16le" } -accel_y = { offset = 24, type = "i16le" } -accel_z = { offset = 26, type = "i16le" } +lt = { offset = 10, type = "u8" } +rt = { offset = 11, type = "u8" } +gyro_x = { offset = 15, type = "i16le" } +gyro_y = { offset = 17, type = "i16le" } +gyro_z = { offset = 19, type = "i16le" } +accel_x = { offset = 21, type = "i16le" } +accel_y = { offset = 23, type = "i16le" } +accel_z = { offset = 25, type = "i16le" } touch0_contact = { offset = 35, type = "u8" } touch1_contact = { offset = 39, type = "u8" } battery_level = { bits = [32, 0, 4] } diff --git a/devices/sony/dualshock4.toml b/devices/sony/dualshock4.toml index bb526b58..faed9948 100644 --- a/devices/sony/dualshock4.toml +++ b/devices/sony/dualshock4.toml @@ -28,14 +28,14 @@ left_x = { offset = 1, type = "u8", transform = "scale(-32768, 32767)" } left_y = { offset = 2, type = "u8", transform = "scale(-32768, 32767), negate" } right_x = { offset = 3, type = "u8", transform = "scale(-32768, 32767)" } right_y = { offset = 4, type = "u8", transform = "scale(-32768, 32767), negate" } -lt = { offset = 9, type = "u8" } -rt = { offset = 10, type = "u8" } -gyro_x = { offset = 14, type = "i16le" } -gyro_y = { offset = 16, type = "i16le" } -gyro_z = { offset = 18, type = "i16le" } -accel_x = { offset = 20, type = "i16le" } -accel_y = { offset = 22, type = "i16le" } -accel_z = { offset = 24, type = "i16le" } +lt = { offset = 8, type = "u8" } +rt = { offset = 9, type = "u8" } +gyro_x = { offset = 13, type = "i16le" } +gyro_y = { offset = 15, type = "i16le" } +gyro_z = { offset = 17, type = "i16le" } +accel_x = { offset = 19, type = "i16le" } +accel_y = { offset = 21, type = "i16le" } +accel_z = { offset = 23, type = "i16le" } touch0_contact = { offset = 33, type = "u8" } touch1_contact = { offset = 37, type = "u8" } battery_level = { bits = [30, 0, 4] } @@ -66,14 +66,14 @@ left_x = { offset = 3, type = "u8", transform = "scale(-32768, 32767)" } left_y = { offset = 4, type = "u8", transform = "scale(-32768, 32767), negate" } right_x = { offset = 5, type = "u8", transform = "scale(-32768, 32767)" } right_y = { offset = 6, type = "u8", transform = "scale(-32768, 32767), negate" } -lt = { offset = 11, type = "u8" } -rt = { offset = 12, type = "u8" } -gyro_x = { offset = 16, type = "i16le" } -gyro_y = { offset = 18, type = "i16le" } -gyro_z = { offset = 20, type = "i16le" } -accel_x = { offset = 22, type = "i16le" } -accel_y = { offset = 24, type = "i16le" } -accel_z = { offset = 26, type = "i16le" } +lt = { offset = 10, type = "u8" } +rt = { offset = 11, type = "u8" } +gyro_x = { offset = 15, type = "i16le" } +gyro_y = { offset = 17, type = "i16le" } +gyro_z = { offset = 19, type = "i16le" } +accel_x = { offset = 21, type = "i16le" } +accel_y = { offset = 23, type = "i16le" } +accel_z = { offset = 25, type = "i16le" } touch0_contact = { offset = 35, type = "u8" } touch1_contact = { offset = 39, type = "u8" } battery_level = { bits = [32, 0, 4] } diff --git a/src/test/interpreter_e2e_test.zig b/src/test/interpreter_e2e_test.zig index 8272e170..95a255ee 100644 --- a/src/test/interpreter_e2e_test.zig +++ b/src/test/interpreter_e2e_test.zig @@ -190,6 +190,40 @@ test "EventLoop pipeline: A press then release" { try testing.expect(d1_btns & a_mask == 0); } +// --- Regression: DualShock 4 USB report offsets (L2/R2 + IMU) --- +// Guards the off-by-one where lt/rt and gyro/accel were each shifted +1 byte. +// Layout per hid-playstation dualshock4_input_report_common (report-id inclusive): +// [0] id 0x01, [1..4] sticks, [5..7] buttons, [8] L2, [9] R2, +// [10..11] timestamp, [12] temp, [13..18] gyro, [19..24] accel. +test "interpreter_e2e: DualShock4 USB — L2/R2 + IMU land at correct offsets" { + const allocator = testing.allocator; + const parsed = try device_mod.parseFile(allocator, "devices/sony/dualshock4.toml"); + defer parsed.deinit(); + const interp = Interpreter.init(&parsed.value); + + var raw = [_]u8{0} ** 64; + raw[0] = 0x01; + raw[8] = 11; // L2 + raw[9] = 22; // R2 + std.mem.writeInt(i16, raw[13..15], 1000, .little); // gyro_x + std.mem.writeInt(i16, raw[15..17], 2000, .little); // gyro_y + std.mem.writeInt(i16, raw[17..19], 3000, .little); // gyro_z + std.mem.writeInt(i16, raw[19..21], -1000, .little); // accel_x + std.mem.writeInt(i16, raw[21..23], -2000, .little); // accel_y + std.mem.writeInt(i16, raw[23..25], -3000, .little); // accel_z + + const delta = (try interp.processReport(0, &raw)) orelse return error.NoMatch; + + try testing.expectEqual(@as(?u8, 11), delta.lt); + try testing.expectEqual(@as(?u8, 22), delta.rt); + try testing.expectEqual(@as(?i16, 1000), delta.gyro_x); + try testing.expectEqual(@as(?i16, 2000), delta.gyro_y); + try testing.expectEqual(@as(?i16, 3000), delta.gyro_z); + try testing.expectEqual(@as(?i16, -1000), delta.accel_x); + try testing.expectEqual(@as(?i16, -2000), delta.accel_y); + try testing.expectEqual(@as(?i16, -3000), delta.accel_z); +} + // --- Layer 2 (manual) --- // 1. zig build -Doptimize=Debug // 2. sudo ./zig-out/bin/padctl --config devices/flydigi/vader5.toml