Closed Ryochan7 closed 1 year ago
Sounds to me like it would be beneficial to simply returning the entire output report unmodified to the SDK and let the user of the API decode the bits relevant to them. Thanks for the explanation, I'll come up with an additional extended notification callback to support this case.
Any update on this? This feature is highly desired.
No. New features for ViGEmBus are on hold until the opportunity opens up again that I find the resources to work on it.
Feature is in the works in this branch.
Implementation done, starting tests...
/**
* Waits until there's one or more pending raw output reports available to consume. This
* function blocks until data becomes available or the device gets disconnected. The waiting is
* event-based, meaning that as soon as a data packet is pending, this call returns a copy of
* the entire buffer. Each call returns a packet in the exact order it arrived in the driver. It
* is recommended to repeatedly call this function in a thread. The call aborts with an error
* code if the target gets unplugged in parallel.
*
* @author Benjamin "Nefarius" Höglinger-Stelzer
* @date 06.08.2022
*
* @param vigem The driver connection object.
* @param target The target device object.
* @param buffer The fixed-size 64-bytes output report buffer that gets written to.
*
* @returns A VIGEM_ERROR.
*/
VIGEM_API VIGEM_ERROR vigem_target_ds4_await_output_report(PVIGEM_CLIENT vigem, PVIGEM_TARGET target, PDS4_OUTPUT_BUFFER buffer);
Familiar sightings 😎
.NET API done too.
I'm happy to see that you could implement that. Thanks
Latest driver beta is required for this to work. C and dotnet SDK updates have been pushed. Backwards compatible is preserved.
It's encouraged to use the new function instead of the DS4 notification callback. Both can exist in parallel though, no data is lost if you use both or either of them but the obvious advantage of the new function is that you get the unmodified raw data buffer and can decide to do whatever you need with it.
Added vigem_target_ds4_await_output_report_timeout
to C/C++ SDK:
/**
* Waits until there's one or more pending raw output reports available to consume. This
* function blocks until data becomes available, the provided timeout has been reached or the
* device gets disconnected. The waiting is event-based, meaning that as soon as a data packet
* is pending, this call returns a copy of the entire buffer. Each call returns a packet in the
* exact order it arrived in the driver. It is recommended to repeatedly call this function in a
* thread. A timeout of a few hundred milliseconds can be used to break out of the loop without
* excessive CPU consumption. The call aborts with an error code if the target gets unplugged in
* parallel. If a timeout of INFINITE is specified, the function basically behaves identical to
* vigem_target_ds4_await_output_report.
*
* @author Benjamin "Nefarius" Höglinger-Stelzer
* @date 12.08.2022
*
* @param vigem The driver connection object.
* @param target The target device object.
* @param milliseconds The timeout in milliseconds.
* @param buffer The fixed-size 64-bytes output report buffer that gets written to.
*
* @returns A VIGEM_ERROR.
*/
VIGEM_API VIGEM_ERROR vigem_target_ds4_await_output_report_timeout(
PVIGEM_CLIENT vigem,
PVIGEM_TARGET target,
DWORD milliseconds,
PDS4_OUTPUT_BUFFER buffer
);
Added IEnumerable<byte> AwaitRawOutputReport(int timeout, out bool timedOut)
to IDualShock4Controller
in .NET SDK.
Is your feature request related to a problem? Please describe.
Virtual DS4 rumble and lightbar passthru support has been a problem for a while but I have not had time to really look into it beforehand; I don't use the feature myself and I had removed support for it in DS4Windows at one point before mika-n added the routine back in the code. The feedback data returned by games can really differ and causes distinguishing between the type of event that the data represents virtually impossible. My main test games that provide native DS4 controller support are The Witcher 3 and Streets of Rage 4.
Currently, DS4Windows tries to make an effort to determine whether an event should be considered a rumble event, lightbar event, or both. The workaround was mainly made using test feedback data given while playing The Witcher 3. Even before this current batch of tests, the data seemed to indicate that The Witcher 3 sent separate output reports for rumble events and lightbar events. The DS4 feedback notification delegate in DS4Windows works on that assumption so it tends to work fine for The Witcher 3; it is likely still not accurate but good enough to not cause major problems. Current tests show that the initial hypothesis is true and The Witcher 3 will change the HID output report features byte (byte 0x01) depending on whether the data represents a rumble event (set to 0x01), a lightbar event (set to 0x02), or both (set to 0x03); a value of 0x03 seems to be used most often for resetting both the rumble motors and lightbar.
However, Streets of Rage 4 seems to include both rumble and lightbar data in the same report and uses a value of 0x07 for the features byte. Flag 0x04 is used to enable flash support for the lightbar although it looks like the game does not set any flash data in the output report buffer. The current DS4 feedback workaround does not really work at all for Streets of Rage 4 and can cause infinite rumble to occur at times.
Location of the DS4 feedback delegate in the current code.
https://github.com/Ryochan7/DS4Windows/blob/57ca7fa2f61ce8447d949760a0146d45aa1aa7cb/DS4Windows/DS4Control/ControlService.cs#L648
Describe the solution you'd like
In order to be able to properly distinguish whether a feedback event should be considered a rumble event, lightbar event, or possibly both, the features byte from the main HID output report buffer (byte 0x01) needs to be provided by ViGEmBus through the ViGEmClient. As it is now, that byte is skipped by ViGEmBus and starts copying report data starting at byte 0x04 (Right Light rumble).
Describe alternatives you've considered
A workaround has been available in DS4Windows for a while. It only works relatively fine in The Witcher 3. The feedback processing workaround fails completely in Streets of Rage 4 when using its native DS4 controller support.
Additional context
I wanted to provide some test data I gathered from Trace events using TraceView Plus. Unfortunately, it looks like TraceView Plus cannot just output the filtered messages to an output file. It still includes all received messages from a session and the process of making the XML file takes several minutes and my current file is around 448 MB. Instead, I can only provide a small snippet of the last group of sample messages shown in a screenshot. The data was gathered while playing The Witcher 3 for a few minutes using its native DS4 controller support.
As you can see, the data differs depending on the flags set in the features byte.
Not sure if it will be relevant but here is the code snippet I inserted into ViGEmBus to log those messages. The code was added to the EmulationTargetDS4::UsbBulkOrInterruptTransfer method in the Ds4Pdo.cpp file.