diff --git a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h index e3ea617c71..cfcc11b102 100644 --- a/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h +++ b/Source/Core/Core/HW/WiimoteCommon/WiimoteReport.h @@ -449,6 +449,13 @@ struct wm_report_core_accel }; static_assert(sizeof(wm_report_core_accel) == 5, "Wrong size"); +struct wm_report_core_ext8 +{ + wm_buttons c; + u8 ext[8]; +}; +static_assert(sizeof(wm_report_core_ext8) == 10, "Wrong size"); + struct wm_report_core_accel_ir12 { wm_buttons c; diff --git a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp index ed9d6d8e13..b0ad431d2d 100644 --- a/Source/Core/Core/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/HW/WiimoteReal/IOWin.cpp @@ -577,6 +577,38 @@ bool WiimoteWindows::IsConnected() const return m_dev_handle != nullptr; } +// See http://wiibrew.org/wiki/Wiimote for the Report IDs and its sizes +size_t GetReportSize(u8 report_id) +{ + switch (report_id) + { + case RT_STATUS_REPORT: + return sizeof(wm_status_report); + case RT_READ_DATA_REPLY: + return sizeof(wm_read_data_reply); + case RT_ACK_DATA: + return sizeof(wm_acknowledge); + case RT_REPORT_CORE: + return sizeof(wm_report_core); + case RT_REPORT_CORE_ACCEL: + return sizeof(wm_report_core_accel); + case RT_REPORT_CORE_EXT8: + return sizeof(wm_report_core_ext8); + case RT_REPORT_CORE_ACCEL_IR12: + return sizeof(wm_report_core_accel_ir12); + case RT_REPORT_CORE_EXT19: + case RT_REPORT_CORE_ACCEL_EXT16: + case RT_REPORT_CORE_IR10_EXT9: + case RT_REPORT_CORE_ACCEL_IR10_EXT6: + case RT_REPORT_EXT21: + case RT_REPORT_INTERLEAVE1: + case RT_REPORT_INTERLEAVE2: + return sizeof(wm_report_ext21); + default: + return 0; + } +} + // positive = read packet // negative = didn't read packet // zero = error @@ -624,7 +656,17 @@ int IORead(HANDLE& dev_handle, OVERLAPPED& hid_overlap_read, u8* buf, int index) } } - return bytes + 1; + // ReadFile will always return 22 bytes read. + // So we need to calculate the actual report size by its report ID + DWORD report_size = static_cast(GetReportSize(buf[1])); + if (report_size == 0) + { + WARN_LOG(WIIMOTE, "Received unsupported report %d in Wii Remote %i", buf[1], index + 1); + return -1; + } + + // 1 Byte for the Data Report Byte, another for the Report ID and the actual report size + return 1 + 1 + report_size; } void WiimoteWindows::IOWakeup() @@ -646,15 +688,15 @@ static int IOWritePerSetOutputReport(HANDLE& dev_handle, const u8* buf, size_t l if (!result) { DWORD err = GetLastError(); - if (err == 121) + if (err == ERROR_SEM_TIMEOUT) { - // Semaphore timeout NOTICE_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Unable to send data to the Wiimote"); } - else if (err != 0x1F) // Some third-party adapters (DolphinBar) use this - // error code to signal the absence of a Wiimote - // linked to the HID device. + else if (err != ERROR_GEN_FAILURE) { + // Some third-party adapters (DolphinBar) use this + // error code to signal the absence of a Wiimote + // linked to the HID device. WARN_LOG(WIIMOTE, "IOWrite[WWM_SET_OUTPUT_REPORT]: Error: %08x", err); } }