0

I need an event listener to which can listen to hardware changes. I tried to implement this using following method.

import javax.swing.SwingUtilities;
import com.sun.jna.platform.mac.IOKit.IOIterator;
import com.sun.jna.platform.mac.IOKitUtil;
import  com.sun.jna.platform.mac.IOKit.IORegistryEntry;

import java.util.ArrayList;

public class HardwareListener implements Runnable{

    private boolean running;

    private WinController controller;


    public  HardwareListener(WinController _controller){

        this.controller=_controller;
    }

    @Override
    public void run() {
        running = true;
        int prevCount=0;
        IOIterator iterator= `IOKitUtil.getMatchingServices("IOUSBHostDevice");`
        if(iterator !=null){
          IORegistryEntry device = iterator.next();
          while (device!=null){
              device.release();
              device = iterator.next();
              prevCount++;

          }
        }
        System.out.println("1 - Previous Count: "+prevCount);
        while (running){
            System.out.println("Previous Count: "+prevCount);
            int count =0;
            iterator= IOKitUtil.getMatchingServices("IOUSBHostDevice");
            if (iterator!=null){
                IORegistryEntry device = iterator.next();
                while (device!=null){
                    device.release();
                    device = iterator.next();
                    count++;

                }
                if (prevCount!=count){
                    controller.updateUSBList();
                }
                if(prevCount>count){
                    System.out.println("Device Removed");
                }else if (prevCount<count){
                    System.out.println("Device Added");
                }
            }
            if (iterator!=null){
                iterator.release();
            }
            System.out.println("New Count: "+count);
            prevCount=count;
            this.sleep(2);
        }
    }

    private void sleep(int seconds){
        try {
            Thread.sleep((int)seconds*100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void stop() {
        running = false;
    }
}

The above snippet run in a secondary thread. However, the loop in run() function fails to run properly time to time. For example, a when a usb hub connected, I have the pause the thread for around 2 seconds ignorer for:

IOIterator iterator =  IOKitUtil.getMatchingServices("IOUSBHostDevice");` 

to detect all the devices. Otherwise, it will detect them through multiple loops.

I want the codes after this line to run once iterator has all the hardware changes identified.

Please can someone provide a better solution to achieve this functionality ?

Framework AND Other details.

  • Java - OpenJDK 20.0.1
  • Java Native Access (JNA) and JNA platform 5.13.0 to interact with native features.
  • JAVAFX for GUI
kanishka
  • 3
  • 2
  • What libraries and versions are you using? Please provide a [minimal reproducible example](http://stackoverflow.com/help/minimal-reproducible-example). – aled Jun 28 '23 at 15:06
  • It's not clear what the problem is. You say "fails to run properly time to time" which appears to mean it's detecting a change but always detecting the same change, indicating you're not storing the update properly. This appears to be in `controller.updateUSBList()` which you have not posted any code for. – Daniel Widdis Jun 28 '23 at 18:27
  • I will update the question adding more details – kanishka Jun 28 '23 at 19:20
  • After the details it just sounds like you need time for updates to process. What are the debug values for the previous and new count when the problem occurs? Note you're only sleeping for 200 ms with your current code, not 2 seconds. – Daniel Widdis Jun 28 '23 at 19:52
  • The hub I used for testing have 7 devices. I managed to fix the issue my changing sleep to 1500ms – kanishka Jun 29 '23 at 10:40

0 Answers0