Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Losing connection with vJoy #164

Open
qrkyckling opened this issue Oct 6, 2018 · 17 comments
Open

Losing connection with vJoy #164

qrkyckling opened this issue Oct 6, 2018 · 17 comments

Comments

@qrkyckling
Copy link

I have a .py script that reads my thrustmaster joystick buttons and creates new buttons in a vJoy device from combinations of those. This because the TM buttons have ON or OFF position and when in OFF I can't bind them in simulators as I would like. So I create a vJoy button only device which I feed to enable buttons when the joystick button is not detected. And then I can bind the vJoy buttons inside the simulator.

It all works nice for a while but FreePIE losing connection to vJoy requires alt+tab out of simulation to stop script (shift+f5) and restart it again (f5), which makes it work again.

Sometimes connection lost in 10 minutes sometimes it lasts up to two hours or more.

  • I have checked vJoyList for owner of devices.
    Sometimes the vJoy is still owned by FreePIE and sometimes the owner PID is blank.

  • FreePIE's own monitor is working. I can see in "Watch" window that the values are changing so connection with joystick is working fine (even without restarting script).

  • There is nothing written to the "Console" or "Error" windows when it fails

  • vJoy is still running and a simple stopping the script in freepie and starting it again makes it work fine again. No restart of vJoy or computer needed.

  • Checking the vJoy device through "USB game controllers" -> Vjoy -> Properties shows all darkened out buttons so none is received.

It appears to me that the connection between FreePIE and vJoy gets broken.

image

@qrkyckling
Copy link
Author

This is the vJoy driver information. It is the one I get when I install "latest".
image

@qrkyckling
Copy link
Author

qrkyckling commented Oct 6, 2018

I have now disabled power management of vJoy device and will see if that resolves problem.

EDIT: It did not.

@MarijnS95
Copy link
Contributor

Would it be possible to share your script so that we can have a look at what's going on?

If anything, FreePIE is just sending axis/button states to the vjoy library that communicates with the driver. Sounds as if FreePIE is not pushing updates anymore.

@qrkyckling
Copy link
Author

Github does not support .py files. Do you want me to zip it up or a screenshot good enough ?

image

@qrkyckling
Copy link
Author

I have FreePIE running right now with the vJoy unresponsive. No owner of vJoy device.
image

@MarijnS95
Copy link
Contributor

You can paste the script in a code block (see the github markdown documentation), but if this is all there is to it then nothing looks out of the ordinary. Good to know that diagnostics.watch keeps going (so your script is properly updating), and that it stops in the monitor, which means the problem is somewhere between passing the data on to vJoy, and the data coming out of the driver as DirectInput controller.

All I can think of right now is adding a watch/log when the status of the joystick changes, though I do not see a reason for the device to suddenly get unacquired. However, the example feeder does handle this case by reacquiring the device if updating fails:
https://github.com/shauleiz/vJoy/blob/2c9a6f14967083d29f5a294b8f5ac65d3d42ac87/apps/vJoyClient/vJoyClient.cpp#L164-L169

FreePIE does not do this, though it should be trivial to add that. Are you in a position to make this change and recompile FreePIE, or should I send you an updated binary (+ send a pull-request once this is confirmed to work)?

@qrkyckling
Copy link
Author

I'm trying to befriend the FreePIE code and Visual Studio environment.
I managed to build and run and I'm trying out this code which I call from SetButton() for now.
I do not see any obvious place (other than inside every function) to place this checkalive() call.
For now I throw exception but will change to reconnect if this get caught.

Do you think this will be acceptable ?

    public void CheckAlive()
    {
        var status = joystick.GetVJDStatus(Index);
        if (status != VjdStat.VJD_STAT_OWN)
        {
            throw new Exception(string.Format("We no longer own the vJoy device"));
        }
    }

@AndersMalmgren
Copy link
Owner

Can't you check it in the BeforeNextExecute

@qrkyckling
Copy link
Author

Seems like a better place. Yes, I missed that one.
I'll see if it catches the problem from there.

@MarijnS95
Copy link
Contributor

You could do that in DoBeforeNextExecute, though I'd recommend printing it to the log instead of raising an exception.

At the same time you could add a conditional to all joystick.Set* calls; if it returns false, log it and reacquire the device, similar to the vJoy client linked above.

@qrkyckling
Copy link
Author

I'll change to System.Console.WriteLine or to be quiet when I reaquire the device.
If that is the problem.
I hope that is the problem.
If that is not the problem then we have a problem :-)

@qrkyckling
Copy link
Author

Well I'm having problems recreating the detach.
I disconnected the joystick on purpose to make sure there is no glitching.
When disconnected the monitoring stops working as well so now I know that is not the issue.

Will continue trying to recreate detach.

@qrkyckling
Copy link
Author

I've finally managed to lose connection and verified FreePIE automatically connects back again.
Printing a line on console about "lost connection and attempting to reacquire."

I'll try to have a PR ready by tomorrow. Busy weekend.

@MarijnS95
Copy link
Contributor

Cool :). Was it the joystick.Set* calls returning false after some time, or is it detected using joystick.GetVJDStatus(Index)?

@qrkyckling
Copy link
Author

I check joystick.GetVJDStatus(Index) in CheckAlive() which is called from the DoBeforeNextExecute loop.

It might be less expensive to just check retval from joystick.Set* calls but I'm thinking at that time it is already too late and you will miss one event? So for now I poll at every loop.

Still no idea why it disconnects tho..
While trying to fix this there has been times when it went 8h+ without disconnect (I gave up and shut down) and there are times when disconnects happen within 15 minutes.

@MarijnS95
Copy link
Contributor

MarijnS95 commented Oct 14, 2018

I agree it is a weird situation, especially since no-one has ever faced this before. However, this looks like expected behaviour thanks to the boolean returns from the Set* functions so you shouldn't worry too much about it.

Using the boolean will be faster because it's readily available (unlike GetVJDStatus which has to call into the C library, which in turn does an IoControl call to the driver to retrieve the result). The difference will be negligible though, just like every python call to setButton, setAxis and others do exactly the same. (If anyone wants to tackle this: store the values in JoystickState and call UpdateVJD with it from DoBeforeNextExecute).

If false is returned and the event is missed, it can easily be sent again after reacquiring the device, in the same if block. Such an edgecase for every set method adds duplication which can be hidden with some lambda functions ;). I'll let @AndersMalmgren decide on that.

private void UpdateJoystickField(Action updater)
{
    if (!updater())
    {
        joystick.Acquire();
        if (!updater())
            throw new Exception("Failed to update joystick after .Acquire()!");
    }
}

@qrkyckling
Copy link
Author

PR created.
#165

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants