From 0e9ea6706686ee810eea8171b96637b324763481 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 1 Jan 2022 12:11:15 +0100 Subject: [PATCH] device: Implement correct sign extension for Windows raw devices Hopefully, fix for #1218 --- panda/src/device/winRawInputDevice.cxx | 30 ++++++++++++++++++++------ panda/src/device/winRawInputDevice.h | 6 +++--- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/panda/src/device/winRawInputDevice.cxx b/panda/src/device/winRawInputDevice.cxx index 421d3c573c..8448b58da4 100644 --- a/panda/src/device/winRawInputDevice.cxx +++ b/panda/src/device/winRawInputDevice.cxx @@ -405,7 +405,8 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { << ", UsagePage=0x" << hex << cap.UsagePage << ", Usage=0x" << cap.Range.UsageMin << "..0x" << cap.Range.UsageMax << dec << ", LogicalMin=" << cap.LogicalMin - << ", LogicalMax=" << cap.LogicalMax << "\n"; + << ", LogicalMax=" << cap.LogicalMax + << ", BitSize=" << cap.BitSize << "\n"; } } else { if (device_cat.is_debug()) { @@ -415,7 +416,8 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { << ", UsagePage=0x" << hex << cap.UsagePage << ", Usage=0x" << cap.NotRange.Usage << dec << ", LogicalMin=" << cap.LogicalMin - << ", LogicalMax=" << cap.LogicalMax << "\n"; + << ", LogicalMax=" << cap.LogicalMax + << ", BitSize=" << cap.BitSize << "\n"; } } @@ -428,7 +430,7 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { // My gamepads give this odd invalid range. if (cap.LogicalMin == 0 && cap.LogicalMax == -1) { - cap.LogicalMax = 65535; + cap.LogicalMax = (1 << cap.BitSize) - 1; is_signed = false; } @@ -562,6 +564,17 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { } } + int sign_bit = 0; + if (cap.BitSize < 32) { + if (cap.LogicalMin < 0) { + sign_bit = 1 << (cap.BitSize - 1); + } + else if (is_signed) { + //XXX is this still necessary? + sign_bit = (1 << 15); + } + } + int axis_index; if (!is_signed) { // All axes on the weird XInput-style mappings go from -1 to 1 @@ -569,7 +582,7 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) { } else { axis_index = add_axis(axis, cap.LogicalMin, cap.LogicalMax); } - _indices[data_index] = Index::axis(axis_index, is_signed); + _indices[data_index] = Index::axis(axis_index, sign_bit); } } @@ -685,8 +698,13 @@ process_report(PCHAR ptr, size_t size) { const Index &idx = _indices[data[di].DataIndex]; if (idx._axis >= 0) { - if (idx._signed) { - axis_changed(idx._axis, (SHORT)data[di].RawValue); + if (idx._sign_bit != 0) { + // Sign extend. + int value = data[di].RawValue; + if (value & idx._sign_bit) { + value = -(value & ~idx._sign_bit); + } + axis_changed(idx._axis, value); } else { axis_changed(idx._axis, data[di].RawValue); } diff --git a/panda/src/device/winRawInputDevice.h b/panda/src/device/winRawInputDevice.h index bea8066b85..84189b506e 100644 --- a/panda/src/device/winRawInputDevice.h +++ b/panda/src/device/winRawInputDevice.h @@ -59,16 +59,16 @@ private: idx._button = index; return idx; } - static Index axis(int index, bool is_signed=true) { + static Index axis(int index, int sign_bit = 0) { Index idx; idx._axis = index; - idx._signed = is_signed; + idx._sign_bit = sign_bit; return idx; } int _button; int _axis; - bool _signed; + int _sign_bit; }; // Maps a "data index" to either button index or axis index.