Emulator Issues #6071
closedWiimote packet loss on Windows [with proposed patch]
0%
Description
While developing my sf.net/projects/wiimotecontrol application, I
discovered a bug in Dolphin's WiimoteReal/IOWin.cpp file.
This bug could lead to ignoring packets from the Wiimote, which I
actually experienced indeed. Losing a packet in which the button
bitmask changes, for example due to releasing a button, can be
particularly nasty.
The Wiimote sends a packet when pressing a button, and when releasing
a button. In between this time, Dolphin repeats the last packet (i.e.,
the "button press packet"). If we then miss the "button release
packet", Dolphin keeps repeating the "button press packet" until it
receives a new packet. If indeed such a packet is lost, it causes my
Wiimote Control application to behave as if the last-pressed button
(or buttons) is/are still held down.
I imagine this also happens on the computers of Dolphin users, perhaps
far less often (maybe that's why it hasn't been fixed yet?), for some
reason I haven't looked into.
The technical issue is that after calling CancelIo(), IOWin.cpp does
NOT call GetOverlappedResult(). This means a packet may be lost (in
fact there's even a WARN_LOG() call for that).
To see why calling GetOverlappedResult() after calling CancelIo() is
necessary, I quote this excerpt from 'fixed.patch':
// We must make sure the attempt at cancellation has
// completed, by calling GetOverlappedResult(). We must
// still determine the result of the operation. Did the
// cancellation succeed, or did the packet still get
// through?
If indeed the packet still got through after calling CancelIo(),
Dolphin should handle it, and not ignore it.
I have attached a binary (plus a patch one can use to re-create this
binary; feel free to do so). The binary is the Wiimote Control program
with modifications so that the bug can be revealed reasonably quickly
if one keeps tapping a button on the Wiimote (might need to retry it a
few times).
In total I've attached two patches, one ('packet loss test.patch') to
create the Wiimote Control test case binary with, and the other
contains the proposed solution ('fixed.patch') for Dolphin.
Cheers
Updated by Billiard26 over 11 years ago
- Operating system Windows added
Wiimotes continuously send input regardless of changes in button state when "continuous reporting" is enabled which AFAIK every game enables.
I don't think "missing a button release packet" is a problem, and if it was, it would not be fixable?
But you did make me realize we should be extracting the "core button" data from every input report and placing it in our stored "last data report" to prevent spurious presses/releases.
Also, your patch is based on an old IOWin.cpp.
I will change IOWin to use GetOverlappedResult after CancelIO as that is proper.
But I don't think this will really help anything.
Updated by bughunter2 over 11 years ago
The continously sending input is precisely what I meant with "Dolphin repeats the last packet".
If you run the test case binary, you will see the problem is reasonably easy (at least it was for me) to reproduce. It can indeed be fixed by calling GetOverlappedResult() and handling the packet in case it did get through even though CancelIo() was called.
Updated by Billiard26 over 11 years ago
bughunter2, Not only dolphin continuously sends input, the physical wiimote does when the proper flag is enabled when setting the reporting mode.
Is your app setting the "continuous reporting mode" flag?
http://wiibrew.org/wiki/Wiimote#Data_Reporting
"Bit 2 of TT specifies whether continuous reporting is desired. If bit 2 (0x04) is set, the Wii Remote will send reports whether there has been any change to the data or not. Otherwise, the Wii Remote will only send an output report when the data has changed."
Updated by bughunter2 over 11 years ago
My application uses Dolphin's code without calling DisableDataReporting(), so perhaps that means continuous reporting is still enabled? I don't think so though. I suspect continuous reporting is disabled in my application.
It's quite logical that the bug only becomes apparent in my application and not in Dolphin, if indeed continuous reporting is used by Dolphin and not by my application, since missing just one packet in continuous reporting mode isn't so bad, but it is if you don't have continuous reporting enabled.
However, bottom line is still that calling GetOverlappedResult() after CancelIo() fixes my issue, and that packet loss never occurs that way (at least not due to the inherent race condition present when using CancelIo(), which is that the packet may still get through).
Given this bug, and the fact that it's fixed in my application in my proposed way, I do not think that my application is using Dolphin's code wrongly (not that you claim this, of course), even though it uses the Wiimote code from Dolphin differently than Dolphin does.
Just wanted to report it to you, as it is indeed, as you say, proper, to call GetOverlappedResult() after CancelIo().
Updated by Billiard26 over 11 years ago
- Status changed from New to Fixed
This issue was closed by revision ceebed9268f6.