device: added checks, robustness, debug output for Windows raw input

This commit is contained in:
rdb 2019-01-05 22:00:34 +01:00
parent 0d5d6466f1
commit d106fd6a3a
3 changed files with 47 additions and 8 deletions

View File

@ -315,7 +315,8 @@ on_input_device_arrival(HANDLE handle) {
// Is this an XInput device? If so, handle it via XInput, which allows us
// to handle independent left/right triggers as well as vibration output.
if (info.dwType == RIM_TYPEHID && strstr(path, "&IG_") != nullptr) {
if (info.dwType == RIM_TYPEHID && strstr(path, "&IG_") != nullptr &&
XInputDevice::init_xinput()) {
// This is a device we should handle via the XInput API. Check which of
// the four players was the lucky one.
if (_xinput_device0.check_arrival(info, inst, name, manufacturer)) {

View File

@ -334,6 +334,14 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
return false;
}
if (device_cat.is_debug()) {
device_cat.debug()
<< "Found " << _device_class << " device \"" << _name << "\" with "
<< caps.NumberInputDataIndices << " data indices, "
<< caps.NumberInputButtonCaps << " button caps, "
<< caps.NumberInputValueCaps << " value caps\n";
}
// Do we have a button mapping?
static const ButtonHandle gamepad_buttons_common[] = {
ButtonHandle::none(),
@ -374,8 +382,11 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
_axes.clear();
USHORT num_button_caps = caps.NumberInputButtonCaps;
PHIDP_BUTTON_CAPS button_caps = (PHIDP_BUTTON_CAPS)alloca(num_button_caps * sizeof(HIDP_BUTTON_CAPS));
PHIDP_BUTTON_CAPS button_caps;
if (num_button_caps > 0u) {
button_caps = (PHIDP_BUTTON_CAPS)alloca(num_button_caps * sizeof(HIDP_BUTTON_CAPS));
_HidP_GetButtonCaps(HidP_Input, button_caps, &num_button_caps, buffer);
}
for (USHORT i = 0; i < num_button_caps; ++i) {
HIDP_BUTTON_CAPS &cap = button_caps[i];
@ -396,13 +407,15 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
if (device_cat.is_debug()) {
device_cat.debug()
<< "Found button: DataIndex=" << dec << cap.NotRange.DataIndex
<< ", ReportID=" << dec << (int)cap.ReportID
<< ", UsagePage=0x" << cap.UsagePage
<< ", ReportID=" << (int)cap.ReportID
<< ", UsagePage=0x" << hex << cap.UsagePage
<< ", Usage=0x" << cap.NotRange.Usage
<< dec << "\n";
}
}
nassertd(cap.Range.DataIndexMin + upper < _indices.size()) continue;
// Windows will only tell us which buttons in a report are "on", so we
// need to keep track of which buttons exist in which report so that we
// can figure out which ones are off.
@ -429,6 +442,9 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
handle = MouseButton::button(button);
}
break;
default:
continue;
}
int button_index = _buttons.size();
@ -439,8 +455,11 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
}
USHORT num_value_caps = caps.NumberInputValueCaps;
PHIDP_VALUE_CAPS value_caps = (PHIDP_VALUE_CAPS)alloca(num_value_caps * sizeof(HIDP_VALUE_CAPS));
PHIDP_VALUE_CAPS value_caps;
if (num_value_caps > 0u) {
value_caps = (PHIDP_VALUE_CAPS)alloca(num_value_caps * sizeof(HIDP_VALUE_CAPS));
_HidP_GetValueCaps(HidP_Input, value_caps, &num_value_caps, buffer);
}
_hat_data_index = -1;
@ -464,7 +483,7 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
if (device_cat.is_debug()) {
device_cat.debug()
<< "Found value: DataIndex=" << dec << cap.NotRange.DataIndex
<< ", ReportID=" << dec << (int)cap.ReportID
<< ", ReportID=" << (int)cap.ReportID
<< ", UsagePage=0x" << hex << cap.UsagePage
<< ", Usage=0x" << cap.NotRange.Usage
<< dec << ", LogicalMin=" << cap.LogicalMin
@ -472,6 +491,8 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
}
}
nassertd(cap.Range.DataIndexMin + upper < _indices.size()) continue;
for (int j = 0; j <= upper; ++j) {
USAGE usage = j + cap.Range.UsageMin;
USHORT data_index = j + cap.Range.DataIndexMin;
@ -590,6 +611,8 @@ on_arrival(HANDLE handle, const RID_DEVICE_INFO &info, std::string name) {
_max_data_count = _HidP_MaxDataListLength(HidP_Input, buffer);
nassertr_always(_max_data_count >= 0, false);
_handle = handle;
_is_connected = true;
return true;
@ -619,6 +642,10 @@ on_input(PRAWINPUT input) {
nassertv(input != nullptr);
nassertv(_preparsed != nullptr);
if (_max_data_count == 0) {
return;
}
BYTE *ptr = input->data.hid.bRawData;
if (input->data.hid.dwSizeHid == 0) {
return;
@ -626,6 +653,12 @@ on_input(PRAWINPUT input) {
LightMutexHolder holder(_lock);
if (device_cat.is_spam()) {
device_cat.spam()
<< _name << " received " << input->data.hid.dwCount << " reports of size "
<< input->data.hid.dwSizeHid << "\n";
}
for (DWORD i = 0; i < input->data.hid.dwCount; ++i) {
process_report((PCHAR)ptr, input->data.hid.dwSizeHid);
ptr += input->data.hid.dwSizeHid;
@ -654,6 +687,7 @@ process_report(PCHAR ptr, size_t size) {
if (status == HIDP_STATUS_SUCCESS) {
for (ULONG di = 0; di < count; ++di) {
if (data[di].DataIndex != _hat_data_index) {
nassertd(data[di].DataIndex < _indices.size()) continue;
const Index &idx = _indices[data[di].DataIndex];
if (idx._axis >= 0) {
if (idx._signed) {

View File

@ -249,6 +249,10 @@ detect(InputDeviceManager *mgr) {
*/
bool XInputDevice::
init_xinput() {
if (_initialized) {
return true;
}
if (device_cat.is_debug()) {
device_cat.debug() << "Initializing XInput library.\n";
}