import java.util.*;
import javax.usb.*;
import javax.usb.event.*;

public class cm15comm extends Thread implements UsbPipeListener {
    public final static short ID_VENDOR = 0x0bc7;
    public final static short ID_PRODUCT = 0x0001;
    public final static short BCD_DEVICE = 0x0100;

    public static void main(String args[]) throws Exception {
	cm15comm pc = new cm15comm();
	pc.start();
	for (int i = 0; i < 9; i++)
	  (new cm15comm(pc)).start();

	sleep(3000);

	pc.getStatus();
	sleep(3000);
	pc.getStatus();
    }

    public cm15comm(cm15comm c) throws Exception {
	_in = c._in;
	_inIRP = _in.createUsbIrp();
    }

    public cm15comm() throws Exception {
	UsbDevice dev = getDevice(UsbHostManager.getUsbServices().getRootUsbHub());
	if (dev == null) {
	    System.err.println("Device not found");
	    return;
	}
	
	System.err.println("Device found");
	processDevice(dev);

	if (_in == null || _out == null)
	    return;

	_in.open();
	_out.open();
	_inIRP = _in.createUsbIrp();
	_outIRP = _out.createUsbIrp();	

	_in.addUsbPipeListener(this);
    }

    public void run() {
	byte buf[] = new byte[8];

//	while (true) {
	    try {
		System.out.println("Listening");
		_inIRP.setData(buf);
		_inIRP.setComplete(false);
		_in.syncSubmit(_inIRP);
		//printBuffer("In", buf);
		System.out.println("Done");
	    } catch (UsbException e) {
		System.err.println(e.toString());
	    }
//	}
    }

    public synchronized void getStatus() throws Exception {
	clearBuf();
	_buf[0] = (byte) 0x8b;
	  
	send();
    }

    public void clearBuf() {
	for (int i = 0; i < _buf.length; i++)
	    _buf[i] = 0;
    }

    public void printBuffer(String dir, byte buf[]) {
	System.out.print(dir + ": ");
	for (int i = 0; i < buf.length; i++)
	    System.out.print(Integer.toHexString(buf[i] & 0xff) + " ");
        System.out.println();

    }

    public void send() throws Exception {
	printBuffer("Out", _buf);
	_outIRP.setData(_buf);
	_outIRP.setUsbException(null);
	_outIRP.setComplete(false);
	_out.syncSubmit(_outIRP);
	System.out.println("Sent");
    }

    public UsbDevice getDevice(UsbHub hub) throws Exception {
	Iterator it = hub.getAttachedUsbDevices().iterator();
	while (it.hasNext()) {
	    UsbDevice dev = (UsbDevice) it.next();
	    if (dev.isUsbHub())
		return getDevice((UsbHub) dev);
	    else {
		UsbDeviceDescriptor desc = dev.getUsbDeviceDescriptor();
		if (desc.idProduct() == ID_PRODUCT
		    && desc.idVendor() == ID_VENDOR
		    && desc.bcdDevice() == BCD_DEVICE)
		    return dev;
	    }
	}

	return null;
    }
    
    public void processDevice(UsbDevice dev) {
	UsbConfiguration config = dev.getActiveUsbConfiguration();
	if (config == null)
	    return;

	Iterator it = config.getUsbInterfaces().iterator();
	while (it.hasNext()) {
	    UsbInterface iface = (UsbInterface) it.next();
	    if (iface.isActive())
		processInterface(iface);
	}
    }

    public void processInterface(UsbInterface iface) {
	try {
	    iface.claim(new ForcePolicy());
	} catch (UsbClaimException e) {
	    System.err.println(e.toString());
	    return;
	} catch (UsbException e) {
	    System.err.println(e.toString());
	    return;
	}

	Iterator it = iface.getUsbEndpoints().iterator();
	while (it.hasNext()) {
	    UsbEndpoint ep = (UsbEndpoint) it.next();
	    if (ep.getDirection() == UsbConst.ENDPOINT_DIRECTION_IN) {
		_in = ep.getUsbPipe();
		//_inIRP = _in.createUsbIrp();
	    } else if (ep.getDirection() == UsbConst.ENDPOINT_DIRECTION_OUT) {
		_out = ep.getUsbPipe();
		//_outIRP = _out.createUsbIrp();	
	    }
	}
    }

    private class ForcePolicy implements UsbInterfacePolicy {
	public boolean forceClaim(UsbInterface i) {
	    return true;
	}
    }

    public void dataEventOccurred(UsbPipeDataEvent event) {
	byte buf[] = event.getData();

	printBuffer("In", buf);
    }

    public void errorEventOccurred(UsbPipeErrorEvent error) {
	error.getUsbException().printStackTrace();
    }

    private UsbPipe _out, _in;
    private UsbIrp _inIRP, _outIRP;
    private byte _buf[] = new byte[8];
}
