nyholku / purejavahidapi

Other
120 stars 69 forks source link

readRunOnBackground() hangs on GetOverlappedResult #32

Closed ItsVeeBot closed 7 years ago

ItsVeeBot commented 8 years ago

I am attempting to use the API to control the lighting in a device. Upon completing the first write, the API will continuously block whenever it's called again, even between program runs. I'm not sure if this is an issue with the API or with my code - in which case my code is as follows. The program blocks on the enumerateDevices() line and on the controllerDevice.close() line.

package buzzshow;

import purejavahidapi.*;

/**
 *
 * @author Bryan Hauser <vmkid95@gmail.com>
 */
public class ControllerLights{

    private static final short VENDOR_ID = 0x054C;
    private static final short PRODUCT_ID = 0x1000;
    private static final int MESSAGE_LENGTH = 6;

    HidDeviceInfo controller;
    HidDevice controllerDevice;

    public ControllerLights(){

        PureJavaHidApi.enumerateDevices().stream().filter((info) -> (info.getVendorId()==VENDOR_ID && info.getProductId()==PRODUCT_ID)).forEach((info) -> {
            controller=info;
        });
        try{
            controllerDevice = PureJavaHidApi.openDevice(controller.getPath());
        }catch(Exception e){
            System.out.println("Couldn't open controller for lighting!");
            return;
        }
    }

    public void controlLights(boolean[] lights){

        byte[] message = new byte[MESSAGE_LENGTH];
        for(int i=0; i<4; i++){
            if(lights[i]){
                message[i+1]=(byte)0xff;
            }
        }
        try{
            controllerDevice = PureJavaHidApi.openDevice(controller.getPath());
        }catch(Exception e){
            System.out.println("Couldn't open controller for lighting!");
            return;
        }
        controllerDevice.setOutputReport((byte)0x00, message, MESSAGE_LENGTH);
        //controllerDevice.close();
    }
    public void shutdown(){
        controllerDevice.close();
    }
}
nyholku commented 8 years ago

On the first try, does the command you send have the desired effect, ie it works?

Does unplugging/replugging the device make it work again?

Which call hangs on the second try?

Which platform are you trying this on?

Would you be ready to try debug this with a piece of HIDAPI code to get a baseline reference weather this works with a known good C-API?

ItsVeeBot commented 8 years ago

I've revised my code slightly since asking the question (I removed the redundant openDevice from the controlLights() function). Currently, it does have the desired effect upon running the first time. However, upon calling close(), the program hangs.

Unplugging and replugging the opened device doesn't seem to be fixing the issue- rather, unplugging and replugging a completely unrelated device seems to fix the problem.

Upon trying to re-run the program after a failed close(), enumerateDevices() is the line that hangs.

The platform is Windows 10 64-bit.

ItsVeeBot commented 8 years ago

Alright, after a bit of debugging, it appears that the API is blocking consistently at this line in purajavahidapi.windows.HidDevice's close() method: m_SyncShutdown.waitAndSync(); For whatever reason, it appears that runReadOnBackground() isn't reaching the end of its loop somehow, or it's ignoring m_StopThread.

ItsVeeBot commented 8 years ago

After even further debugging, I found where readRunOnBackground() is blocking. On line 234 in the Windows version of HidDevice: if (!GetOverlappedResult(m_Handle, m_InputReportOverlapped, m_InputReportBytesRead, true/* wait */)) { I'm not actually reading from the device- it appears the API is trying to read from nothing at all. I'm going to rename the topic to something a bit more descriptive.

nyholku commented 8 years ago

I think I see what is going on.

We should call "CancelIoEx" aftet m_Thread.interrupt(); (line 137 in HidDevice) because the interrupt() does not interrupt that GetOverlappedResult().

nyholku commented 7 years ago

An attempt to fix this is now in the latest (0.0.7 ->) version so I will close this until someone tells me it does not fix the issue