Controlling DS4 input programmatically (PC)



  • Hi,

    I'm really excited I've found this forum and all of the nice tools you've developed.

    What I'm trying to achieve is the following. I'd like to be able to programmatically send input to the Remote Play running on Windows, with, or without a DS4 controller connected to the PC (preferably without one).

    For example, say I have a running Java/C# app (or some scripting language, it doesn't matter) and when some event happens I want to send X, or any other button to the remote play instance. Is that achievable with the current set of tools? If so, could you please point me to some documentation where I can find additional information for this specific case?

    Many thanks for all the work you've done.

    Regards,
    Harry



  • @harry Hello and welcome to the madness! ☺

    What you're asking for is totally achievable, docs are currently unfortunately still neglected, but you can take a peak at reference implementations:

    Hope this could give you something to start with.

    Cheers



  • Thank you, nefarius! Appreciate the prompt reply.

    I had a quick look at the test code and the API does seem to be pretty straight forward to use, how cool!
    I do have a couple of technical and a few general questions, if you don't mind and have some time to answer.

    Basically, as a (mainly) Java developer what I'd like to do is to expose the client API in some way so that I can access it from my favorite language (well, basically that's what I've used to implement most of my tooling).
    I've been thinking about using JNA to expose a minimal set of bindings directly through the DLL, if feasible, just to get the job done, or spawn a server socket thread in C# and communicate with Java that way (it'd probably be easier to just do it in C# but I feel quite old to drop my Java habits πŸ™‚ )

    As far as I understand, assuming I'd go with the second approach, I could simply parse the client message on the server side (e.g. PRESS:X) and invoke the report API:

    report.SetButtons(X);
    ds4.SendReport(report);

    Are there any thread related considerations in using that sort of approach? I don't even know at this point if SetButtons or SendReport are blocking APIs. Moreover, is there some timer internally for keeping a button pressed for a certain amount of time?
    I came across this tool some time ago PS4RemotePlayInterceptor where you'd have to keep the assignment in the callback for as long as you wanted the button pressed. Is there something similar in ViGEm client?

    I have one more technical Q before I bore you too much with my questions. After installing the driver, is there some trigger to enable it or is it always there sitting waiting for a client to talk to it? Is it OK if an actual DS4 is connected at the same time also sending input?

    Finally, I've got one general question πŸ™‚ Is there any possibility that Sony to start warning/banning accounts based on whether users have been using such tools? Is it against some of their policy?

    Apologies for the super long reply, I guess I've got too excited! Thanks again for all you've done, even though I haven't used it yet (but I have a feeling it's exactly what I need).

    Cheers



  • @harry said in Controlling DS4 input programmatically (PC):

    As far as I understand, assuming I'd go with the second approach, I could simply parse the client message on the server side (e.g. PRESS:X) and invoke the report API:
    report.SetButtons(X);
    ds4.SendReport(report);

    That is correct. The .NET API is unfortunately quite clunky because it's just a simple wrapper around the C-API, I am currently attempting to redesign this in a new branch, using familiar .NET/OOR patterns. Not in a state to be production ready yet so you'll have to stick to the "old" NuGet for now.

    @harry said in Controlling DS4 input programmatically (PC):

    Are there any thread related considerations in using that sort of approach? I don't even know at this point if SetButtons or SendReport are blocking APIs. Moreover, is there some timer internally for keeping a button pressed for a certain amount of time?

    • The API is not thread-safe so if you share resources you're responsible for proper locking.
    • Those functions are technically blocking, although the time they take should be considered negligible
    • There is no timer; buttons and axis values will stay at the values that were last submitted by the API

    @harry said in Controlling DS4 input programmatically (PC):

    I came across this tool some time ago PS4RemotePlayInterceptor where you'd have to keep the assignment in the callback for as long as you wanted the button pressed. Is there something similar in ViGEm client?

    This project achieves its goal by API hooking, it works in an entirely different way than ViGEm so it can't really be compared.

    @harry said in Controlling DS4 input programmatically (PC):

    Finally, I've got one general question Is there any possibility that Sony to start warning/banning accounts based on whether users have been using such tools? Is it against some of their policy?

    I don't have the slightest clue, I neither know how far spread the use of my solution is nor have I been contacted by some official so I can only guess. My personal opinion though is that dictating or restricting input devices to a certain brand is stupid, especially for e.g. disabled users.

    Hope I could answer everything.

    Cheers



  • Thanks again for the prompt reply.

    I do understand the differences between the approach you've used and the one komefai did (emulated driver vs API hooking). I believe the former is a much cleaner way to do it.
    I also strongly agree that limiting the input device doesn't make any sense and it's almost always a profit oriented decision.

    By the way, with regard to the last query, is there some specific way to "enable" the driver, and also, would it interfere with a normal DS4 connected via USB? I've been wondering how Remote Play would recognize it, or to be more precise, which controller would it recognize if you have the emulated it one and a real one connected at the same time.

    Best,
    Harry



  • @harry said in Controlling DS4 input programmatically (PC):

    I have one more technical Q before I bore you too much with my questions. After installing the driver, is there some trigger to enable it or is it always there sitting waiting for a client to talk to it? Is it OK if an actual DS4 is connected at the same time also sending input?

    @harry said in Controlling DS4 input programmatically (PC):

    By the way, with regard to the last query, is there some specific way to "enable" the driver, and also, would it interfere with a normal DS4 connected via USB? I've been wondering how Remote Play would recognize it, or to be more precise, which controller would it recognize if you have the emulated it one and a real one connected at the same time.

    Sorry, I somehow forgot to answer this paragraph.

    The bus driver by default does nothing. It just sits there and waits until a feeder application talks to it. It also doesn't allocate any critical system resources while it "waits". It is perfectly fine to connect and mix as many DS4 or X360 devices - physical or virtual - as you like, it's designed to co-exist in peace πŸ•Š

    Since the emulated one mimics the real one a 100% it's picked up by the application. I guess RemotePlay simply compares the Vendor and Product IDs of the USB device but that's just a guess, I haven't looked into this.

    There are ofc. ways to distinguish the "real" from the "fake" one on a technical level but so far I guess no attempt to blacklist a ViGEm device has been made.

    Cheers



  • That's perfection, amazing.
    What's the best way to clear a set button? send an empty/null report? set to null first and then send a report?

    Cheers



  • That's where the .NET implementation is currently a bit dumb; you can only submit a full report with all state changes, meaning if you want to unset only one button, you need the previous report object, unset it there and submit it again. The new API/branch has this solved more elegantly.



  • I see, looking forward to the new implementation! Is there some alpha/beta code out already?

    By the way, my understanding is that the default (no button set) state is this:

    Buttons &= unchecked((ushort)~0xF);
    Buttons |= 0x08;

    So basically I need to set the buttons value back to that value, or create a new report (which has the default) and pass that.



  • @harry said in Controlling DS4 input programmatically (PC):

    I see, looking forward to the new implementation! Is there some alpha/beta code out already?

    There is but I'd rather not publish it. I have learned my lesson; people somehow don't understand what "unfinished" means and latch onto it and then waste my time reporting bugs that are none because the design isn't even finished. No offense to you but I've had too many negative examples. Once I start working on it again I'll report progress on the forums.

    @harry said in Controlling DS4 input programmatically (PC):

    Buttons &= unchecked((ushort)~0xF);
    Buttons |= 0x08;
    So basically I need to set the buttons value back to that value, or create a new report (which has the default) and pass that.

    You got it.

    Cheers



  • @nefarius said in Controlling DS4 input programmatically (PC):

    @harry said in Controlling DS4 input programmatically (PC):

    I see, looking forward to the new implementation! Is there some alpha/beta code out already?

    There is but I'd rather not publish it. I have learned my lesson; people somehow don't understand what "unfinished" means and latch onto it and then waste my time reporting bugs that are none because the design isn't even finished. No offense to you but I've had too many negative examples. Once I start working on it again I'll report progress on the forums.

    Of course, I totally understand. I guess people underestimate the meaning of alpha and/or beta.
    When it's ready I'd be happy to try/experiment with the very first version πŸ™‚



  • Be my guest, we've done "private" alpha/beta group testing with various components before, I myself use the new library already in a project so it will definitely gain more traction once my mind is free from Bluetooth and... other things πŸ™‚



  • Best of luck with that. I cannot even start to imagine how complicated/tedious that sort of thing can be. Luckily, it seems we've got one of the best minds working on that!

    By the way, I was thinking of attempting to create some bindings for Java, for the old client (feeder), through JNI/JNA (I'll experiment). I know it'd be throw away work mostly, but that's the only thing published right now that I can work with.

    Have you by any chance experimented with ViGEm running on a VM with a remote play instance running in it? Would such setup work?



  • @harry said in Controlling DS4 input programmatically (PC):

    Best of luck with that. I cannot even start to imagine how complicated/tedious that sort of thing can be. Luckily, it seems we've got one of the best minds working on that!

    I didn't know either what would hit me three to four years ago πŸ˜†

    @harry said in Controlling DS4 input programmatically (PC):

    By the way, I was thinking of attempting to create some bindings for Java, for the old client (feeder), through JNI/JNA (I'll experiment). I know it'd be throw away work mostly, but that's the only thing published right now that I can work with.

    Be my guest, you won't see any Java wrappers from me πŸ™‚ And one thing I learned: no code is complete throw-away, sooner or later I come back and recycle 😜

    @harry said in Controlling DS4 input programmatically (PC):

    Have you by any chance experimented with ViGEm running on a VM with a remote play instance running in it? Would such setup work?

    Sure, I developed ViGEm in a VM and it runs without issues. I have never worked with RemotePlay though as I do not own a PS4. I have a PS3 I only bought so I could reverse engineer the Bluetooth stack (my life is strange, I know) which is now done so I should probably sell it sometime soon...



  • Cool. I'll give it a try (running in VM and to create Java bindings, perhaps using javacpp).

    By the way, is there some installer for the driver or the only way currently is the PowerCLI way?



  • @harry PowerShell is the way to go until things have cooled down and I can work on a new setup-based installer and publish a long awaited new release. The government is currently holding me back (no, I'm not in prison, I'm waiting on some important legal documents to get processed πŸ˜ͺ )



  • Of course, I wouldn't be asking for anything. PowerCLI gets the job done just fine, so everything's good. I was just wondering if I've missed something.

    By the way, do those legal stuff have anything to do with the work you've been doing on this?



  • @harry said in Controlling DS4 input programmatically (PC):

    Of course, I wouldn't be asking for anything. PowerCLI gets the job done just fine, so everything's good. I was just wondering if I've missed something.

    PowerCLI... I've spotted a VMware user it seems πŸ˜‰

    @harry said in Controlling DS4 input programmatically (PC):

    By the way, do those legal stuff have anything to do with the work you've been doing on this?

    It has indeed. I will shed light on it in greater detail in a dedicated news post. Sorry to beat around the bush but I don't like talking about unfinished business πŸ˜‰



  • @nefarius said in Controlling DS4 input programmatically (PC):

    Sorry to beat around the bush but I don't like talking about unfinished business

    don’t count your chickens before they hatch

    Seems like the closest English translation to the German figure of speech "ΓΌber ungelegte Eier spricht man nicht" πŸ˜‰



  • I've put together a very (very) simple solution to invoke the client API from Java, using JNA. I should mention it only supports DS* calls for now.

    All calls but one seem to be working fine. Specifically, VIGEM_API BOOL vigem_target_is_attached(PVIGEM_TARGET target); never returns true, even when the target is actually attached and I can send reports to it. Perhaps I got the API wrong?

    Isn't that API call supposed to be used right after a vigem_target_add call (with polling for instance) to ensure that the device is attached before starting to send reports?

    Cheers


Log in to reply