device: Implement correct sign extension for Windows raw devices

Hopefully, fix for #1218
This commit is contained in:
rdb 2022-01-01 12:11:15 +01:00
parent 72bf9e7fd1
commit 0e9ea67066
2 changed files with 27 additions and 9 deletions

View File

@ -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);
}

View File

@ -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.