/*
 * Copyright (C) 2014 Klaus Reimer <k@ailis.de>
 * See LICENSE.txt for licensing information.
 */

package org.usb4java.examples;

import org.usb4java.Context;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.HotplugCallback;
import org.usb4java.HotplugCallbackHandle;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;

/**
 * Demonstrates how to use the hotplug feature of libusb.
 * 
 * @author Klaus Reimer <k@ailis.de>
 */
public class HotPlug
{
    /**
     * This is the event handling thread. libusb doesn't start threads by
     * its own so it is our own responsibility to give libusb time to handle
     * the events in our own thread.
     */
    static class EventHandlingThread extends Thread
    {
        /** If thread should abort. */
        private volatile boolean abort;
        
        /**
         * Aborts the event handling thread.
         */
        public void abort()
        {
            this.abort = true;
        }
        
        @Override
        public void run()
        {
            while (!this.abort)
            {
                // This call blocks until libusb has handled at least one
                // event or a hotplug callback has been deregistered 
                LibUsb.handleEvents(null);
            }
        }
    }
    
    /**
     * The hotplug callback handler
     */
    static class Callback implements HotplugCallback
    {
        @Override
        public int processEvent(Context context, Device device, int event,
            Object userData)
        {
            DeviceDescriptor descriptor = new DeviceDescriptor();
            LibUsb.getDeviceDescriptor(device, descriptor);
            System.out.format("%s: %04x:%04x%n", 
                event == LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED ? "Connected" : 
                    "Disconnected",
                descriptor.idVendor(), descriptor.idProduct());
            return 0;
        }
    }

    /**
     * Main method.
     * 
     * @param args
     *            Command-line arguments (Ignored)
     * @throws Exception
     *             When something goes wrong.
     */
    public static void main(String[] args) throws Exception
    {
        // Initialize the libusb context
        int result = LibUsb.init(null);
        if (result != LibUsb.SUCCESS)
        {
            throw new LibUsbException("Unable to initialize libusb", result);
        }
        
        // Check if hotplug is available
        if (!LibUsb.hasCapability(LibUsb.CAP_HAS_HOTPLUG))
        {
            System.err.println("libusb doesn't support hotplug on this system");
            System.exit(1);
        }

        // Start the event handling thread
        EventHandlingThread thread = new EventHandlingThread();
        thread.start();

        // Register the hotplug callback
        HotplugCallbackHandle callbackHandle = new HotplugCallbackHandle();
        result = LibUsb.hotplugRegisterCallback(null,
            LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED
                | LibUsb.HOTPLUG_EVENT_DEVICE_LEFT,
            LibUsb.HOTPLUG_ENUMERATE,
            LibUsb.HOTPLUG_MATCH_ANY,
            LibUsb.HOTPLUG_MATCH_ANY,
            LibUsb.HOTPLUG_MATCH_ANY,
            new Callback(), null, callbackHandle);
        if (result != LibUsb.SUCCESS)
        {
            throw new LibUsbException("Unable to register hotplug callback", 
                result);
        }        

        // Our faked application. Hit enter key to exit the application.
        System.out.println("Hit enter to exit the demo");
        System.in.read();
        
        // Unregister the hotplug callback and stop the event handling thread
        thread.abort();        
        LibUsb.hotplugDeregisterCallback(null, callbackHandle);

        // Deinitialize the libusb context
        LibUsb.exit(null);
    }
}

@@ -583,19 +583,19 @@
 s by
+ its
 %0A     *
- its
  own
@@ -660,19 +660,19 @@
 ndle
+ the
 %0A     *
- the
  eve
@@ -839,25 +839,17 @@
  abort;%0A
-        
 %0A
+
         
@@ -984,33 +984,25 @@
 ;%0A        %7D%0A
-        
 %0A
+
         @Ove
@@ -1112,62 +1112,66 @@
  // 
-This call blocks until libusb has handled at least one
+Let libusb handle pending events. This blocks until events
 %0A   
@@ -1190,16 +1190,26 @@
  // 
-event or
+have been handled,
  a h
@@ -1249,50 +1249,318 @@
 ered
- %0A                LibUsb.handleEvents(null
+%0A                // or the specified time of 1 second (Specified in%0A                // Microseconds) has passed.%0A                int result = LibUsb.handleEventsTimeout(null, 1000000);%0A                if (result != LibUsb.SUCCESS)%0A                    throw new LibUsbException(%22Unable to handle events%22, result
 );%0A 
@@ -1588,21 +1588,17 @@
 %7D%0A    %7D%0A
-    
 %0A
+
     /**%0A
@@ -1901,32 +1901,45 @@
 r();%0A           
+ int result =
  LibUsb.getDevic
@@ -1971,16 +1971,165 @@
 iptor);%0A
+            if (result != LibUsb.SUCCESS)%0A                throw new LibUsbException(%22Unable to read device descriptor%22,%0A                    result);%0A
         
@@ -2168,17 +2168,16 @@
 %2504x%25n%22,
- 
 %0A       
@@ -2245,17 +2245,16 @@
 ected%22 :
- 
 %0A       
@@ -2853,25 +2853,17 @@
       %7D%0A
-        
 %0A
+
         
@@ -3814,17 +3814,16 @@
 llback%22,
- 
 %0A       
@@ -3849,24 +3849,16 @@
        %7D
-        
 %0A%0A      
@@ -4008,25 +4008,17 @@
 read();%0A
-        
 %0A
+
         
@@ -4079,32 +4079,32 @@
 handling thread%0A
+
         thread.a
@@ -4110,24 +4110,16 @@
 abort();
-        
 %0A       

Use handleEventTimeout instead of handleEvent and improve error handling