OpenCores
URL https://opencores.org/ocsvn/usb_fpga_1_15/usb_fpga_1_15/trunk

Subversion Repositories usb_fpga_1_15

[/] [usb_fpga_1_15/] [trunk/] [java/] [DeviceServer/] [DeviceServer.java] - Diff between revs 3 and 4

Only display areas with differences | Details | Blame | View Log

Rev 3 Rev 4
/*!
/*!
   Firmware / Bitstream loader for the ZTEX EZ-USB FX2 SDK
   DeviceServer for the ZTEX USB-FPGA Modules
   Copyright (C) 2009-2011 ZTEX GmbH.
   Copyright (C) 2009-2014 ZTEX GmbH.
   http://www.ztex.de
   http://www.ztex.de
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3 as
   it under the terms of the GNU General Public License version 3 as
   published by the Free Software Foundation.
   published by the Free Software Foundation.
 
 
   This program is distributed in the hope that it will be useful, but
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.
   General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program; if not, see http://www.gnu.org/licenses/.
   along with this program; if not, see http://www.gnu.org/licenses/.
!*/
!*/
 
 
/*
/*
    ZTEX device server
    ZTEX device server
*/
*/
 
 
import java.io.*;
import java.io.*;
import java.util.*;
import java.util.*;
import java.text.*;
import java.text.*;
import java.net.*;
import java.net.*;
 
 
import com.sun.net.httpserver.*;
import com.sun.net.httpserver.*;
 
 
import ch.ntb.usb.*;
import ch.ntb.usb.*;
 
 
import ztex.*;
import ztex.*;
 
 
// *****************************************************************************
// *****************************************************************************
// ******* ErrorBuffer *********************************************************
// ******* ErrorBuffer *********************************************************
// *****************************************************************************
// *****************************************************************************
class ErrorBuffer {
class ErrorBuffer {
    private static final int bufsize = 128;
    private static final int bufsize = 128;
    private static String cids[] = new String[bufsize];
    private static String cids[] = new String[bufsize];
    private static StringBuilder messages[] = new StringBuilder[bufsize];
    private static StringBuilder messages[] = new StringBuilder[bufsize];
    private static int id[] = new int[bufsize];
    private static int id[] = new int[bufsize];
    private static boolean initialized = false;
    private static boolean initialized = false;
    private static int idcnt = 0;
    private static int idcnt = 0;
 
 
    private static void initialize() {
    private static void initialize() {
        if ( ! initialized ) {
        if ( ! initialized ) {
            for ( int i=0; i<bufsize; i++ )
            for ( int i=0; i<bufsize; i++ )
                id[i]=-1;
                id[i]=-1;
            initialized = true;
            initialized = true;
        }
        }
    }
    }
 
 
    public static void add (String cid, StringBuilder message) {
    public static void add (String cid, StringBuilder message) {
        if (cid==null) return;
        if (cid==null) return;
        initialize();
        initialize();
        int j=0, k=-1;
        int j=0, k=-1;
        for ( int i=0; i<bufsize; i++ ) {
        for ( int i=0; i<bufsize; i++ ) {
            if ( id[i]<id[j] ) j=i;
            if ( id[i]<id[j] ) j=i;
            if ( id[i]>=0 && cid.equals(cids[i]) ) k=i;
            if ( id[i]>=0 && cid.equals(cids[i]) ) k=i;
        }
        }
        if ( k>=0 ) {
        if ( k>=0 ) {
            messages[k].append(message);
            messages[k].append(message);
        }
        }
        else {
        else {
            id[j] = idcnt;
            id[j] = idcnt;
            idcnt ++;
            idcnt ++;
            messages[j] = message;
            messages[j] = message;
            cids[j] = cid;
            cids[j] = cid;
        }
        }
    }
    }
 
 
    public static StringBuilder get (String cid) {
    public static StringBuilder get (String cid) {
        if (cid==null) return null;
        if (cid==null) return null;
        initialize();
        initialize();
        for ( int i=0; i<bufsize; i++ ) {
        for ( int i=0; i<bufsize; i++ ) {
            if ( id[i]>=0 && cid.equals(cids[i]) ) {
            if ( id[i]>=0 && cid.equals(cids[i]) ) {
                id[i] = -1;
                id[i] = -1;
                return messages[i];
                return messages[i];
            }
            }
        }
        }
        return null;
        return null;
    }
    }
}
}
 
 
// *****************************************************************************
// *****************************************************************************
// ******* NonBlockingBufferedInputStream **************************************
// ******* NonBlockingBufferedInputStream **************************************
// *****************************************************************************
// *****************************************************************************
class NonBlockingBufferedInputStream extends BufferedInputStream {
class NonBlockingBufferedInputStream extends BufferedInputStream {
    private final int timeout = 1000;
    private final int timeout = 1000;
    private final int delay = 10;
    private final int delay = 10;
 
 
    NonBlockingBufferedInputStream(InputStream in) {
    NonBlockingBufferedInputStream(InputStream in) {
        super(in);
        super(in);
    }
    }
 
 
    public int read( byte[] b, int off, int len) throws IOException {
    public int read( byte[] b, int off, int len) throws IOException {
        int cnt=0, a=1;
        int cnt=0, a=1;
        while ( len > 0 && a>0 ) {
        while ( len > 0 && a>0 ) {
            a=available();
            a=available();
            int to=0;
            int to=0;
            while ( a<1 && to<timeout ) {
            while ( a<1 && to<timeout ) {
                try {
                try {
                    Thread.sleep( delay );
                    Thread.sleep( delay );
                }
                }
                catch ( InterruptedException e) {
                catch ( InterruptedException e) {
                }
                }
                a=available();
                a=available();
                to+=delay;
                to+=delay;
            }
            }
            if (a > len ) a=len;
            if (a > len ) a=len;
            if ( a > 0 ) super.read(b, off, a);
            if ( a > 0 ) super.read(b, off, a);
            off+=a;
            off+=a;
            len-=a;
            len-=a;
            cnt+=a;
            cnt+=a;
        }
        }
        return cnt;
        return cnt;
    }
    }
 
 
    public void close() {
    public void close() {
    }
    }
 
 
}
}
 
 
// *****************************************************************************
// *****************************************************************************
// ******* SocketThread ********************************************************
// ******* SocketThread ********************************************************
// *****************************************************************************
// *****************************************************************************
class SocketThread extends Thread {
class SocketThread extends Thread {
    private Socket socket;
    private Socket socket;
    private PrintStream printer = null;
    private PrintStream printer = null;
    private BufferedOutputStream binOut = null;
    private BufferedOutputStream binOut = null;
    private NonBlockingBufferedInputStream in = null;
    private NonBlockingBufferedInputStream in = null;
 
 
// ******* SocketThread ********************************************************
// ******* SocketThread ********************************************************
    public SocketThread ( Socket s ) {
    public SocketThread ( Socket s ) {
        socket = s;
        socket = s;
        DeviceServer.addSocket(socket);
        DeviceServer.addSocket(socket);
        start();
        start();
    }
    }
 
 
// ******* out *****************************************************************
// ******* out *****************************************************************
    private BufferedOutputStream binOut() throws IOException {
    private BufferedOutputStream binOut() throws IOException {
        if ( binOut == null ) binOut = new BufferedOutputStream( socket.getOutputStream() );
        if ( binOut == null ) binOut = new BufferedOutputStream( socket.getOutputStream() );
        if ( printer != null ) {
        if ( printer != null ) {
            printer.flush();
            printer.flush();
            printer = new PrintStream( binOut );
            printer = new PrintStream( binOut );
        }
        }
        return binOut;
        return binOut;
    }
    }
 
 
// ******* writer **************************************************************
// ******* writer **************************************************************
    private PrintStream printer() throws IOException {
    private PrintStream printer() throws IOException {
        if ( printer == null ) printer = new PrintStream( binOut==null ? socket.getOutputStream() : binOut, true);
        if ( printer == null ) printer = new PrintStream( binOut==null ? socket.getOutputStream() : binOut, true);
        return printer;
        return printer;
    }
    }
 
 
// ******* printHelp ***********************************************************
// ******* printHelp ***********************************************************
    private void printHelp ( String cmd ) throws IOException  {
    private void printHelp ( String cmd ) throws IOException  {
        boolean all = cmd.equalsIgnoreCase("all");
        boolean all = cmd.equalsIgnoreCase("all");
        PrintStream out = printer();
        PrintStream out = printer();
        boolean b = false;
        boolean b = false;
        if ( all || cmd.equalsIgnoreCase("help") ) {
        if ( all || cmd.equalsIgnoreCase("help") ) {
            out.println( "Supported commands:\n" +
            out.println( "Supported commands:\n" +
                         "  scan     Scan buses\n" +
                         "  scan     Scan buses\n" +
                         "  info     Print device capabilities\n" +
                         "  info     Print device capabilities\n" +
                         "  upload   Upload firmware\n" +
                         "  upload   Upload firmware\n" +
                         "  config   Configure FPGA\n" +
                         "  config   Configure FPGA\n" +
                         "  read     Read data from given endpoint\n" +
                         "  read     Read data from given endpoint\n" +
                         "  write    Write data to given endpoint\n" +
                         "  write    Write data to given endpoint\n" +
                         "  errors   Returns errors\n" +
                         "  errors   Returns errors\n" +
                         "  help     Help\n" +
                         "  help     Help\n" +
                         "  quit     Quit Device Server\n" +
                         "  quit     Quit Device Server\n" +
                         "\n" +
                         "\n" +
                         "See help <command>|all  for detailed info\n" );
                         "See help <command>|all  for detailed info\n" );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("scan") ) {
        if ( all || cmd.equalsIgnoreCase("scan") ) {
            out.println( "[<cid:>]scan [-bin]\n" +
            out.println( "[<cid:>]scan [-bin]\n" +
                         "  (Re)scan buses and returns the device list. If <cid> and -bin are specified\n" +
                         "  (Re)scan buses and returns the device list. If <cid> and -bin are specified\n" +
                         "  errors are stored and can be read out using \"errors <cid>\". If -bin is not\n" +
                         "  errors are stored and can be read out using \"errors <cid>\". If -bin is not\n" +
                         "  specified errors are returned directly.\n" +
                         "  specified errors are returned directly.\n" +
                         "    -bin   print it in (computer friendly) binary format\n"
                         "    -bin   print it in (computer friendly) binary format\n"
                        );
                        );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("info") ) {
        if ( all || cmd.equalsIgnoreCase("info") ) {
            out.println( "info <bus index> <device number>\n" +
            out.println( "info <bus index> <device number>\n" +
                         "  Returns device capabilities.\n"
                         "  Returns device capabilities.\n"
                        );
                        );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("upload") ) {
        if ( all || cmd.equalsIgnoreCase("upload") ) {
            out.println( "upload <bus index> <device number> [-v] [-nv] [-e] [-f]\n" +
            out.println( "upload <bus index> <device number> [-v] [-nv] [-e] [-f]\n" +
                         "  Upload firmware to USB controller. Returns errors, if any.\n" +
                         "  Upload firmware to USB controller. Returns errors, if any.\n" +
                         "    -v   upload to volatile memory (default if neither -nv nor -env is given)\n" +
                         "    -v   upload to volatile memory (default if neither -nv nor -env is given)\n" +
                         "    -nv  upload to non-volatile memory\n" +
                         "    -nv  upload to non-volatile memory\n" +
                         "    -e   erase / disable firmware in non-volatile memory\n" +
                         "    -e   erase / disable firmware in non-volatile memory\n" +
                         "    -f   force upload of incompatible firmware\n"
                         "    -f   force upload of incompatible firmware\n"
                        );
                        );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("config") ) {
        if ( all || cmd.equalsIgnoreCase("config") ) {
            out.println( "config <bus index> <device number> [-v] [-nv] [-e] [-f]\n" +
            out.println( "config <bus index> <device number> [-v] [-nv] [-e] [-f]\n" +
                         "  Configure FPGA. Returns errors, if any.\n" +
                         "  Configure FPGA. Returns errors, if any.\n" +
                         "    -v    upload to volatile memory (default if -nv is not given)\n" +
                         "    -v    upload to volatile memory (default if -nv is not given)\n" +
                         "    -nv   upload to non-volatile memory\n" +
                         "    -nv   upload to non-volatile memory\n" +
                         "    -e    erase / disable bitstream in non-volatile memory\n" +
                         "    -e    erase / disable bitstream in non-volatile memory\n" +
                         "    -f    force upload if already configured\n"
                         "    -f    force upload if already configured\n"
                        );
                        );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("read") ) {
        if ( all || cmd.equalsIgnoreCase("read") ) {
            out.println( "[<cid>:]read <bus index> <device number> <ep> [<max. bytes>]\n" +
            out.println( "[<cid>:]read <bus index> <device number> <ep> [<max. bytes>]\n" +
                         "  Read data from endpoint and returns them. If <max. bytes> if not specified\n" +
                         "  Read data from endpoint and returns them. If <max. bytes> if not specified\n" +
                         "  data is read until end. If <cid> is specified errors are stored and can be\n" +
                         "  data is read until end. If <cid> is specified errors are stored and can be\n" +
                         "  read out using \"errors <cid>\" \n"
                         "  read out using \"errors <cid>\" \n"
                        );
                        );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("write") ) {
        if ( all || cmd.equalsIgnoreCase("write") ) {
            out.println( "write <bus number> <device number> <ep>\n" +
            out.println( "write <bus number> <device number> <ep>\n" +
                         "  write data to endpoint. Returns errors, if any.\n"
                         "  write data to endpoint. Returns errors, if any.\n"
                       );
                       );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("errors") ) {
        if ( all || cmd.equalsIgnoreCase("errors") ) {
            out.println( "errors <cid>\n" +
            out.println( "errors <cid>\n" +
                         "  Returns errors stored under <cid>.\n"
                         "  Returns errors stored under <cid>.\n"
                       );
                       );
            b=true;
            b=true;
        }
        }
 
 
        if ( all || cmd.equalsIgnoreCase("quit") ) {
        if ( all || cmd.equalsIgnoreCase("quit") ) {
            out.println( "quit\n" +
            out.println( "quit\n" +
                         "  Quit Device Server\n"
                         "  Quit Device Server\n"
                       );
                       );
            b=true;
            b=true;
        }
        }
 
 
        if ( ! b )  {
        if ( ! b )  {
            out.println( "No help available for command " + cmd + "\n");
            out.println( "No help available for command " + cmd + "\n");
        }
        }
    }
    }
 
 
// ******* str2bin *************************************************************
// ******* str2bin *************************************************************
    private static void str2bin( String s, byte buf[], int start, int len ) {
    private static void str2bin( String s, byte buf[], int start, int len ) {
        byte bytes[] = null;
        byte bytes[] = null;
        int l = 0;
        int l = 0;
        if ( s != null ) {
        if ( s != null ) {
            bytes = s.getBytes();
            bytes = s.getBytes();
            l = Math.min(bytes.length,len);
            l = Math.min(bytes.length,len);
        }
        }
        for ( int i=0; i<l; i++ )
        for ( int i=0; i<l; i++ )
            buf[start+i]=bytes[i];
            buf[start+i]=bytes[i];
        for ( int i=l; i<len; i++ )
        for ( int i=l; i<len; i++ )
            buf[start+i]=0;
            buf[start+i]=0;
    }
    }
 
 
// ******* scan ****************************************************************
// ******* scan ****************************************************************
    private void scan ( boolean bin ) throws IOException  {
    private void scan ( boolean bin ) throws IOException  {
        DeviceServer.scanUSB();
        DeviceServer.scanUSB();
        int n = DeviceServer.numberOfDevices();
        int n = DeviceServer.numberOfDevices();
        if ( bin ) {
        if ( bin ) {
            byte buf[] = new byte[7+15+64+64];
            byte buf[] = new byte[7+15+64+64];
            BufferedOutputStream out = binOut();
            BufferedOutputStream out = binOut();
            if ( n>255 ) n=255;
            if ( n>255 ) n=255;
            out.write(n);
            out.write(n);
            for ( int i=0; i<n; i++ ) {
            for ( int i=0; i<n; i++ ) {
                try {
                try {
                    ZtexDevice1 dev = DeviceServer.device(i);
                    ZtexDevice1 dev = DeviceServer.device(i);
                    buf[0] = (byte) DeviceServer.busIdx(i);
                    buf[0] = (byte) DeviceServer.busIdx(i);
                    buf[1] = (byte) DeviceServer.devNum(i);
                    buf[1] = (byte) DeviceServer.devNum(i);
                    buf[2] = (byte) (dev.valid() ? 1 : 0);
                    buf[2] = (byte) (dev.valid() ? 1 : 0);
                    buf[3] = (byte) dev.productId(0);
                    buf[3] = (byte) dev.productId(0);
                    buf[4] = (byte) dev.productId(1);
                    buf[4] = (byte) dev.productId(1);
                    buf[5] = (byte) dev.productId(2);
                    buf[5] = (byte) dev.productId(2);
                    buf[6] = (byte) dev.productId(3);
                    buf[6] = (byte) dev.productId(3);
                    str2bin( dev.snString(), buf,7,15);
                    str2bin( dev.snString(), buf,7,15);
                    str2bin( dev.manufacturerString(), buf,22,64);
                    str2bin( dev.manufacturerString(), buf,22,64);
                    str2bin( dev.productString(), buf,86,64);
                    str2bin( dev.productString(), buf,86,64);
                    out.write(buf);
                    out.write(buf);
                }
                }
                catch ( IndexOutOfBoundsException e ) {
                catch ( IndexOutOfBoundsException e ) {
                }
                }
            }
            }
            out.flush();
            out.flush();
        }
        }
        else {
        else {
            PrintStream out = printer();
            PrintStream out = printer();
            if ( n<1 ) {
            if ( n<1 ) {
                out.println("(No devices)");
                out.println("(No devices)");
            }
            }
            else {
            else {
                out.println("# <busIdx>:<devNum>        <busName>       <product ID'S>  <serial number string>  <manufacturer string>   <product name>");
                out.println("# <busIdx>:<devNum>        <busName>       <product ID'S>  <serial number string>  <manufacturer string>   <product name>");
            }
            }
            for ( int i=0; i<n; i++ ) {
            for ( int i=0; i<n; i++ ) {
                try {
                try {
                    ZtexDevice1 dev = DeviceServer.device(i);
                    ZtexDevice1 dev = DeviceServer.device(i);
                    out.println(DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i)
                    out.println(DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i)
                            + " " + dev.dev().getBus().getDirname()
                            + " " + dev.dev().getBus().getDirname()
                            + ( dev.valid() ? ( "       " + ZtexDevice1.byteArrayString(dev.productId()) ) : "  (unconfigured)" )
                            + ( dev.valid() ? ( "       " + ZtexDevice1.byteArrayString(dev.productId()) ) : "  (unconfigured)" )
                            + " \"" + ( dev.snString() == null ? "" : dev.snString() ) + "\""
                            + " \"" + ( dev.snString() == null ? "" : dev.snString() ) + "\""
                            + " \"" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "\""
                            + " \"" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "\""
                            + " \"" + ( dev.productString() == null ? "" : dev.productString() ) + "\""  );
                            + " \"" + ( dev.productString() == null ? "" : dev.productString() ) + "\""  );
 
 
                }
                }
                catch ( IndexOutOfBoundsException e ) {
                catch ( IndexOutOfBoundsException e ) {
                }
                }
            }
            }
 
 
        }
        }
    }
    }
 
 
// ******* info ****************************************************************
// ******* info ****************************************************************
    private void info ( int busIdx, int devNum ) throws IOException, Exception  {
    private void info ( int busIdx, int devNum ) throws IOException, Exception  {
        ZtexDevice1 dev = DeviceServer.findDevice(busIdx,devNum);
        ZtexDevice1 dev = DeviceServer.findDevice(busIdx,devNum);
        EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
        EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
        if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
        if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
        Ztex1v1 ztex = new Ztex1v1(dev);
        Ztex1v1 ztex = new Ztex1v1(dev);
        PrintStream out = printer();
        PrintStream out = printer();
        out.println("Bus name: " + dev.dev().getBus().getDirname() );
        out.println("Bus name: " + dev.dev().getBus().getDirname() );
        out.println("Device Number: " + devNum );
        out.println("Device Number: " + devNum );
        out.println("USB ID's: " + Integer.toHexString(dev.usbVendorId()) + ":" + Integer.toHexString(dev.usbProductId()) );
        out.println("USB ID's: " + Integer.toHexString(dev.usbVendorId()) + ":" + Integer.toHexString(dev.usbProductId()) );
        out.println("Product ID's: " + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) );
        out.println("Product ID's: " + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) );
        out.println("Firmware version: " + ( dev.valid() ? (dev.fwVersion() & 255) : "" ) );
        out.println("Firmware version: " + ( dev.valid() ? (dev.fwVersion() & 255) : "" ) );
        out.println("Serial Number String: " + ( dev.snString() == null ? "" : dev.snString() ) );
        out.println("Serial Number String: " + ( dev.snString() == null ? "" : dev.snString() ) );
        out.println("Manufacturer String: " + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) );
        out.println("Manufacturer String: " + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) );
        out.println("Product String: " + ( dev.productString() == null ? "" : dev.productString() ) );
        out.println("Product String: " + ( dev.productString() == null ? "" : dev.productString() ) );
        String s = ztex.capabilityInfo("\nCapability: ");
        String s = ztex.capabilityInfo("\nCapability: ");
        if ( s.length()>0 ) out.println("Capability: " + s);
        if ( s.length()>0 ) out.println("Capability: " + s);
        if ( ztex.config != null ) {
        if ( ztex.config != null ) {
            out.println("ZTEX Product: " + ztex.config.getName());
            out.println("ZTEX Product: " + ztex.config.getName());
            out.println("FPGA: " + ztex.config.getFpga());
            out.println("FPGA: " + ztex.config.getFpga());
            if (ztex.config.getRamSize()>0)  out.println("RAM: " + (ztex.config.getRamSize() >> 20) + " MByte " + ztex.config.getRamType());
            if (ztex.config.getRamSize()>0)  out.println("RAM: " + (ztex.config.getRamSize() >> 20) + " MByte " + ztex.config.getRamType());
        }
        }
        s = ztex.flashInfo(); if ( s.length()>0 ) out.println("Flash: " + s);
        s = ztex.flashInfo(); if ( s.length()>0 ) out.println("Flash: " + s);
        try {
        try {
            s = ztex.getFpgaConfigurationStr();
            s = ztex.getFpgaConfigurationStr();
            out.println("FPGA State: " + s);
            out.println("FPGA State: " + s);
        } catch ( Exception e ) {
        } catch ( Exception e ) {
        }
        }
        if ( eps!=null ) {
        if ( eps!=null ) {
            for ( int i=0; i<eps.size(); i++ ) {
            for ( int i=0; i<eps.size(); i++ ) {
                EPDescriptor ep = eps.elementAt(i);
                EPDescriptor ep = eps.elementAt(i);
                out.println("Endpoint: "+ep.num()+" "+(ep.in() ? "read" : "write"));
                out.println("Endpoint: "+ep.num()+" "+(ep.in() ? "read" : "write"));
            }
            }
        }
        }
    }
    }
 
 
// ******* run *****************************************************************
// ******* run *****************************************************************
    public void run () {
    public void run () {
        final int bufSize = 512;
        final int bufSize = 512;
        final int maxArgs = 32;
        final int maxArgs = 32;
 
 
        byte buf[] = new byte[bufSize];
        byte buf[] = new byte[bufSize];
        String args[] = new String[maxArgs];
        String args[] = new String[maxArgs];
        int bufN=0, argsN=0;
        int bufN=0, argsN=0;
        String cid="", cid2=null;
        String cid="", cid2=null;
        boolean noErrors = false;
        boolean noErrors = false;
 
 
        try {
        try {
            in = new NonBlockingBufferedInputStream( socket.getInputStream() );
            in = new NonBlockingBufferedInputStream( socket.getInputStream() );
 
 
            // read command and args        
            // read command and args        
            int b = 0;
            int b = 0;
            do {
            do {
                b = in.read();
                b = in.read();
                if ( b <= 32 ) {
                if ( b <= 32 ) {
                    if ( bufN > 0 ) {
                    if ( bufN > 0 ) {
                        if ( argsN >= maxArgs ) throw new Exception("Error reading command: Argument buffer overflow");
                        if ( argsN >= maxArgs ) throw new Exception("Error reading command: Argument buffer overflow");
                        args[argsN] = new String(buf,0,bufN);
                        args[argsN] = new String(buf,0,bufN);
                        argsN+=1;
                        argsN+=1;
                        bufN=0;
                        bufN=0;
                    }
                    }
                }
                }
                else {
                else {
                    if ( bufN >= bufSize ) throw new Exception("Error reading command: Buffer overflow");
                    if ( bufN >= bufSize ) throw new Exception("Error reading command: Buffer overflow");
                    buf[bufN] = (byte) b;
                    buf[bufN] = (byte) b;
                    bufN+=1;
                    bufN+=1;
                }
                }
            } while (b!=10 && b>0);
            } while (b!=10 && b>0);
 
 
            if ( argsN == 0 ) throw new Exception ("Command missed");
            if ( argsN == 0 ) throw new Exception ("Command missed");
        }
        }
        catch (Exception e) {
        catch (Exception e) {
//          DeviceServer.error("Error: "+e.getLocalizedMessage() );
//          DeviceServer.error("Error: "+e.getLocalizedMessage() );
            try {
            try {
                printer().println("Error: "+e.getLocalizedMessage());
                printer().println("Error: "+e.getLocalizedMessage());
            }
            }
            catch (IOException f) {
            catch (IOException f) {
                DeviceServer.error("Error: "+e.getLocalizedMessage() );
                DeviceServer.error("Error: "+e.getLocalizedMessage() );
            }
            }
        }
        }
 
 
        StringBuilder messages = new StringBuilder();
        StringBuilder messages = new StringBuilder();
        if ( args[0].indexOf(':') > 0 ) {
        if ( args[0].indexOf(':') > 0 ) {
            int i = args[0].lastIndexOf(':');
            int i = args[0].lastIndexOf(':');
            cid = args[0].substring(0,i);
            cid = args[0].substring(0,i);
            args[0] = args[0].substring(i+1);
            args[0] = args[0].substring(i+1);
        }
        }
 
 
        // process commands
        // process commands
        try {
        try {
            // quit
            // quit
            if ( args[0].equalsIgnoreCase("quit") ) {
            if ( args[0].equalsIgnoreCase("quit") ) {
                DeviceServer.quit = true;
                DeviceServer.quit = true;
            }
            }
            // help [<command>]
            // help [<command>]
            else if ( args[0].equalsIgnoreCase("help") ) {
            else if ( args[0].equalsIgnoreCase("help") ) {
                if ( argsN < 2 ) printHelp("help");
                if ( argsN < 2 ) printHelp("help");
                for ( int i=1; i<argsN; i++ ) {
                for ( int i=1; i<argsN; i++ ) {
                    printHelp( args[i] );
                    printHelp( args[i] );
                }
                }
            }
            }
            // [<cid>:]scan [-bin]
            // [<cid>:]scan [-bin]
            else if ( args[0].equalsIgnoreCase("scan") ) {
            else if ( args[0].equalsIgnoreCase("scan") ) {
                if ( argsN > 2 ) throw new Exception("scan: to much parameters" );
                if ( argsN > 2 ) throw new Exception("scan: to much parameters" );
                if ( argsN==2 && ! args[1].equalsIgnoreCase("-bin") ) throw new Exception("scan: invalid parameter: " + args[1] );
                if ( argsN==2 && ! args[1].equalsIgnoreCase("-bin") ) throw new Exception("scan: invalid parameter: " + args[1] );
                if ( argsN == 2 ) noErrors = true;
                if ( argsN == 2 ) noErrors = true;
                scan( argsN==2 );
                scan( argsN==2 );
            }
            }
            // info <bus index> <device number>
            // info <bus index> <device number>
            else if ( args[0].equalsIgnoreCase("info") ) {
            else if ( args[0].equalsIgnoreCase("info") ) {
                if ( argsN !=3 ) throw new Exception("info: invalid number of parameters" );
                if ( argsN !=3 ) throw new Exception("info: invalid number of parameters" );
                info( Integer.valueOf(args[1]), Integer.valueOf(args[2]) );
                info( Integer.valueOf(args[1]), Integer.valueOf(args[2]) );
            }
            }
            // upload <bus index> <device number> [-v] [-nv] [-e] [-f] 
            // upload <bus index> <device number> [-v] [-nv] [-e] [-f] 
            // config <bus index> <device number> [-v] [-nv] [-e] [-f]
            // config <bus index> <device number> [-v] [-nv] [-e] [-f]
            else if ( args[0].equalsIgnoreCase("upload") || args[0].equalsIgnoreCase("config") ) {
            else if ( args[0].equalsIgnoreCase("upload") || args[0].equalsIgnoreCase("config") ) {
                if ( argsN<3 ) throw new Exception(args[0]+": to less parameters" );
                if ( argsN<3 ) throw new Exception(args[0]+": to less parameters" );
                boolean vola=false, nonvola=false, erase=false, force=false;
                boolean vola=false, nonvola=false, erase=false, force=false;
                for ( int i=3; i<argsN; i++) {
                for ( int i=3; i<argsN; i++) {
                    if ("-v".equalsIgnoreCase(args[i])) vola=true;
                    if ("-v".equalsIgnoreCase(args[i])) vola=true;
                    else if ("-nv".equalsIgnoreCase(args[i])) nonvola=true;
                    else if ("-nv".equalsIgnoreCase(args[i])) nonvola=true;
                    else if ("-e".equalsIgnoreCase(args[i])) erase=true;
                    else if ("-e".equalsIgnoreCase(args[i])) erase=true;
                    else if ("-f".equalsIgnoreCase(args[i])) force=true;
                    else if ("-f".equalsIgnoreCase(args[i])) force=true;
                    else throw new Exception("Invalid parameter: "+args[i]);
                    else throw new Exception("Invalid parameter: "+args[i]);
                }
                }
                int busIdx=Integer.valueOf(args[1]);
                int busIdx=Integer.valueOf(args[1]);
                int devNum=Integer.valueOf(args[2]);
                int devNum=Integer.valueOf(args[2]);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                Ztex1v1 ztex = new Ztex1v1(dev);
                Ztex1v1 ztex = new Ztex1v1(dev);
 
 
                if ( args[0].equalsIgnoreCase("upload")) {
                if ( args[0].equalsIgnoreCase("upload")) {
                    DeviceServer.loadFirmware ( ztex, messages, in, IPPermissions.toString( socket.getInetAddress() ), force, vola, nonvola, erase );
                    DeviceServer.loadFirmware ( ztex, messages, in, IPPermissions.toString( socket.getInetAddress() ), force, vola, nonvola, erase );
                    int ndn = ztex.dev().dev().getDevnum();
                    int ndn = ztex.dev().dev().getDevnum();
                    if ( ndn != devNum ) {
                    if ( ndn != devNum ) {
                        messages.append("Device re-numerated: " + busIdx + ":" + devNum + " -> " + busIdx + ":" + ndn + "\n");
                        messages.append("Device re-numerated: " + busIdx + ":" + devNum + " -> " + busIdx + ":" + ndn + "\n");
                        DeviceServer.scanUSB();
                        DeviceServer.scanUSB();
                    }
                    }
                }
                }
                else {
                else {
                    DeviceServer.loadBitstream ( ztex, messages, in, IPPermissions.toString( socket.getInetAddress() ), force, vola, nonvola, erase );
                    DeviceServer.loadBitstream ( ztex, messages, in, IPPermissions.toString( socket.getInetAddress() ), force, vola, nonvola, erase );
                }
                }
            }
            }
            // write <bus number> <device number> <ep> 
            // write <bus number> <device number> <ep> 
            else if ( args[0].equalsIgnoreCase("write") ) {
            else if ( args[0].equalsIgnoreCase("write") ) {
                if ( argsN !=4 ) throw new Exception("write: invalid number of parameters" );
                if ( argsN !=4 ) throw new Exception("write: invalid number of parameters" );
                int busIdx=Integer.valueOf(args[1]);
                int busIdx=Integer.valueOf(args[1]);
                int devNum=Integer.valueOf(args[2]);
                int devNum=Integer.valueOf(args[2]);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                Ztex1v1 ztex = new Ztex1v1(dev);
                Ztex1v1 ztex = new Ztex1v1(dev);
                EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
                EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
                try {
                try {
                    DeviceServer.epUpload (ztex, eps.find(Integer.valueOf(args[3])), in, messages);
                    DeviceServer.epUpload (ztex, eps.find(Integer.valueOf(args[3])), in, messages);
                }
                }
                finally {
                finally {
                    DeviceServer.release(ztex);
                    DeviceServer.release(ztex);
                }
                }
            }
            }
            // [<cid>:]read <bus index> <device number> <ep> [<max. bytes>]
            // [<cid>:]read <bus index> <device number> <ep> [<max. bytes>]
            else if ( args[0].equalsIgnoreCase("read") ) {
            else if ( args[0].equalsIgnoreCase("read") ) {
                noErrors = true;
                noErrors = true;
                if ( argsN<4 || argsN>5 ) throw new Exception("read: invalid number of parameters" );
                if ( argsN<4 || argsN>5 ) throw new Exception("read: invalid number of parameters" );
                int busIdx=Integer.valueOf(args[1]);
                int busIdx=Integer.valueOf(args[1]);
                int devNum=Integer.valueOf(args[2]);
                int devNum=Integer.valueOf(args[2]);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum);
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found");
                Ztex1v1 ztex = new Ztex1v1(dev);
                Ztex1v1 ztex = new Ztex1v1(dev);
                EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
                EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
                int max_size = argsN==5 ? Integer.valueOf(args[4]) : Integer.MAX_VALUE;
                int max_size = argsN==5 ? Integer.valueOf(args[4]) : Integer.MAX_VALUE;
                try {
                try {
                    DeviceServer.epDownload (ztex, eps.find(Integer.valueOf(args[3])), binOut(), max_size, messages);
                    DeviceServer.epDownload (ztex, eps.find(Integer.valueOf(args[3])), binOut(), max_size, messages);
                    binOut.flush();
                    binOut.flush();
                }
                }
                finally {
                finally {
                    DeviceServer.release(ztex);
                    DeviceServer.release(ztex);
                }
                }
            }
            }
            // error <cid>
            // error <cid>
            else if ( args[0].equalsIgnoreCase("errors") ) {
            else if ( args[0].equalsIgnoreCase("errors") ) {
                cid2 = cid;
                cid2 = cid;
                cid = null;
                cid = null;
                if ( argsN > 2 ) throw new Exception("errors: to much parameters" );
                if ( argsN > 2 ) throw new Exception("errors: to much parameters" );
                if ( argsN == 2 ) cid2 = args[1];
                if ( argsN == 2 ) cid2 = args[1];
                messages = ErrorBuffer.get(cid2);
                messages = ErrorBuffer.get(cid2);
                if (messages != null) printer().print( messages );
                if (messages != null) printer().print( messages );
                messages = new StringBuilder();
                messages = new StringBuilder();
            }
            }
            else {
            else {
                throw new Exception("Invalid command: "+args[0] );
                throw new Exception("Invalid command: "+args[0] );
            }
            }
        }
        }
        catch ( IOException e) {
        catch ( IOException e) {
            DeviceServer.error("Error: "+e.getLocalizedMessage() );
            DeviceServer.error("Error: "+e.getLocalizedMessage() );
        }
        }
        catch (NumberFormatException e) {
        catch (NumberFormatException e) {
            messages.append("Error: Number expected: "+e.getLocalizedMessage()+"\n");
            messages.append("Error: Number expected: "+e.getLocalizedMessage()+"\n");
        }
        }
        catch (Exception e) {
        catch (Exception e) {
            messages.append("Error: "+e.getLocalizedMessage()+"\n");
            messages.append("Error: "+e.getLocalizedMessage()+"\n");
        }
        }
 
 
        try {
        try {
            if ( messages != null && messages.length()>0 ) {
            if ( messages != null && messages.length()>0 ) {
                if ( ! noErrors ) printer().print(messages);
                if ( ! noErrors ) printer().print(messages);
                ErrorBuffer.add(cid,messages);
                ErrorBuffer.add(cid,messages);
            }
            }
        }
        }
        catch ( IOException e) {
        catch ( IOException e) {
            DeviceServer.error("Error2: "+e.getLocalizedMessage() );
            DeviceServer.error("Error2: "+e.getLocalizedMessage() );
        }
        }
 
 
 
 
        try {
        try {
            socket.getInputStream().close();
            socket.getInputStream().close();
        }
        }
        catch (Exception e) {
        catch (Exception e) {
            DeviceServer.error("Error closing input stream: "+e.getLocalizedMessage() );
            DeviceServer.error("Error closing input stream: "+e.getLocalizedMessage() );
        }
        }
 
 
        try {
        try {
            if ( binOut!=null ) binOut.close();
            if ( binOut!=null ) binOut.close();
            else if ( printer != null ) printer.close();
            else if ( printer != null ) printer.close();
        }
        }
        catch (Exception e) {
        catch (Exception e) {
            DeviceServer.error("Error closing output stream: "+e.getLocalizedMessage() );
            DeviceServer.error("Error closing output stream: "+e.getLocalizedMessage() );
        }
        }
 
 
        DeviceServer.removeSocket(socket);
        DeviceServer.removeSocket(socket);
        try {
        try {
            socket.close();
            socket.close();
        }
        }
        catch (Exception e) {
        catch (Exception e) {
            DeviceServer.error("Error closing output socket: "+e.getLocalizedMessage() );
            DeviceServer.error("Error closing output socket: "+e.getLocalizedMessage() );
        }
        }
    }
    }
}
}
 
 
 
 
// *****************************************************************************
// *****************************************************************************
// ******* MultipartFormDataReader ********************************************
// ******* MultipartFormDataReader ********************************************
// *****************************************************************************
// *****************************************************************************
class MultipartFormDataReader {
class MultipartFormDataReader {
    private final byte eol[] = { 13, 10 };
    private final byte eol[] = { 13, 10 };
    private InputStream in;
    private InputStream in;
    private byte sep[] = null;
    private byte sep[] = null;
    private boolean eof = false;
    private boolean eof = false;
    public String name = "";
    public String name = "";
    public String fileName = "";
    public String fileName = "";
 
 
// ******* readTo **************************************************************
// ******* readTo **************************************************************
    private boolean readTo ( OutputStream out, byte s[] ) {
    private boolean readTo ( OutputStream out, byte s[] ) {
        byte buf[] = new byte[s.length];
        byte buf[] = new byte[s.length];
        int eq = 0;
        int eq = 0;
        while ( eq<s.length && !eof ) {
        while ( eq<s.length && !eof ) {
            int i = 0;
            int i = 0;
            try {
            try {
                i = in.read();
                i = in.read();
                eof = i<0;
                eof = i<0;
            }
            }
            catch ( IOException e ) {
            catch ( IOException e ) {
                eof = true;
                eof = true;
            }
            }
            if ( !eof ) {
            if ( !eof ) {
                buf[eq] = (byte) i;
                buf[eq] = (byte) i;
                if ( buf[eq] == s[eq] ) {
                if ( buf[eq] == s[eq] ) {
                    eq++;
                    eq++;
                }
                }
                else {
                else {
                    try {
                    try {
                        if ( out != null ) out.write(buf,0,eq+1);
                        if ( out != null ) out.write(buf,0,eq+1);
                    }
                    }
                    catch ( IOException e ) {
                    catch ( IOException e ) {
                    }
                    }
                    eq=0;
                    eq=0;
                }
                }
            }
            }
        }
        }
        return !eof;
        return !eof;
    }
    }
 
 
// ******* MultiPartFormDataReader *********************************************
// ******* MultiPartFormDataReader *********************************************
    MultipartFormDataReader ( InputStream in_ ) {
    MultipartFormDataReader ( InputStream in_ ) {
        in = in_;
        in = in_;
        do {
        do {
            try {
            try {
                if ( in.read() == 45 && in.read() == 45 ) {
                if ( in.read() == 45 && in.read() == 45 ) {
                    ByteArrayOutputStream buf = new ByteArrayOutputStream();
                    ByteArrayOutputStream buf = new ByteArrayOutputStream();
                    buf.write(eol,0,eol.length);
                    buf.write(eol,0,eol.length);
                    buf.write(45);
                    buf.write(45);
                    buf.write(45);
                    buf.write(45);
                    readTo( buf, eol );
                    readTo( buf, eol );
                    sep = buf.toByteArray();
                    sep = buf.toByteArray();
//                  System.out.println("sep: -->" + new String(sep) + "<--");
//                  System.out.println("sep: -->" + new String(sep) + "<--");
                }
                }
                else {
                else {
                    readTo( null, eol );
                    readTo( null, eol );
                }
                }
            }
            }
            catch ( IOException e ) {
            catch ( IOException e ) {
                eof = true;
                eof = true;
            }
            }
        } while ( sep == null && !eof );
        } while ( sep == null && !eof );
    }
    }
 
 
// ******* readField ***********************************************************
// ******* readField ***********************************************************
    public boolean readField ( OutputStream data ) {
    public boolean readField ( OutputStream data ) {
        if ( sep == null ) return false;
        if ( sep == null ) return false;
        ByteArrayOutputStream lineBuf = new ByteArrayOutputStream();
        ByteArrayOutputStream lineBuf = new ByteArrayOutputStream();
        String line;
        String line;
        name = "";
        name = "";
        fileName = "";
        fileName = "";
        do {
        do {
            readTo ( lineBuf, eol );
            readTo ( lineBuf, eol );
            line = lineBuf.toString();
            line = lineBuf.toString();
//          System.out.println("line: "+line);
//          System.out.println("line: "+line);
            int i=0;
            int i=0;
            while ( i<line.length() && line.codePointAt(i) <= 32 ) i++;
            while ( i<line.length() && line.codePointAt(i) <= 32 ) i++;
            if ( line.length()>=i+19 && line.substring(i,i+19).equalsIgnoreCase("Content-Disposition") ) {
            if ( line.length()>=i+19 && line.substring(i,i+19).equalsIgnoreCase("Content-Disposition") ) {
                String tokens[] = line.split(";");
                String tokens[] = line.split(";");
                for ( int j=1; j<tokens.length; j++ ) {
                for ( int j=1; j<tokens.length; j++ ) {
                    String t = tokens[j];
                    String t = tokens[j];
                    i=0;
                    i=0;
                    while ( t.codePointAt(i) <= 32 && i < t.length() ) i++;
                    while ( t.codePointAt(i) <= 32 && i < t.length() ) i++;
                    String s=t.substring(i,i+5);
                    String s=t.substring(i,i+5);
                    if ( s.equalsIgnoreCase("name ") || s.equalsIgnoreCase("name=") ) {
                    if ( s.equalsIgnoreCase("name ") || s.equalsIgnoreCase("name=") ) {
                        int a = t.indexOf("\"");
                        int a = t.indexOf("\"");
                        int z = t.lastIndexOf("\"");
                        int z = t.lastIndexOf("\"");
                        if ( a>0 && z>a ) name=t.substring(a+1,z);
                        if ( a>0 && z>a ) name=t.substring(a+1,z);
                    }
                    }
                    s=t.substring(i,i+9);
                    s=t.substring(i,i+9);
                    if ( s.equalsIgnoreCase("filename ") || s.equalsIgnoreCase("filename=") ) {
                    if ( s.equalsIgnoreCase("filename ") || s.equalsIgnoreCase("filename=") ) {
                        int a = t.indexOf("\"");
                        int a = t.indexOf("\"");
                        int z = t.lastIndexOf("\"");
                        int z = t.lastIndexOf("\"");
                        if ( a>0 && z>a ) fileName=t.substring(a+1,z);
                        if ( a>0 && z>a ) fileName=t.substring(a+1,z);
                    }
                    }
                }
                }
//              System.out.println("name: "+name);
//              System.out.println("name: "+name);
//              System.out.println("filename: "+fileName);
//              System.out.println("filename: "+fileName);
            }
            }
            lineBuf.reset();
            lineBuf.reset();
        } while ( line.length()>0 && !eof );
        } while ( line.length()>0 && !eof );
        if ( ! eof ) readTo( data, sep );
        if ( ! eof ) readTo( data, sep );
        boolean result = !eof;
        boolean result = !eof;
        try {
        try {
            in.read();
            in.read();
            in.read();
            in.read();
        }
        }
        catch ( IOException e ) {
        catch ( IOException e ) {
            eof = true;
            eof = true;
        }
        }
        return result;
        return result;
    }
    }
}
}
 
 
 
 
// *****************************************************************************
// *****************************************************************************
// ******* ZtexHttpHandler *****************************************************
// ******* ZtexHttpHandler *****************************************************
// *****************************************************************************
// *****************************************************************************
class ZtexHttpHandler implements HttpHandler {
class ZtexHttpHandler implements HttpHandler {
 
 
// ******* htmlHeader **********************************************************
// ******* htmlHeader **********************************************************
    private StringBuilder htmlHeader ( String title )  {
    private StringBuilder htmlHeader ( String title )  {
        StringBuilder sb = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
        sb.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n");
        sb.append("<html>\n");
        sb.append("<html>\n");
        sb.append("<head>\n");
        sb.append("<head>\n");
        sb.append("  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
        sb.append("  <meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n");
        sb.append("  <meta http-equiv=\"Content-Language\" content=\"en\">\n");
        sb.append("  <meta http-equiv=\"Content-Language\" content=\"en\">\n");
        sb.append("  <meta name=\"author\" content=\"ZTEX GmbH\">\n");
        sb.append("  <meta name=\"author\" content=\"ZTEX GmbH\">\n");
        sb.append("<title>" + title + "</title>\n");
        sb.append("<title>" + title + "</title>\n");
        sb.append("<style type=\"text/css\">\n");
        sb.append("<style type=\"text/css\">\n");
        sb.append("body { background-color:#f0f0f0; color:#202020; font-family:Helvetica,Helv,sans-serif; font-size:11pt}\n");
        sb.append("body { background-color:#f0f0f0; color:#202020; font-family:Helvetica,Helv,sans-serif; font-size:11pt}\n");
        sb.append("a:link { color:#2020a0; }\n");
        sb.append("a:link { color:#2020a0; }\n");
        sb.append("a:visited { color:#a02020; }\n");
        sb.append("a:visited { color:#a02020; }\n");
        sb.append("a:active { color:#208020; }\n");
        sb.append("a:active { color:#208020; }\n");
        sb.append("a.topmenu { color:#ffffff; font-size:12pt; text-decoration:none; font-weight:bold }\n");
        sb.append("a.topmenu { color:#ffffff; font-size:12pt; text-decoration:none; font-weight:bold }\n");
        sb.append("a.topmenu:link { color:#ffffff; }\n");
        sb.append("a.topmenu:link { color:#ffffff; }\n");
        sb.append("a.topmenu:visited { color:#ffffff; }\n");
        sb.append("a.topmenu:visited { color:#ffffff; }\n");
        sb.append("a.topmenu:hover { color:#202020; }\n");
        sb.append("a.topmenu:hover { color:#202020; }\n");
        sb.append("</style>\n");
        sb.append("</style>\n");
        sb.append("</head>\n");
        sb.append("</head>\n");
        sb.append("<body>\n");
        sb.append("<body>\n");
        sb.append("<center><table border=0 bgcolor=\"#7870a0\" cellpadding=2 cellspacing=0><tr><td>\n");
        sb.append("<center><table border=0 bgcolor=\"#7870a0\" cellpadding=2 cellspacing=0><tr><td>\n");
        sb.append("<table border=0 bgcolor=\"#eae6ff\" cellpadding=5 cellspacing=10>\n");
        sb.append("<table border=0 bgcolor=\"#eae6ff\" cellpadding=5 cellspacing=10>\n");
        sb.append("  <tr><th bgcolor=\"#cac4ec\">\n");
        sb.append("  <tr><th bgcolor=\"#cac4ec\">\n");
        sb.append("    <span style=\"font-size:125%\">" + title + "</span>\n");
        sb.append("    <span style=\"font-size:125%\">" + title + "</span>\n");
        sb.append("  </th></tr>\n");
        sb.append("  </th></tr>\n");
        sb.append("  <tr><td align=center>\n");
        sb.append("  <tr><td align=center>\n");
        return sb;
        return sb;
    }
    }
 
 
// ******* heading *************************************************************
// ******* heading *************************************************************
    private StringBuilder heading ( StringBuilder sb, String s )  {
    private StringBuilder heading ( StringBuilder sb, String s )  {
        sb.append ( "</td></tr>\n");
        sb.append ( "</td></tr>\n");
        sb.append("  <tr><th bgcolor=\"#cac4ec\">\n");
        sb.append("  <tr><th bgcolor=\"#cac4ec\">\n");
        sb.append("    <span style=\"font-size:125%\">" + s + "</span>\n");
        sb.append("    <span style=\"font-size:125%\">" + s + "</span>\n");
        sb.append("  </th></tr>\n");
        sb.append("  </th></tr>\n");
        sb.append("  <tr><td align=center>\n");
        sb.append("  <tr><td align=center>\n");
        return sb;
        return sb;
    }
    }
 
 
// ******* htmlConvert *********************************************************
// ******* htmlConvert *********************************************************
    private byte[] htmlConvert ( StringBuilder sb )  {
    private byte[] htmlConvert ( StringBuilder sb )  {
        sb.append ( "</td></tr>\n");
        sb.append ( "</td></tr>\n");
        sb.append ( "</table>\n");
        sb.append ( "</table>\n");
        sb.append ( "</td></tr></table><center>\n");
        sb.append ( "</td></tr></table><center>\n");
        sb.append ( "<p>\n");
        sb.append ( "<p>\n");
        sb.append ( "<hr>\n");
        sb.append ( "<hr>\n");
        sb.append ( "<center>\n");
        sb.append ( "<center>\n");
        sb.append ( "  <a href=\"http://www.ztex.de/\">[ZTEX Homepage]</a>&nbsp;\n");
        sb.append ( "  <a href=\"http://www.ztex.de/\">[ZTEX Homepage]</a>&nbsp;\n");
        sb.append ( "  <a href=\"http://wiki.ztex.de/\">[ZTEX Wiki]</a>&nbsp;\n");
        sb.append ( "  <a href=\"http://wiki.ztex.de/\">[ZTEX Wiki]</a>&nbsp;\n");
        sb.append ( "  <span style=\"font-size:80%\">&#169; ZTEX GmbH</span>\n");
        sb.append ( "  <span style=\"font-size:80%\">&#169; ZTEX GmbH</span>\n");
        sb.append ( "</center>\n");
        sb.append ( "</center>\n");
        sb.append ( "</body></html>" );
        sb.append ( "</body></html>" );
        return sb.toString().getBytes();
        return sb.toString().getBytes();
    }
    }
 
 
// ******* test ****************************************************************
// ******* test ****************************************************************
    private byte[] test (HttpExchange t) throws IOException {
    private byte[] test (HttpExchange t) throws IOException {
        InputStream in = new BufferedInputStream( t.getRequestBody() );
        InputStream in = new BufferedInputStream( t.getRequestBody() );
        System.out.println("Request Body: " + in.available() + "Bytes");
        System.out.println("Request Body: " + in.available() + "Bytes");
        int i;
        int i;
        do {
        do {
            i = in.read();
            i = in.read();
            if ( i>=0 ) System.out.print((char)i);
            if ( i>=0 ) System.out.print((char)i);
        } while (i>=0);
        } while (i>=0);
 
 
        Headers h = t.getResponseHeaders();
        Headers h = t.getResponseHeaders();
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        StringBuilder sb = htmlHeader ("Test");
        StringBuilder sb = htmlHeader ("Test");
        sb.append ("<form action=\"test\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("<form action=\"test\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("  <p>W&auml;hlen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:<br>\n");
        sb.append ("  <p>W&auml;hlen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:<br>\n");
        sb.append ("    <input name=\"Datei\" type=\"file\" size=\"50\" maxlength=\"100000\" >\n");
        sb.append ("    <input name=\"Datei\" type=\"file\" size=\"50\" maxlength=\"100000\" >\n");
        sb.append ("  </p>\n");
        sb.append ("  </p>\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("</form>\n");
        sb.append ("</form>\n");
 
 
        return htmlConvert(sb);
        return htmlConvert(sb);
    }
    }
 
 
// ******* test2 ***************************************************************
// ******* test2 ***************************************************************
    private byte[] test2 (HttpExchange t) throws IOException {
    private byte[] test2 (HttpExchange t) throws IOException {
        MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) );
        MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) );
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        while ( form.readField( data ) ) {
        while ( form.readField( data ) ) {
            System.out.println( "Name=\"" + form.name + "\"" );
            System.out.println( "Name=\"" + form.name + "\"" );
            System.out.println( "Filename=\"" + form.fileName + "\"" );
            System.out.println( "Filename=\"" + form.fileName + "\"" );
            System.out.println( "Data -->" + data + "<--" );
            System.out.println( "Data -->" + data + "<--" );
            data.reset();
            data.reset();
        }
        }
 
 
        Headers h = t.getResponseHeaders();
        Headers h = t.getResponseHeaders();
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        StringBuilder sb = htmlHeader ("Test2");
        StringBuilder sb = htmlHeader ("Test2");
        sb.append ("<form action=\"test2\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("<form action=\"test2\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("  <p>W&auml;hlen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:<br>\n");
        sb.append ("  <p>W&auml;hlen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:<br>\n");
        sb.append ("    <input name=\"Datei\" type=\"file\" size=\"50\" maxlength=\"100000\" >\n");
        sb.append ("    <input name=\"Datei\" type=\"file\" size=\"50\" maxlength=\"100000\" >\n");
        sb.append ("  </p>\n");
        sb.append ("  </p>\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"v\">Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"nv\">Non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"checkbox\" name=\"upload_to\" value=\"nv\">Non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("</form>\n");
        sb.append ("</form>\n");
 
 
        return htmlConvert(sb);
        return htmlConvert(sb);
    }
    }
 
 
// ******* scan ****************************************************************
// ******* scan ****************************************************************
    private byte[] scan (HttpExchange t) {
    private byte[] scan (HttpExchange t) {
        DeviceServer.scanUSB();
        DeviceServer.scanUSB();
        int n = DeviceServer.numberOfDevices();
        int n = DeviceServer.numberOfDevices();
        Headers h = t.getResponseHeaders();
        Headers h = t.getResponseHeaders();
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        StringBuilder sb = htmlHeader ("Device overview");
        StringBuilder sb = htmlHeader ("Device overview");
        sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=4>\n");
        sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=4>\n");
        sb.append ("  <tr>\n");
        sb.append ("  <tr>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Device Link / <br> &lt;Bus Index&gt;:&lt;Device Number&gt;</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Device Link / <br> &lt;Bus Index&gt;:&lt;Device Number&gt;</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Bus Name</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Bus Name</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Product ID's</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Product ID's</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Serial Number String</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Serial Number String</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Manufacturer String</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Manufacturer String</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Product String</td>\n");
        sb.append ("    <td align=center bgcolor=\"#e0e0e0\">Product String</td>\n");
        sb.append ("  </tr>\n");
        sb.append ("  </tr>\n");
        if ( n<1 ) {
        if ( n<1 ) {
            sb.append("<tr><td align=center bgcolor=\"#f0f0f0\" colspan=6>(No devices)</td>");
            sb.append("<tr><td align=center bgcolor=\"#f0f0f0\" colspan=6>(No devices)</td>");
        } else {
        } else {
            for ( int i=0; i<n; i++ ) {
            for ( int i=0; i<n; i++ ) {
                try {
                try {
                    ZtexDevice1 dev = DeviceServer.device(i);
                    ZtexDevice1 dev = DeviceServer.device(i);
                    sb.append("    <tr>\n");
                    sb.append("    <tr>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\"><a href=\"" + DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i) + "\">" + DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i) + "</a></td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\"><a href=\"" + DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i) + "\">" + DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i) + "</a></td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + dev.dev().getBus().getDirname() + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + dev.dev().getBus().getDirname() + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.snString() == null ? "" : dev.snString() ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.snString() == null ? "" : dev.snString() ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.productString() == null ? "" : dev.productString() ) + "</td>\n");
                    sb.append("    <td align=center bgcolor=\"#f0f0f0\">" + ( dev.productString() == null ? "" : dev.productString() ) + "</td>\n");
                    sb.append("  </tr>\n");
                    sb.append("  </tr>\n");
                }
                }
                catch ( IndexOutOfBoundsException e ) {
                catch ( IndexOutOfBoundsException e ) {
                }
                }
            }
            }
        }
        }
        sb.append ("</table>\n");
        sb.append ("</table>\n");
        sb.append ("<p>\n");
        sb.append ("<p>\n");
        sb.append ("<a href=\"/scan\"><button>Re-Scan</button></a>\n");
        sb.append ("<a href=\"/scan\"><button>Re-Scan</button></a>\n");
        return htmlConvert(sb);
        return htmlConvert(sb);
    }
    }
 
 
// ******* device **************************************************************
// ******* device **************************************************************
    private byte[] device ( HttpExchange t, int busIdx, int devNum, int epnum, ZtexDevice1 dev ) {
    private byte[] device ( HttpExchange t, int busIdx, int devNum, int epnum, ZtexDevice1 dev ) {
 
 
        StringBuilder messages = new StringBuilder();
        StringBuilder messages = new StringBuilder();
        EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
        EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum);
        Headers h = t.getResponseHeaders();
        Headers h = t.getResponseHeaders();
 
 
        // ***********
        // ***********
        // * request *
        // * request *
        // ***********
        // ***********
        boolean fw_force = false;
        boolean fw_force = false;
        boolean fw_upload_v = false;
        boolean fw_upload_v = false;
        boolean fw_upload_nv = false;
        boolean fw_upload_nv = false;
        boolean fw_erase = false;
        boolean fw_erase = false;
        ByteArrayInputStream fw_data = null;
        ByteArrayInputStream fw_data = null;
        String fw_data_name = null;
        String fw_data_name = null;
 
 
        boolean bs_force = false;
        boolean bs_force = false;
        boolean bs_upload_v = false;
        boolean bs_upload_v = false;
        boolean bs_upload_nv = false;
        boolean bs_upload_nv = false;
        boolean bs_erase = false;
        boolean bs_erase = false;
        byte bs_data[] = null;
        byte bs_data[] = null;
        String bs_data_name = null;
        String bs_data_name = null;
 
 
        ByteArrayInputStream ep_data = null;
        ByteArrayInputStream ep_data = null;
        String ep_data_name = null;
        String ep_data_name = null;
        int ep_data_num = -1;
        int ep_data_num = -1;
        int ep_down_size = -1;
        int ep_down_size = -1;
 
 
        MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) );
        MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) );
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        while ( form.readField( data ) ) {
        while ( form.readField( data ) ) {
/*          System.out.println( "Name=\"" + form.name + "\"" );
/*          System.out.println( "Name=\"" + form.name + "\"" );
            System.out.println( "Filename=\"" + form.fileName + "\"" );
            System.out.println( "Filename=\"" + form.fileName + "\"" );
            System.out.println( "Data -->" + data + "<--" ); */
            System.out.println( "Data -->" + data + "<--" ); */
            if ( data.size()>0 ) {
            if ( data.size()>0 ) {
                if ( form.name.equalsIgnoreCase("fw_force" ) ) fw_force=true;
                if ( form.name.equalsIgnoreCase("fw_force" ) ) fw_force=true;
                else if ( form.name.equalsIgnoreCase("fw_upload_v" ) ) fw_upload_v=true;
                else if ( form.name.equalsIgnoreCase("fw_upload_v" ) ) fw_upload_v=true;
                else if ( form.name.equalsIgnoreCase("fw_upload_nv" ) ) fw_upload_nv=true;
                else if ( form.name.equalsIgnoreCase("fw_upload_nv" ) ) fw_upload_nv=true;
                else if ( form.name.equalsIgnoreCase("fw_erase" ) ) fw_erase=true;
                else if ( form.name.equalsIgnoreCase("fw_erase" ) ) fw_erase=true;
                else if ( form.name.equalsIgnoreCase("fw_data" ) ) {
                else if ( form.name.equalsIgnoreCase("fw_data" ) ) {
                    fw_data = new ByteArrayInputStream(data.toByteArray());
                    fw_data = new ByteArrayInputStream(data.toByteArray());
                    fw_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                    fw_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                }
                }
                else if ( form.name.equalsIgnoreCase("bs_force" ) ) bs_force=true;
                else if ( form.name.equalsIgnoreCase("bs_force" ) ) bs_force=true;
                else if ( form.name.equalsIgnoreCase("bs_upload_v" ) ) bs_upload_v=true;
                else if ( form.name.equalsIgnoreCase("bs_upload_v" ) ) bs_upload_v=true;
                else if ( form.name.equalsIgnoreCase("bs_upload_nv" ) ) bs_upload_nv=true;
                else if ( form.name.equalsIgnoreCase("bs_upload_nv" ) ) bs_upload_nv=true;
                else if ( form.name.equalsIgnoreCase("bs_erase" ) ) bs_erase=true;
                else if ( form.name.equalsIgnoreCase("bs_erase" ) ) bs_erase=true;
                else if ( form.name.equalsIgnoreCase("bs_data" ) ) {
                else if ( form.name.equalsIgnoreCase("bs_data" ) ) {
                    bs_data = data.toByteArray();
                    bs_data = data.toByteArray();
                    bs_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                    bs_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                }
                }
                else if ( form.name.equalsIgnoreCase("ep_down_size" ) ) {
                else if ( form.name.equalsIgnoreCase("ep_down_size" ) ) {
                    try {
                    try {
                        ep_down_size = Integer.valueOf(data.toString());
                        ep_down_size = Integer.valueOf(data.toString());
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        ep_down_size = -1;
                        ep_down_size = -1;
                    }
                    }
//                  System.out.println(ep_down_size);
//                  System.out.println(ep_down_size);
                }
                }
                else {
                else {
                    for ( int i=0; eps!=null && i<eps.size(); i++ ) {
                    for ( int i=0; eps!=null && i<eps.size(); i++ ) {
                        EPDescriptor ep = eps.elementAt(i);
                        EPDescriptor ep = eps.elementAt(i);
                        if ( ! ep.in() && form.name.equalsIgnoreCase("ep_"+ep.num()+"_data" ) ) {
                        if ( ! ep.in() && form.name.equalsIgnoreCase("ep_"+ep.num()+"_data" ) ) {
                            ep_data = new ByteArrayInputStream(data.toByteArray());
                            ep_data = new ByteArrayInputStream(data.toByteArray());
                            ep_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                            ep_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName;
                            ep_data_num = ep.num();
                            ep_data_num = ep.num();
                        }
                        }
                    }
                    }
                }
                }
                data.reset();
                data.reset();
            }
            }
        }
        }
 
 
        // **********
        // **********
        // * action *
        // * action *
        // **********
        // **********
        Ztex1v1 ztex = null;
        Ztex1v1 ztex = null;
        try {
        try {
            ztex = new Ztex1v1(dev);
            ztex = new Ztex1v1(dev);
        } catch ( Exception e ) {
        } catch ( Exception e ) {
            ztex = null;
            ztex = null;
            messages.append( "Error: " + e.getLocalizedMessage() + "\n");
            messages.append( "Error: " + e.getLocalizedMessage() + "\n");
        }
        }
 
 
        int oldDevNum = devNum;
        int oldDevNum = devNum;
        try {
        try {
            DeviceServer.loadFirmware ( ztex, messages, fw_data, fw_data_name, fw_force, fw_upload_v, fw_upload_nv, fw_erase );
            DeviceServer.loadFirmware ( ztex, messages, fw_data, fw_data_name, fw_force, fw_upload_v, fw_upload_nv, fw_erase );
            if ( ztex != null ) {
            if ( ztex != null ) {
                devNum = ztex.dev().dev().getDevnum();
                devNum = ztex.dev().dev().getDevnum();
                if ( devNum != oldDevNum ) {
                if ( devNum != oldDevNum ) {
                    messages.append("Device re-numerated: " + busIdx + ":" + oldDevNum + " -> " + busIdx + ":" + devNum + "\n");
                    messages.append("Device re-numerated: " + busIdx + ":" + oldDevNum + " -> " + busIdx + ":" + devNum + "\n");
                    DeviceServer.scanUSB();
                    DeviceServer.scanUSB();
                    eps = DeviceServer.getEps(busIdx,devNum);
                    eps = DeviceServer.getEps(busIdx,devNum);
                }
                }
            }
            }
        } catch ( Exception e ) {
        } catch ( Exception e ) {
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
        }
        }
 
 
        try {
        try {
            if ( ztex != null ) DeviceServer.loadBitstream ( ztex, messages, bs_data, bs_data_name, bs_force, bs_upload_v, bs_upload_nv, bs_erase );
            if ( ztex != null ) DeviceServer.loadBitstream ( ztex, messages, bs_data, bs_data_name, bs_force, bs_upload_v, bs_upload_nv, bs_erase );
        } catch ( Exception e ) {
        } catch ( Exception e ) {
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
        }
        }
 
 
        try {
        try {
            if ( ep_data != null ) DeviceServer.epUpload (ztex, eps.find(ep_data_num), ep_data, messages);
            if ( ep_data != null ) DeviceServer.epUpload (ztex, eps.find(ep_data_num), ep_data, messages);
        } catch ( Exception e ) {
        } catch ( Exception e ) {
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
        }
        }
 
 
        try {
        try {
            if ( epnum>0 ){
            if ( epnum>0 ){
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                DeviceServer.epDownload (ztex, eps.find(epnum), out, ep_down_size, messages);
                DeviceServer.epDownload (ztex, eps.find(epnum), out, ep_down_size, messages);
                h.add("Content-Type", "application/octet-stream");
                h.add("Content-Type", "application/octet-stream");
                return out.toByteArray();
                return out.toByteArray();
            }
            }
        } catch ( Exception e ) {
        } catch ( Exception e ) {
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
            messages.append( "Error: " + e.getLocalizedMessage() + '\n' );
        }
        }
 
 
        DeviceServer.release (ztex);
        DeviceServer.release (ztex);
 
 
        // ************
        // ************
        // * response *
        // * response *
        // ************
        // ************
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        h.add("Content-Type", "text/html;Charset=iso-8859-1");
        StringBuilder sb = htmlHeader ("Device " + busIdx + ":" + devNum + ( devNum!=oldDevNum ? ( " (was " + busIdx + ":" + oldDevNum +")" ) : "" ) );
        StringBuilder sb = htmlHeader ("Device " + busIdx + ":" + devNum + ( devNum!=oldDevNum ? ( " (was " + busIdx + ":" + oldDevNum +")" ) : "" ) );
 
 
        // info 
        // info 
        sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=4>\n");
        sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=4>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Bus name: </td><td align=left bgcolor=\"#f0f0f0\">" + dev.dev().getBus().getDirname() + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Bus name: </td><td align=left bgcolor=\"#f0f0f0\">" + dev.dev().getBus().getDirname() + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Device Number: </td><td align=left bgcolor=\"#f0f0f0\">" + devNum + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Device Number: </td><td align=left bgcolor=\"#f0f0f0\">" + devNum + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> USB ID's: </td><td align=left bgcolor=\"#f0f0f0\">" + Integer.toHexString(dev.usbVendorId()) + ":" + Integer.toHexString(dev.usbProductId()) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> USB ID's: </td><td align=left bgcolor=\"#f0f0f0\">" + Integer.toHexString(dev.usbVendorId()) + ":" + Integer.toHexString(dev.usbProductId()) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Product ID's: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Product ID's: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Firmware version: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.valid() ? (dev.fwVersion() & 255) : "" ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Firmware version: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.valid() ? (dev.fwVersion() & 255) : "" ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Serial Number String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.snString() == null ? "" : dev.snString() ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Serial Number String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.snString() == null ? "" : dev.snString() ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Manufacturer String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Manufacturer String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Product String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.productString() == null ? "" : dev.productString() ) + "</td></tr>\n");
        sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Product String: </td><td align=left bgcolor=\"#f0f0f0\">" + ( dev.productString() == null ? "" : dev.productString() ) + "</td></tr>\n");
        if ( ztex != null ) {
        if ( ztex != null ) {
            String s = ztex.capabilityInfo(", ");
            String s = ztex.capabilityInfo(", ");
            if ( s.length()>0 ) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Capabilities: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
            if ( s.length()>0 ) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Capabilities: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
            if ( ztex.config != null ) {
            if ( ztex.config != null ) {
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> ZTEX Product: </td><td align=left bgcolor=\"#f0f0f0\">" + ztex.config.getName() + "</td></tr>\n");
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> ZTEX Product: </td><td align=left bgcolor=\"#f0f0f0\">" + ztex.config.getName() + "</td></tr>\n");
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> FPGA: </td><td align=left bgcolor=\"#f0f0f0\">" + ztex.config.getFpga() + "</td></tr>\n");
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> FPGA: </td><td align=left bgcolor=\"#f0f0f0\">" + ztex.config.getFpga() + "</td></tr>\n");
                if (ztex.config.getRamSize()>0) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> RAM: </td><td align=left bgcolor=\"#f0f0f0\">" + (ztex.config.getRamSize() >> 20) + " MByte " + ztex.config.getRamType() + "</td></tr>\n");
                if (ztex.config.getRamSize()>0) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> RAM: </td><td align=left bgcolor=\"#f0f0f0\">" + (ztex.config.getRamSize() >> 20) + " MByte " + ztex.config.getRamType() + "</td></tr>\n");
                s = ztex.flashInfo(); if ( s.length()>0 ) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Flash: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
                s = ztex.flashInfo(); if ( s.length()>0 ) sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> Flash: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
            }
            }
            try {
            try {
                s = ztex.getFpgaConfigurationStr();
                s = ztex.getFpgaConfigurationStr();
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> FPGA State: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
                sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> FPGA State: </td><td align=left bgcolor=\"#f0f0f0\">" + s + "</td></tr>\n");
            } catch ( Exception e ) {
            } catch ( Exception e ) {
            }
            }
        }
        }
        sb.append ("</table>\n");
        sb.append ("</table>\n");
        sb.append ("<p><a href=\"/\"><button>Device Overview</button></a>\n");
        sb.append ("<p><a href=\"/\"><button>Device Overview</button></a>\n");
 
 
        // firmware
        // firmware
        heading(sb,"Firmware Upload");
        heading(sb,"Firmware Upload");
        sb.append ("<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">\n");
        sb.append ("  <div align=left>\n");
        sb.append ("  <div align=left>\n");
        sb.append ("    Firmware file: <input name=\"fw_data\" type=\"file\" size=\"70\" accept=\".ihx\" maxlength=\"5000000\"><p>\n");
        sb.append ("    Firmware file: <input name=\"fw_data\" type=\"file\" size=\"70\" accept=\".ihx\" maxlength=\"5000000\"><p>\n");
        sb.append ("    <input type=\"checkbox\" name=\"fw_upload_v\" value=\"x\" " + ( fw_upload_v ? "checked" : "" ) + ">Upload to volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
        sb.append ("    <input type=\"checkbox\" name=\"fw_upload_v\" value=\"x\" " + ( fw_upload_v ? "checked" : "" ) + ">Upload to volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
//        try {
//        try {
//          if ( ztex != null ) {
//          if ( ztex != null ) {
//              ztex.checkCapability(ztex.CAPABILITY_EEPROM);
//              ztex.checkCapability(ztex.CAPABILITY_EEPROM);
                sb.append ("    <input type=\"checkbox\" name=\"fw_upload_nv\" value=\"x\"" + ( fw_upload_nv ? "checked" : "" ) + ">Upload to non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
                sb.append ("    <input type=\"checkbox\" name=\"fw_upload_nv\" value=\"x\"" + ( fw_upload_nv ? "checked" : "" ) + ">Upload to non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
                sb.append ("    <input type=\"checkbox\" name=\"fw_erase\" value=\"x\"" + ( fw_erase ? "checked" : "" ) + ">Erase firmware in non-volatile memory");
                sb.append ("    <input type=\"checkbox\" name=\"fw_erase\" value=\"x\"" + ( fw_erase ? "checked" : "" ) + ">Erase firmware in non-volatile memory");
//          }
//          }
//      }
//      }
//      catch ( Exception a ) {
//      catch ( Exception a ) {
//      }
//      }
        sb.append ("    <input type=\"checkbox\" name=\"fw_force\" value=\"x\"" + ( fw_force ? "checked" : "" ) + ">Enforce upload<p>");
        sb.append ("    <input type=\"checkbox\" name=\"fw_force\" value=\"x\"" + ( fw_force ? "checked" : "" ) + ">Enforce upload<p>");
        sb.append ("    (Before firmware can be loaded into non-volatile memory some firmware must be installed in volatile memory.)<p>\n");
        sb.append ("    (Before firmware can be loaded into non-volatile memory some firmware must be installed in volatile memory.)<p>\n");
        sb.append ("  </div>\n");
        sb.append ("  </div>\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
        sb.append ("</form>\n");
        sb.append ("</form>\n");
 
 
        // bitstream
        // bitstream
        try {
        try {
            if ( ztex == null ) throw new Exception();
            if ( ztex == null ) throw new Exception();
            ztex.checkCapability(ztex.CAPABILITY_FPGA);
            ztex.checkCapability(ztex.CAPABILITY_FPGA);
            heading(sb,"Bitstream Upload");
            heading(sb,"Bitstream Upload");
            sb.append ("<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">\n");
            sb.append ("<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">\n");
            sb.append ("  <div align=left>\n");
            sb.append ("  <div align=left>\n");
            sb.append ("    Bitstream file: <input name=\"bs_data\" type=\"file\" size=\"70\" accept=\".ihx\" maxlength=\"5000000\"><p>\n");
            sb.append ("    Bitstream file: <input name=\"bs_data\" type=\"file\" size=\"70\" accept=\".ihx\" maxlength=\"5000000\"><p>\n");
            sb.append ("        <input type=\"checkbox\" name=\"bs_upload_v\" value=\"x\" " + ( bs_upload_v ? "checked" : "" ) + ">Upload to volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
            sb.append ("        <input type=\"checkbox\" name=\"bs_upload_v\" value=\"x\" " + ( bs_upload_v ? "checked" : "" ) + ">Upload to volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
            try {
            try {
                if ( ztex != null && ztex.flashEnabled() ) {
                if ( ztex != null && ztex.flashEnabled() ) {
                    sb.append ("    <input type=\"checkbox\" name=\"bs_upload_nv\" value=\"x\"" + ( bs_upload_nv ? "checked" : "" ) + ">Upload to non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
                    sb.append ("    <input type=\"checkbox\" name=\"bs_upload_nv\" value=\"x\"" + ( bs_upload_nv ? "checked" : "" ) + ">Upload to non-Volatile Memory &nbsp;&nbsp;&nbsp;&nbsp;\n");
                    sb.append ("    <input type=\"checkbox\" name=\"bs_erase\" value=\"x\"" + ( bs_erase ? "checked" : "" ) + ">Erase bitstream in non-volatile memory");
                    sb.append ("    <input type=\"checkbox\" name=\"bs_erase\" value=\"x\"" + ( bs_erase ? "checked" : "" ) + ">Erase bitstream in non-volatile memory");
                }
                }
            }
            }
            catch ( Exception a ) {
            catch ( Exception a ) {
            }
            }
            sb.append ("    <input type=\"checkbox\" name=\"bs_force\" value=\"x\"" + ( bs_force ? "checked" : "" ) + ">Enforce upload<p>");
            sb.append ("    <input type=\"checkbox\" name=\"bs_force\" value=\"x\"" + ( bs_force ? "checked" : "" ) + ">Enforce upload<p>");
            sb.append ("  </div>\n");
            sb.append ("  </div>\n");
            sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
            sb.append ("  <input type=\"submit\" value=\"Submit\">\n");
            sb.append ("</form>\n");
            sb.append ("</form>\n");
        }
        }
        catch ( Exception a ) {
        catch ( Exception a ) {
        }
        }
 
 
        // endpoints
        // endpoints
        if ( eps!=null && eps.size()>0) {
        if ( eps!=null && eps.size()>0) {
            heading(sb,"Endpoints");
            heading(sb,"Endpoints");
            sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=12>\n");
            sb.append ("<table border=\"0\" bgcolor=\"#808080\" cellspacing=1 cellpadding=12>\n");
            for (int i=0; i<eps.size(); i++ ) {
            for (int i=0; i<eps.size(); i++ ) {
                EPDescriptor ep = eps.elementAt(i);
                EPDescriptor ep = eps.elementAt(i);
                if ( ep.in() ) {
                if ( ep.in() ) {
                    sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> IN EP " + ep.num() +":</td>  <td align=left bgcolor=\"#f0f0f0\">"
                    sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> IN EP " + ep.num() +":</td>  <td align=left bgcolor=\"#f0f0f0\">"
                        + "<form action=\"" + busIdx + ":" + devNum + ":" + ep.num() + "\" method=\"post\" enctype=\"multipart/form-data\">"
                        + "<form action=\"" + busIdx + ":" + devNum + ":" + ep.num() + "\" method=\"post\" enctype=\"multipart/form-data\">"
                        + "Maximum size: <input type=\"text\" name=\"ep_down_size\" value=\"1000000\" size=12 maxlength=11>"
                        + "Maximum size: <input type=\"text\" name=\"ep_down_size\" value=\"1000000\" size=12 maxlength=11>"
                        + "&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" value=\"Download\">"
                        + "&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" value=\"Download\">"
                        + "</form></td></tr>\n" );
                        + "</form></td></tr>\n" );
                } else {
                } else {
                    sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> OUT EP " + ep.num() +":</td>  <td align=left bgcolor=\"#f0f0f0\">"
                    sb.append("  <tr><td align=left bgcolor=\"#e0e0e0\"> OUT EP " + ep.num() +":</td>  <td align=left bgcolor=\"#f0f0f0\">"
                        + "<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">"
                        + "<form action=\"" + busIdx + ":" + devNum + "\" method=\"post\" enctype=\"multipart/form-data\">"
                        + "File: <input name=\"ep_"+ep.num()+"_data\" type=\"file\" size=\"60\" accept=\"\" maxlength=\"50000000\">"
                        + "File: <input name=\"ep_"+ep.num()+"_data\" type=\"file\" size=\"60\" accept=\"\" maxlength=\"50000000\">"
                        + "&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" value=\"Upload\">"
                        + "&nbsp;&nbsp;&nbsp;&nbsp;<input type=\"submit\" value=\"Upload\">"
                        + "</form></td></tr>\n" );
                        + "</form></td></tr>\n" );
                }
                }
            }
            }
            sb.append ("</table>\n");
            sb.append ("</table>\n");
        }
        }
 
 
        // messages
        // messages
        if ( messages.length() > 0 ) {
        if ( messages.length() > 0 ) {
            heading(sb,"Messages");
            heading(sb,"Messages");
            sb.append ("<div align=left><pre>\n");
            sb.append ("<div align=left><pre>\n");
            sb.append(messages);
            sb.append(messages);
            sb.append ("</pre></div>");
            sb.append ("</pre></div>");
        }
        }
 
 
        return htmlConvert(sb);
        return htmlConvert(sb);
    }
    }
 
 
// ******* handle **************************************************************
// ******* handle **************************************************************
    public void handle(HttpExchange t) throws IOException {
    public void handle(HttpExchange t) throws IOException {
        String path = t.getRequestURI().getPath();
        String path = t.getRequestURI().getPath();
        int responseCode = 200;
        int responseCode = 200;
        byte buf[] = {};
        byte buf[] = {};
        if ( path.charAt(0) != '/' ) path = '/' + path;
        if ( path.charAt(0) != '/' ) path = '/' + path;
        int rcvd = t.getRequestBody().available();
        int rcvd = t.getRequestBody().available();
 
 
        if ( ! DeviceServer.httpPermissions().checkAddress( t.getRemoteAddress().getAddress() ) ) {
        if ( ! DeviceServer.httpPermissions().checkAddress( t.getRemoteAddress().getAddress() ) ) {
            responseCode = 400;
            responseCode = 400;
            StringBuilder sb = htmlHeader ("400 Bad Request");
            StringBuilder sb = htmlHeader ("400 Bad Request");
            sb.append("Access denied" );
            sb.append("Access denied" );
            buf = htmlConvert(sb);
            buf = htmlConvert(sb);
        }
        }
/*      else if ( path.equalsIgnoreCase("/test") ) {
/*      else if ( path.equalsIgnoreCase("/test") ) {
            buf = test(t);
            buf = test(t);
        }
        }
        else if ( path.equalsIgnoreCase("/test2") ) {
        else if ( path.equalsIgnoreCase("/test2") ) {
            buf = test2(t);
            buf = test2(t);
        } */
        } */
        else if ( path.equalsIgnoreCase("/") || path.equalsIgnoreCase("/scan") ) {
        else if ( path.equalsIgnoreCase("/") || path.equalsIgnoreCase("/scan") ) {
            buf = scan(t);
            buf = scan(t);
        }
        }
        else if ( path.indexOf(':') > 0 ) {
        else if ( path.indexOf(':') > 0 ) {
            try {
            try {
                int i = path.indexOf(':');
                int i = path.indexOf(':');
                int j = path.lastIndexOf(':');
                int j = path.lastIndexOf(':');
                if (j<=i) j=path.length();
                if (j<=i) j=path.length();
                int busIdx = Integer.valueOf(path.substring(1,i));
                int busIdx = Integer.valueOf(path.substring(1,i));
                int devNum = Integer.valueOf(path.substring(i+1,j ));
                int devNum = Integer.valueOf(path.substring(i+1,j ));
                int epNum = j < path.length() ? Integer.valueOf(path.substring(j+1)) : -1;
                int epNum = j < path.length() ? Integer.valueOf(path.substring(j+1)) : -1;
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx,devNum);
                ZtexDevice1 dev = DeviceServer.findDevice(busIdx,devNum);
                if ( dev == null ) throw new Exception();
                if ( dev == null ) throw new Exception();
                buf = device(t, busIdx, devNum, epNum, dev);
                buf = device(t, busIdx, devNum, epNum, dev);
            }
            }
            catch ( Exception e ) {
            catch ( Exception e ) {
                responseCode = 400;
                responseCode = 400;
                StringBuilder sb = htmlHeader ("400 Bad Request");
                StringBuilder sb = htmlHeader ("400 Bad Request");
                sb.append("Invalid device path: " + path );
                sb.append("Invalid device path: " + path );
                sb.append ("<p>\n");
                sb.append ("<p>\n");
                sb.append ("<a href=\"/\"><button>Device Overview</button></a>\n");
                sb.append ("<a href=\"/\"><button>Device Overview</button></a>\n");
                buf = htmlConvert(sb);
                buf = htmlConvert(sb);
            }
            }
        }
        }
        else {
        else {
            responseCode = 404;
            responseCode = 404;
            StringBuilder sb = htmlHeader ("404 Not Found");
            StringBuilder sb = htmlHeader ("404 Not Found");
            sb.append("Invalid path: " + path );
            sb.append("Invalid path: " + path );
            sb.append ("<p>\n");
            sb.append ("<p>\n");
            sb.append ("<a href=\"/\"><button>Device Overview</button></a>\n");
            sb.append ("<a href=\"/\"><button>Device Overview</button></a>\n");
            buf = htmlConvert(sb);
            buf = htmlConvert(sb);
        }
        }
        DeviceServer.info( "Connection from " + IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ": " + path + ": " + responseCode + ": received " + rcvd + " bytes,  sent " + buf.length + " bytes" );
        DeviceServer.info( "Connection from " + IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ": " + path + ": " + responseCode + ": received " + rcvd + " bytes,  sent " + buf.length + " bytes" );
        t.sendResponseHeaders(responseCode, buf.length);
        t.sendResponseHeaders(responseCode, buf.length);
        OutputStream os = t.getResponseBody();
        OutputStream os = t.getResponseBody();
        os.write(buf);
        os.write(buf);
        os.close();
        os.close();
    }
    }
}
}
 
 
 
 
// *****************************************************************************
// *****************************************************************************
// ******* IPPermissionList ****************************************************
// ******* IPPermissionList ****************************************************
// *****************************************************************************
// *****************************************************************************
class IPPermissions {
class IPPermissions {
    private byte ip[][] = { { 127, 0, 0, 1 } };
    private byte ip[][] = { { 127, 0, 0, 1 } };
    private boolean deny[] = { false };
    private boolean deny[] = { false };
    private int mask[] = { 32 };
    private int mask[] = { 32 };
 
 
    public IPPermissions(String adrs) throws UnknownHostException,IllegalArgumentException {
    public IPPermissions(String adrs) throws UnknownHostException,IllegalArgumentException {
        String strs[] = adrs.split(",");
        String strs[] = adrs.split(",");
        ip = new byte[strs.length][];
        ip = new byte[strs.length][];
        deny = new boolean[strs.length];
        deny = new boolean[strs.length];
        mask = new int[strs.length];
        mask = new int[strs.length];
        for (int i=0; i<strs.length; i++ ) {
        for (int i=0; i<strs.length; i++ ) {
            if ( strs[i].length()==0 ) throw new IllegalArgumentException( "Invalid address format at position " + (i+1) + ": empty string");
            if ( strs[i].length()==0 ) throw new IllegalArgumentException( "Invalid address format at position " + (i+1) + ": empty string");
            deny[i] = strs[i].charAt(0) == '-';
            deny[i] = strs[i].charAt(0) == '-';
            int start = deny[i] ? 1 : 0;
            int start = deny[i] ? 1 : 0;
            int end = strs[i].lastIndexOf("/");
            int end = strs[i].lastIndexOf("/");
            if ( end < 0 ) end = strs[i].length();
            if ( end < 0 ) end = strs[i].length();
            ip[i] = InetAddress.getByName(strs[i].substring(start,end)).getAddress();
            ip[i] = InetAddress.getByName(strs[i].substring(start,end)).getAddress();
            try {
            try {
                mask[i] = ( end+1 < strs[i].length() ) ? Integer.parseInt(strs[i].substring(end+1)) : ip[i].length*8;
                mask[i] = ( end+1 < strs[i].length() ) ? Integer.parseInt(strs[i].substring(end+1)) : ip[i].length*8;
            }
            }
            catch (Exception e) {
            catch (Exception e) {
                throw new IllegalArgumentException("Invalid mask format at position " + (i+1) + ": `" + strs[i].substring(end+1) + "'" );
                throw new IllegalArgumentException("Invalid mask format at position " + (i+1) + ": `" + strs[i].substring(end+1) + "'" );
            }
            }
        }
        }
    }
    }
 
 
    public IPPermissions() {
    public IPPermissions() {
    }
    }
 
 
    public boolean checkAddress ( byte rip[]) {
    public boolean checkAddress ( byte rip[]) {
        boolean allow = false;
        boolean allow = false;
        for ( int i=0; i<ip.length; i++ ) {
        for ( int i=0; i<ip.length; i++ ) {
            if ( ip[i].length == rip.length ) {
            if ( ip[i].length == rip.length ) {
                boolean eq = true;
                boolean eq = true;
                for ( int j=0; j<rip.length; j++ ) {
                for ( int j=0; j<rip.length; j++ ) {
                    int k = Math.max( (j+1)*8-mask[i], 0);
                    int k = Math.max( (j+1)*8-mask[i], 0);
                    eq = eq && ( (ip[i][j] & 255)>>k == (rip[j] & 255)>>k );
                    eq = eq && ( (ip[i][j] & 255)>>k == (rip[j] & 255)>>k );
                }
                }
                if ( eq ) allow = ! deny[i];
                if ( eq ) allow = ! deny[i];
            }
            }
        }
        }
        return allow;
        return allow;
    }
    }
 
 
    public boolean checkAddress ( InetAddress adr ) {
    public boolean checkAddress ( InetAddress adr ) {
        return checkAddress( adr.getAddress() );
        return checkAddress( adr.getAddress() );
    }
    }
 
 
    public static String toString(byte ip[]) {
    public static String toString(byte ip[]) {
        StringBuilder sb = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        if ( ip.length<6 || (ip.length & 1) != 0 ) {
        if ( ip.length<6 || (ip.length & 1) != 0 ) {
            for (int i=0; i<ip.length; i++ ) {
            for (int i=0; i<ip.length; i++ ) {
                if (i>0) sb.append('.');
                if (i>0) sb.append('.');
                sb.append(ip[i] & 255);
                sb.append(ip[i] & 255);
            }
            }
        }
        }
        else {
        else {
            for (int i=0; i+1<ip.length; i+=2 ) {
            for (int i=0; i+1<ip.length; i+=2 ) {
                if (i>0) sb.append(':');
                if (i>0) sb.append(':');
                sb.append(Integer.toString( ((ip[i] & 255)<<8) | (ip[i+1] & 255), 16 ) );
                sb.append(Integer.toString( ((ip[i] & 255)<<8) | (ip[i+1] & 255), 16 ) );
            }
            }
        }
        }
 
 
        return sb.toString();
        return sb.toString();
    }
    }
 
 
    public static String toString(InetAddress adr) {
    public static String toString(InetAddress adr) {
        return toString( adr.getAddress() );
        return toString( adr.getAddress() );
    }
    }
 
 
    public String toString() {
    public String toString() {
        StringBuilder sb = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<ip.length; i++ ) {
        for (int i=0; i<ip.length; i++ ) {
            if (i>0) sb.append(',');
            if (i>0) sb.append(',');
            if (deny[i]) sb.append('-');
            if (deny[i]) sb.append('-');
            sb.append(toString(ip[i])+"/"+mask[i]);
            sb.append(toString(ip[i])+"/"+mask[i]);
        }
        }
        return sb.toString();
        return sb.toString();
    }
    }
}
}
 
 
// *****************************************************************************
// *****************************************************************************
// ******* EPDescriptor ********************************************************
// ******* EPDescriptor ********************************************************
// *****************************************************************************
// *****************************************************************************
class EPDescriptor {
class EPDescriptor {
    private boolean in, bulk;
    private boolean in, bulk;
    public int num;
    public int num;
    public int size;
    public int size;
 
 
    public EPDescriptor ( boolean p_in, int p_num, boolean p_bulk, int p_size ) {
    public EPDescriptor ( boolean p_in, int p_num, boolean p_bulk, int p_size ) {
        in = p_in;
        in = p_in;
        num = p_num;
        num = p_num;
        bulk = p_bulk;
        bulk = p_bulk;
        size = p_size;
        size = p_size;
//      System.out.println((in ? "IN" : "OUT" ) + " EP "+num + ": " + (bulk ? "BULK" : "INT" ) + ", " + size);
//      System.out.println((in ? "IN" : "OUT" ) + " EP "+num + ": " + (bulk ? "BULK" : "INT" ) + ", " + size);
    }
    }
 
 
    public boolean in () {
    public boolean in () {
        return in;
        return in;
    }
    }
 
 
    public int num () {
    public int num () {
        return num;
        return num;
    }
    }
 
 
    public boolean bulk () {
    public boolean bulk () {
        return bulk;
        return bulk;
    }
    }
 
 
    public int size () {
    public int size () {
        return size;
        return size;
    }
    }
}
}
 
 
// *****************************************************************************
// *****************************************************************************
// ******* EPDescriptorVector **************************************************
// ******* EPDescriptorVector **************************************************
// *****************************************************************************
// *****************************************************************************
class EPDescriptorVector extends Vector<EPDescriptor> {
class EPDescriptorVector extends Vector<EPDescriptor> {
    public EPDescriptor find(int num) {
    public EPDescriptor find(int num) {
        for (int i=0; i<size(); i++) {
        for (int i=0; i<size(); i++) {
            if ( elementAt(i).num() == num ) return elementAt(i);
            if ( elementAt(i).num() == num ) return elementAt(i);
        }
        }
        return null;
        return null;
    }
    }
}
}
 
 
// *****************************************************************************
// *****************************************************************************
// ******* DeviceServer ********************************************************
// ******* DeviceServer ********************************************************
// *****************************************************************************
// *****************************************************************************
class DeviceServer {
class DeviceServer {
    public static final int maxConnections = 128;
    public static final int maxConnections = 128;
    public final static SimpleDateFormat msgDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    public final static SimpleDateFormat msgDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
 
 
    public static int usbVendorId = ZtexDevice1.ztexVendorId;
    public static int usbVendorId = ZtexDevice1.ztexVendorId;
    public static int usbProductId = -1;
    public static int usbProductId = -1;
    public static boolean cypress = true;
    public static boolean cypress = true;
    public static int httpPort = 9080;
    public static int httpPort = 9080;
    public static int socketPort = 9081;
    public static int socketPort = 9081;
    public static boolean quit = false;
    public static boolean quit = false;
 
 
    private static Vector<Socket> socketVector = new Vector<Socket>();
    private static Vector<Socket> socketVector = new Vector<Socket>();
    private static boolean verbose = false;
    private static boolean verbose = false;
    private static boolean quiet = false;
    private static boolean quiet = false;
    private static PrintStream logFile = null;
    private static PrintStream logFile = null;
    private static PrintStream log2File = null;
    private static PrintStream log2File = null;
 
 
    private static IPPermissions httpPermissions = new IPPermissions();
    private static IPPermissions httpPermissions = new IPPermissions();
    private static IPPermissions socketPermissions = new IPPermissions();
    private static IPPermissions socketPermissions = new IPPermissions();
    private static String httpBind = null, socketBind = null;
    private static String httpBind = null, socketBind = null;
 
 
    private static ZtexScanBus1 scanBus;
    private static ZtexScanBus1 scanBus;
    private static int busIdx[];
    private static int busIdx[];
    private static int devNum[];
    private static int devNum[];
    private static int confNum[];
    private static int confNum[];
    private static EPDescriptorVector eps[];
    private static EPDescriptorVector eps[];
    private static Vector<String> dirnameDB = new Vector<String>();
    private static Vector<String> dirnameDB = new Vector<String>();
 
 
// ******* addSocket ***********************************************************
// ******* addSocket ***********************************************************
    public synchronized static void addSocket( Socket socket ) {
    public synchronized static void addSocket( Socket socket ) {
        info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " established" );
        info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " established" );
        socketVector.addElement(socket);
        socketVector.addElement(socket);
    }
    }
 
 
// ******* removeSocket ********************************************************
// ******* removeSocket ********************************************************
    public synchronized static void removeSocket(Socket socket) {
    public synchronized static void removeSocket(Socket socket) {
        info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " closed" );
        info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " closed" );
        socketVector.remove(socket);
        socketVector.remove(socket);
    }
    }
 
 
// ******* httpPermissions *****************************************************
// ******* httpPermissions *****************************************************
    public static IPPermissions httpPermissions() {
    public static IPPermissions httpPermissions() {
        return httpPermissions;
        return httpPermissions;
    }
    }
 
 
// ******* sleep ***************************************************************
// ******* sleep ***************************************************************
    public static void sleep(int ms) {
    public static void sleep(int ms) {
        try {
        try {
            Thread.sleep(ms);
            Thread.sleep(ms);
        }
        }
        catch ( InterruptedException e ) {
        catch ( InterruptedException e ) {
        }
        }
    }
    }
 
 
// ******* info ****************************************************************
// ******* info ****************************************************************
    public synchronized static void info (String msg) {
    public synchronized static void info (String msg) {
        if ( verbose ) System.err.println( msg );
        if ( verbose ) System.err.println( msg );
        if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg );
        if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg );
    }
    }
 
 
// ******* error ***************************************************************
// ******* error ***************************************************************
    public synchronized static void error (String msg) {
    public synchronized static void error (String msg) {
        if ( ! quiet ) System.err.println( msg );
        if ( ! quiet ) System.err.println( msg );
        if ( logFile != null ) logFile.println( msgDateFormat.format(new Date()) + ": " + msg );
        if ( logFile != null ) logFile.println( msgDateFormat.format(new Date()) + ": " + msg );
        if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg );
        if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg );
    }
    }
 
 
// ******* getDirnameNum *******************************************************
// ******* getDirnameNum *******************************************************
    public static int getDirnameIdx ( String dirname ) {
    public static int getDirnameIdx ( String dirname ) {
        if ( dirname == null ) return -1;
        if ( dirname == null ) return -1;
        for ( int i=0; i<dirnameDB.size(); i++ ) {
        for ( int i=0; i<dirnameDB.size(); i++ ) {
            if ( dirname.equals(dirnameDB.elementAt(i)) ) return i;
            if ( dirname.equals(dirnameDB.elementAt(i)) ) return i;
        }
        }
        dirnameDB.add(dirname);
        dirnameDB.add(dirname);
        info("Found bus \"" +dirname + "\": assigned bus index " + (dirnameDB.size()-1));
        info("Found bus \"" +dirname + "\": assigned bus index " + (dirnameDB.size()-1));
        return dirnameDB.size()-1;
        return dirnameDB.size()-1;
    }
    }
 
 
// ******* scanUSB *************************************************************
// ******* scanUSB *************************************************************
    public synchronized static void scanUSB () {
    public synchronized static void scanUSB () {
        info("Scanning USB ...");
        info("Scanning USB ...");
        scanBus = new ZtexScanBus1( usbVendorId, usbProductId, cypress, false, 1 );
        scanBus = new ZtexScanBus1( usbVendorId, usbProductId, cypress, false, 1 );
        int n = scanBus.numberOfDevices();
        int n = scanBus.numberOfDevices();
        if ( n > 0 ) {
        if ( n > 0 ) {
            busIdx = new int[n];
            busIdx = new int[n];
            devNum = new int[n];
            devNum = new int[n];
            confNum = new int[n];
            confNum = new int[n];
            eps = new EPDescriptorVector[n];
            eps = new EPDescriptorVector[n];
            for ( int i=0; i<n; i++ ) {
            for ( int i=0; i<n; i++ ) {
                Usb_Device dev = scanBus.device(i).dev();
                Usb_Device dev = scanBus.device(i).dev();
                busIdx[i] = getDirnameIdx( dev.getBus().getDirname() );
                busIdx[i] = getDirnameIdx( dev.getBus().getDirname() );
                devNum[i] = dev.getDevnum();
                devNum[i] = dev.getDevnum();
                confNum[i] = -1;
                confNum[i] = -1;
                eps[i] = new EPDescriptorVector();
                eps[i] = new EPDescriptorVector();
                try {
                try {
                    if ( dev.getDescriptor().getBNumConfigurations() < 1 ) throw new Exception();
                    if ( dev.getDescriptor().getBNumConfigurations() < 1 ) throw new Exception();
                    Usb_Config_Descriptor conf = dev.getConfig()[0];
                    Usb_Config_Descriptor conf = dev.getConfig()[0];
                    confNum[i] = conf.getBConfigurationValue();
                    confNum[i] = conf.getBConfigurationValue();
                    if ( conf.getBNumInterfaces() < 1 ) throw new Exception();
                    if ( conf.getBNumInterfaces() < 1 ) throw new Exception();
                    Usb_Interface iface = conf.getInterface()[0];
                    Usb_Interface iface = conf.getInterface()[0];
                    if ( iface.getNumAltsetting() < 1 ) throw new Exception();
                    if ( iface.getNumAltsetting() < 1 ) throw new Exception();
                    Usb_Interface_Descriptor desc = iface.getAltsetting()[0];
                    Usb_Interface_Descriptor desc = iface.getAltsetting()[0];
                    if ( desc.getBNumEndpoints() < 1 ) throw new Exception();
                    if ( desc.getBNumEndpoints() < 1 ) throw new Exception();
                    Usb_Endpoint_Descriptor epd[] = desc.getEndpoint();
                    Usb_Endpoint_Descriptor epd[] = desc.getEndpoint();
                    for ( int j=0; j<epd.length; j++ ) {
                    for ( int j=0; j<epd.length; j++ ) {
                        int t = epd[j].getBmAttributes() & Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_MASK;
                        int t = epd[j].getBmAttributes() & Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_MASK;
                        if ( t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK || t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_INTERRUPT )
                        if ( t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK || t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_INTERRUPT )
                            eps[i].addElement(new EPDescriptor(
                            eps[i].addElement(new EPDescriptor(
                                    (epd[j].getBEndpointAddress() & Usb_Endpoint_Descriptor.USB_ENDPOINT_DIR_MASK) != 0,
                                    (epd[j].getBEndpointAddress() & Usb_Endpoint_Descriptor.USB_ENDPOINT_DIR_MASK) != 0,
                                    epd[j].getBEndpointAddress() & Usb_Endpoint_Descriptor.USB_ENDPOINT_ADDRESS_MASK,
                                    epd[j].getBEndpointAddress() & Usb_Endpoint_Descriptor.USB_ENDPOINT_ADDRESS_MASK,
                                    t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK,
                                    t == Usb_Endpoint_Descriptor.USB_ENDPOINT_TYPE_BULK,
                                    epd[j].getWMaxPacketSize()
                                    epd[j].getWMaxPacketSize()
                                ) );
                                ) );
                    }
                    }
                }
                }
                catch (Exception e) {
                catch (Exception e) {
                }
                }
            }
            }
        }
        }
    }
    }
 
 
// ******* loadFirmware ********************************************************
// ******* loadFirmware ********************************************************
    public synchronized static void loadFirmware ( Ztex1v1 ztex, StringBuilder messages, InputStream in, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseEeprom ) throws Exception {
    public synchronized static void loadFirmware ( Ztex1v1 ztex, StringBuilder messages, InputStream in, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseEeprom ) throws Exception {
        if ( ztex == null ) return;
        if ( ztex == null ) return;
        eraseEeprom = eraseEeprom && (! toNonVolatile );
        eraseEeprom = eraseEeprom && (! toNonVolatile );
        if ( toVolatile || toNonVolatile ) {
        if ( toVolatile || toNonVolatile ) {
            if ( in == null ) throw new Exception("No firmware defined.");
            if ( in == null ) throw new Exception("No firmware defined.");
            ZtexIhxFile1 ihxFile = new ZtexIhxFile1( in, inName );
            ZtexIhxFile1 ihxFile = new ZtexIhxFile1( in, inName );
            if ( toVolatile ) {
            if ( toVolatile ) {
                long i = ztex.uploadFirmware( ihxFile, force );
                long i = ztex.uploadFirmware( ihxFile, force );
                if ( messages != null ) messages.append("Firmware uploaded to volatile memory: "+i+"ms\n");
                if ( messages != null ) messages.append("Firmware uploaded to volatile memory: "+i+"ms\n");
                }
                }
            if ( toNonVolatile ) {
            if ( toNonVolatile ) {
                 long i = ztex.eepromUpload( ihxFile, force );
                 long i = ztex.eepromUpload( ihxFile, force );
                if ( messages != null ) messages.append("Firmware uploaded to non-volatile memory: "+i+"ms\n");
                if ( messages != null ) messages.append("Firmware uploaded to non-volatile memory: "+i+"ms\n");
            }
            }
        }
        }
        if ( eraseEeprom ) {
        if ( eraseEeprom ) {
            ztex.eepromDisable();
            ztex.eepromDisable();
            if ( messages != null ) messages.append("Firmware in non-volatile memory disabled\n");
            if ( messages != null ) messages.append("Firmware in non-volatile memory disabled\n");
        }
        }
    }
    }
 
 
// ******* loadBitstream *******************************************************
// ******* loadBitstream *******************************************************
    public synchronized static void loadBitstream ( Ztex1v1 ztex, StringBuilder messages, byte[] buf, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseFlash ) throws Exception {
    public synchronized static void loadBitstream ( Ztex1v1 ztex, StringBuilder messages, byte[] buf, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseFlash ) throws Exception {
        if ( ztex == null ) return;
        if ( ztex == null ) return;
        eraseFlash = eraseFlash && (! toNonVolatile );
        eraseFlash = eraseFlash && (! toNonVolatile );
        if ( toVolatile || toNonVolatile ) {
        if ( toVolatile || toNonVolatile ) {
            if ( buf == null ) throw new Exception("No firmware defined.");
            if ( buf == null ) throw new Exception("No firmware defined.");
            if ( toVolatile ) {
            if ( toVolatile ) {
                long i = ztex.configureFpga( new ByteArrayInputStream(buf), force, -1 );
                long i = ztex.configureFpga( new ByteArrayInputStream(buf), force, -1 );
                if ( messages != null ) messages.append("Bitstream uploaded to volatile memory: "+i+"ms\n");
                if ( messages != null ) messages.append("Bitstream uploaded to volatile memory: "+i+"ms\n");
                }
                }
            if ( toNonVolatile ) {
            if ( toNonVolatile ) {
                long i = ztex.flashUploadBitstream( new ByteArrayInputStream(buf), -1 );
                long i = ztex.flashUploadBitstream( new ByteArrayInputStream(buf), -1 );
                if ( messages != null ) messages.append("Bitstream uploaded to non-volatile memory: "+i+"ms\n");
                if ( messages != null ) messages.append("Bitstream uploaded to non-volatile memory: "+i+"ms\n");
            }
            }
        }
        }
        if ( eraseFlash ) {
        if ( eraseFlash ) {
            ztex.flashResetBitstream();
            ztex.flashResetBitstream();
            if ( messages != null ) messages.append("Bitstream in non-volatile memory disabled\n");
            if ( messages != null ) messages.append("Bitstream in non-volatile memory disabled\n");
        }
        }
    }
    }
 
 
    public synchronized static void loadBitstream ( Ztex1v1 ztex, StringBuilder messages, InputStream in, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseFlash ) throws Exception {
    public synchronized static void loadBitstream ( Ztex1v1 ztex, StringBuilder messages, InputStream in, String inName, boolean force, boolean toVolatile, boolean toNonVolatile, boolean eraseFlash ) throws Exception {
        byte buf[] = new byte[65536];
        byte buf[] = new byte[65536];
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int i;
        int i;
        do {
        do {
            i=in.read(buf);
            i=in.read(buf);
            if (i>0) out.write(buf,0,i);
            if (i>0) out.write(buf,0,i);
        } while (i>0);
        } while (i>0);
        loadBitstream(ztex, messages, out.toByteArray(), inName, force, toVolatile, toNonVolatile, eraseFlash);
        loadBitstream(ztex, messages, out.toByteArray(), inName, force, toVolatile, toNonVolatile, eraseFlash);
    }
    }
 
 
// ******* claim ***************************************************************
// ******* claim ***************************************************************
    public synchronized static void claim ( Ztex1v1 ztex, StringBuilder messages ) {
    public synchronized static void claim ( Ztex1v1 ztex, StringBuilder messages ) {
        int c = 1;
        int c = 1;
        for (int i=0; i<scanBus.numberOfDevices(); i++ ) {
        for (int i=0; i<scanBus.numberOfDevices(); i++ ) {
            if ( scanBus.device(i) == ztex.dev() ) {
            if ( scanBus.device(i) == ztex.dev() ) {
                c=confNum[i];
                c=confNum[i];
            }
            }
        }
        }
        try {
        try {
            ztex.setConfiguration(c);
            ztex.setConfiguration(c);
        }
        }
        catch ( UsbException e ) {
        catch ( UsbException e ) {
            if (messages!=null) messages.append("Warning: "+e.getLocalizedMessage()+'\n');
            if (messages!=null) messages.append("Warning: "+e.getLocalizedMessage()+'\n');
        }
        }
 
 
        try {
        try {
            ztex.claimInterface(0);
            ztex.claimInterface(0);
        }
        }
        catch ( UsbException e ) {
        catch ( UsbException e ) {
            if (messages!=null) messages.append("Warning: "+e.getLocalizedMessage()+'\n');
            if (messages!=null) messages.append("Warning: "+e.getLocalizedMessage()+'\n');
        }
        }
    }
    }
 
 
// ******* release *************************************************************
// ******* release *************************************************************
    public synchronized static void release ( Ztex1v1 ztex ) {
    public synchronized static void release ( Ztex1v1 ztex ) {
        if (ztex!=null) ztex.releaseInterface(0);
        if (ztex!=null) ztex.releaseInterface(0);
    }
    }
 
 
// ******* epUpload ************************************************************
// ******* epUpload ************************************************************
    public synchronized static void epUpload ( Ztex1v1 ztex, EPDescriptor ep, InputStream in, StringBuilder messages ) throws Exception {
    public synchronized static void epUpload ( Ztex1v1 ztex, EPDescriptor ep, InputStream in, StringBuilder messages ) throws Exception {
        if ( ztex == null ) return;
        if ( ztex == null ) return;
        if ( ep == null || ep.in() ) throw new UsbException(ztex.dev().dev(), "No valid endpoint defined");
        if ( ep == null || ep.in() ) throw new UsbException(ztex.dev().dev(), "No valid endpoint defined");
 
 
        claim(ztex,messages);
        claim(ztex,messages);
 
 
        int bufSize = ep.num()==1 ? 64 : 256*1024;
        int bufSize = ep.num()==1 ? 64 : 256*1024;
        byte buf[] = new byte[bufSize];
        byte buf[] = new byte[bufSize];
        int r,i;
        int r,i;
        do {
        do {
            i = r = Math.max(in.read(buf),0);
            i = r = Math.max(in.read(buf),0);
            if ( i>0 ) i = ep.bulk() ? LibusbJava.usb_bulk_write(ztex.handle(), ep.num, buf, r, 1000) : LibusbJava.usb_interrupt_write(ztex.handle(), ep.num, buf, r, 1000);
            if ( i>0 ) i = ep.bulk() ? LibusbJava.usb_bulk_write(ztex.handle(), ep.num, buf, r, 1000) : LibusbJava.usb_interrupt_write(ztex.handle(), ep.num, buf, r, 1000);
        } while (r>0 && r==i);
        } while (r>0 && r==i);
 
 
        if (i<0) throw new UsbException("Write error: " + LibusbJava.usb_strerror());
        if (i<0) throw new UsbException("Write error: " + LibusbJava.usb_strerror());
        if ( r!=i ) throw new UsbException("Write error: wrote " + i + " bytes instead of " + r + " bytes");
        if ( r!=i ) throw new UsbException("Write error: wrote " + i + " bytes instead of " + r + " bytes");
    }
    }
 
 
// ******* epDownload **********************************************************
// ******* epDownload **********************************************************
    public synchronized static void epDownload ( Ztex1v1 ztex, EPDescriptor ep, OutputStream out, int maxSize, StringBuilder messages ) throws Exception {
    public synchronized static void epDownload ( Ztex1v1 ztex, EPDescriptor ep, OutputStream out, int maxSize, StringBuilder messages ) throws Exception {
        if ( ztex == null ) return;
        if ( ztex == null ) return;
        if ( ep == null || ! ep.in() ) throw new UsbException(ztex.dev().dev(), "No valid endpoint defined");
        if ( ep == null || ! ep.in() ) throw new UsbException(ztex.dev().dev(), "No valid endpoint defined");
        if ( maxSize < 1 ) maxSize = Integer.MAX_VALUE;
        if ( maxSize < 1 ) maxSize = Integer.MAX_VALUE;
 
 
        claim(ztex,messages);
        claim(ztex,messages);
 
 
        int bufSize = ep.num()==1 ? 64 : 256*1024;
        int bufSize = ep.num()==1 ? 64 : 256*1024;
        byte buf[] = new byte[bufSize];
        byte buf[] = new byte[bufSize];
        int r,i;
        int r,i;
        int j=0;
        int j=0;
        do {
        do {
            r = Math.min(bufSize,maxSize);
            r = Math.min(bufSize,maxSize);
            maxSize-=r;
            maxSize-=r;
            i = ep.bulk() ? LibusbJava.usb_bulk_read(ztex.handle(), 0x80 | ep.num, buf, r, j==0 ? 5000 : 1000) : LibusbJava.usb_interrupt_read(ztex.handle(), 0x80 | ep.num, buf, r, 1000);
            i = ep.bulk() ? LibusbJava.usb_bulk_read(ztex.handle(), 0x80 | ep.num, buf, r, j==0 ? 5000 : 1000) : LibusbJava.usb_interrupt_read(ztex.handle(), 0x80 | ep.num, buf, r, 1000);
            if (i>0) out.write(buf,0,i);
            if (i>0) out.write(buf,0,i);
//          System.out.println("r: "+i);
//          System.out.println("r: "+i);
            j++;
            j++;
        } while (maxSize>0 && r==i);
        } while (maxSize>0 && r==i);
 
 
        if (i<0) throw new UsbException("Read error: " + LibusbJava.usb_strerror());
        if (i<0) throw new UsbException("Read error: " + LibusbJava.usb_strerror());
    }
    }
 
 
// ******* numberOfDevices *****************************************************
// ******* numberOfDevices *****************************************************
    public synchronized static int numberOfDevices() {
    public synchronized static int numberOfDevices() {
        return scanBus.numberOfDevices();
        return scanBus.numberOfDevices();
    }
    }
 
 
// ******* device **************************************************************
// ******* device **************************************************************
    public synchronized static ZtexDevice1 device (int i) throws IndexOutOfBoundsException {
    public synchronized static ZtexDevice1 device (int i) throws IndexOutOfBoundsException {
        return scanBus.device(i);
        return scanBus.device(i);
    }
    }
 
 
// ******* findDevice **********************************************************
// ******* findDevice **********************************************************
    public synchronized static ZtexDevice1 findDevice (int b, int d) {
    public synchronized static ZtexDevice1 findDevice (int b, int d) {
        int n = numberOfDevices();
        int n = numberOfDevices();
        for ( int i=0; i<n; i++ ) {
        for ( int i=0; i<n; i++ ) {
            try {
            try {
                if ( busIdx[i]==b && devNum[i]==d ) return scanBus.device(i);
                if ( busIdx[i]==b && devNum[i]==d ) return scanBus.device(i);
            } catch ( IndexOutOfBoundsException e ) {
            } catch ( IndexOutOfBoundsException e ) {
            }
            }
        }
        }
        return null;
        return null;
    }
    }
 
 
// ******* busIdx **************************************************************
// ******* busIdx **************************************************************
    public synchronized static int busIdx (int i) throws IndexOutOfBoundsException {
    public synchronized static int busIdx (int i) throws IndexOutOfBoundsException {
        if ( i<0 || i>=busIdx.length) throw new IndexOutOfBoundsException( "Device number out of range. Valid numbers are 0.." + (busIdx.length-1) );
        if ( i<0 || i>=busIdx.length) throw new IndexOutOfBoundsException( "Device number out of range. Valid numbers are 0.." + (busIdx.length-1) );
        return busIdx[i];
        return busIdx[i];
    }
    }
 
 
// ******* devNum **************************************************************
// ******* devNum **************************************************************
    public synchronized static int devNum (int i) throws IndexOutOfBoundsException {
    public synchronized static int devNum (int i) throws IndexOutOfBoundsException {
        if ( i<0 || i>=devNum.length) throw new IndexOutOfBoundsException( "Device number out of range. Valid numbers are 0.." + (devNum.length-1) );
        if ( i<0 || i>=devNum.length) throw new IndexOutOfBoundsException( "Device number out of range. Valid numbers are 0.." + (devNum.length-1) );
        return devNum[i];
        return devNum[i];
    }
    }
 
 
// ******* getEps  *************************************************************
// ******* getEps  *************************************************************
    public synchronized static EPDescriptorVector getEps (int b, int d) {
    public synchronized static EPDescriptorVector getEps (int b, int d) {
        int n = numberOfDevices();
        int n = numberOfDevices();
        for ( int i=0; i<n; i++ ) {
        for ( int i=0; i<n; i++ ) {
            try {
            try {
                if ( busIdx[i]==b && devNum[i]==d ) return eps[i];
                if ( busIdx[i]==b && devNum[i]==d ) return eps[i];
            } catch ( IndexOutOfBoundsException e ) {
            } catch ( IndexOutOfBoundsException e ) {
            }
            }
        }
        }
        return null;
        return null;
    }
    }
 
 
// ******* main ****************************************************************
// ******* main ****************************************************************
    public static void main (String args[]) {
    public static void main (String args[]) {
        LibusbJava.usb_init();
        LibusbJava.usb_init();
 
 
        final String helpMsg = new String (
        final String helpMsg = new String (
                        "Global parameters:\n"+
                        "Global parameters:\n"+
                        "    -nc              Do not scan for Cypress EZ-USB devices without ZTEX firmware\n"+
                        "    -nc              Do not scan for Cypress EZ-USB devices without ZTEX firmware\n"+
                        "    -id <VID> <PID>  Scan for devices with given Vendor ID and Product ID\n"+
                        "    -id <VID> <PID>  Scan for devices with given Vendor ID and Product ID\n"+
                        "    -sp <port>       Port number for the socket interface (default: 9081; <0: disabled)\n"+
                        "    -sp <port>       Port number for the socket interface (default: 9081; <0: disabled)\n"+
                        "    -hp <port>       Port number for the HTTP interface (default: 9080; <0: disabled)\n"+
                        "    -hp <port>       Port number for the HTTP interface (default: 9080; <0: disabled)\n"+
                        "    -sa [-]<address>[/<mask>][,...]  Allow (permit if '-' is given) HTTP connection from this address(es),\n"+
                        "    -sa [-]<address>[/<mask>][,...]  Allow (permit if '-' is given) HTTP connection from this address(es),\n"+
                        "                     <mask> 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+
                        "                     <mask> 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+
                        "    -ha [-]<address>[/<mask>][,...]  Allow (permit if '-' is given) HTTP connection from this address(es),\n"+
                        "    -ha [-]<address>[/<mask>][,...]  Allow (permit if '-' is given) HTTP connection from this address(es),\n"+
                        "                     <mask> 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+
                        "                     <mask> 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+
                        "    -sb <address>    Bind socket server to this address (default: listen on all interfaces)\n"+
                        "    -sb <address>    Bind socket server to this address (default: listen on all interfaces)\n"+
                        "    -hb <address>    Bind HTTP server to this address (default: listen on all interfaces)\n"+
                        "    -hb <address>    Bind HTTP server to this address (default: listen on all interfaces)\n"+
                        "    -v               Be verbose\n"+
                        "    -v               Be verbose\n"+
                        "    -q               Be quiet\n"+
                        "    -q               Be quiet\n"+
                        "    -l               Log file\n"+
                        "    -l               Log file\n"+
                        "    -l2              Verbose log file\n"+
                        "    -l2              Verbose log file\n"+
                        "    -h               Help" );
                        "    -h               Help" );
 
 
// process parameters
// process parameters
        try {
        try {
 
 
            for (int i=0; i<args.length; i++ ) {
            for (int i=0; i<args.length; i++ ) {
                if ( args[i].equals("-nc") ) {
                if ( args[i].equals("-nc") ) {
                    cypress = false;
                    cypress = false;
                }
                }
                else if ( args[i].equals("-id") ) {
                else if ( args[i].equals("-id") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception();
                            throw new Exception();
                        usbVendorId = Integer.decode( args[i] );
                        usbVendorId = Integer.decode( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: Vendor ID expected after -id");
                        System.err.println("Error: Vendor ID expected after -id");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception();
                            throw new Exception();
                        usbProductId = Integer.decode( args[i] );
                        usbProductId = Integer.decode( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: Product ID expected after -id <VID>");
                        System.err.println("Error: Product ID expected after -id <VID>");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-hp") ) {
                else if ( args[i].equals("-hp") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception();
                            throw new Exception();
                        httpPort = Integer.parseInt( args[i] );
                        httpPort = Integer.parseInt( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: Port number expected after -hp");
                        System.err.println("Error: Port number expected after -hp");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-sp") ) {
                else if ( args[i].equals("-sp") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception();
                            throw new Exception();
                        socketPort = Integer.parseInt( args[i] );
                        socketPort = Integer.parseInt( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: Port number expected after -sp");
                        System.err.println("Error: Port number expected after -sp");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-ha") ) {
                else if ( args[i].equals("-ha") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception("Argument expected after -ha");
                            throw new Exception("Argument expected after -ha");
                        httpPermissions = new IPPermissions( args[i] );
                        httpPermissions = new IPPermissions( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error parsing HTTP permissions:");
                        System.err.println("Error parsing HTTP permissions:");
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-sa") ) {
                else if ( args[i].equals("-sa") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception("Argument expected after -hs");
                            throw new Exception("Argument expected after -hs");
                        socketPermissions = new IPPermissions( args[i] );
                        socketPermissions = new IPPermissions( args[i] );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error parsing socket permissions:");
                        System.err.println("Error parsing socket permissions:");
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-hb") ) {
                else if ( args[i].equals("-hb") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception("Argument expected after -hb");
                            throw new Exception("Argument expected after -hb");
                        httpBind = args[i];
                        httpBind = args[i];
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error parsing HTTP permissions:");
                        System.err.println("Error parsing HTTP permissions:");
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-sb") ) {
                else if ( args[i].equals("-sb") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception("Argument expected after -sb");
                            throw new Exception("Argument expected after -sb");
                        socketBind = args[i];
                        socketBind = args[i];
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error parsing HTTP permissions:");
                        System.err.println("Error parsing HTTP permissions:");
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-hb") ) {
                else if ( args[i].equals("-hb") ) {
                    i++;
                    i++;
                    try {
                    try {
                        if (i>=args.length)
                        if (i>=args.length)
                            throw new Exception("Argument expected after -hb");
                            throw new Exception("Argument expected after -hb");
                        httpBind = args[i];
                        httpBind = args[i];
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error parsing HTTP permissions:");
                        System.err.println("Error parsing HTTP permissions:");
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-v") ) {
                else if ( args[i].equals("-v") ) {
                    verbose = true;
                    verbose = true;
                }
                }
                else if ( args[i].equals("-q") ) {
                else if ( args[i].equals("-q") ) {
                    quiet = true;
                    quiet = true;
                }
                }
                else if ( args[i].equals("-l") ) {
                else if ( args[i].equals("-l") ) {
                    i++;
                    i++;
                    if (i>=args.length) {
                    if (i>=args.length) {
                        System.err.println("Error: File name expected after `-l'");
                        System.err.println("Error: File name expected after `-l'");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                    try {
                    try {
                        logFile = new PrintStream ( new FileOutputStream ( args[i], true ), true );
                        logFile = new PrintStream ( new FileOutputStream ( args[i], true ), true );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: File name expected after `-l': "+e.getLocalizedMessage() );
                        System.err.println("Error: File name expected after `-l': "+e.getLocalizedMessage() );
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-l2") ) {
                else if ( args[i].equals("-l2") ) {
                    i++;
                    i++;
                    if (i>=args.length) {
                    if (i>=args.length) {
                        System.err.println("Error: File name expected after `-l2'");
                        System.err.println("Error: File name expected after `-l2'");
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                    try {
                    try {
                        log2File = new PrintStream ( new FileOutputStream ( args[i], true ), true );
                        log2File = new PrintStream ( new FileOutputStream ( args[i], true ), true );
                    }
                    }
                    catch (Exception e) {
                    catch (Exception e) {
                        System.err.println("Error: File name expected after `-l2': "+e.getLocalizedMessage() );
                        System.err.println("Error: File name expected after `-l2': "+e.getLocalizedMessage() );
                        System.err.println(helpMsg);
                        System.err.println(helpMsg);
                        System.exit(1);
                        System.exit(1);
                    }
                    }
                }
                }
                else if ( args[i].equals("-h") ) {
                else if ( args[i].equals("-h") ) {
                    System.err.println(helpMsg);
                    System.err.println(helpMsg);
                    System.exit(0);
                    System.exit(0);
                }
                }
                else {
                else {
                    System.err.println("Error: Invalid option: `"+args[i]+"'");
                    System.err.println("Error: Invalid option: `"+args[i]+"'");
                    System.err.println(helpMsg);
                    System.err.println(helpMsg);
                    System.exit(1);
                    System.exit(1);
                }
                }
            }
            }
 
 
            if ( httpPort < 0 && socketPort < 0 ) {
            if ( httpPort < 0 && socketPort < 0 ) {
                error("neither HTTP nor socket interface enabled: exiting");
                error("neither HTTP nor socket interface enabled: exiting");
                System.exit(0);
                System.exit(0);
            }
            }
 
 
// init USB stuff
// init USB stuff
            LibusbJava.usb_init();
            LibusbJava.usb_init();
            LibusbJava.usb_find_busses();
            LibusbJava.usb_find_busses();
            Usb_Bus bus = LibusbJava.usb_get_busses();
            Usb_Bus bus = LibusbJava.usb_get_busses();
            while ( bus != null ) {
            while ( bus != null ) {
                getDirnameIdx(bus.getDirname());
                getDirnameIdx(bus.getDirname());
                bus = bus.getNext();
                bus = bus.getNext();
            }
            }
            scanUSB();
            scanUSB();
 
 
// start http server
// start http server
            HttpServer httpServer = null;
            HttpServer httpServer = null;
            if ( httpPort > 0 ) {
            if ( httpPort > 0 ) {
                error ( "Listening for http connections at port " + httpPort + " from addresses " + httpPermissions ); // not really an error
                error ( "Listening for http connections at port " + httpPort + " from addresses " + httpPermissions ); // not really an error
                httpServer = HttpServer.create( ( httpBind == null ) ? new InetSocketAddress(httpPort) : new InetSocketAddress(InetAddress.getByName(httpBind),httpPort), 0);
                httpServer = HttpServer.create( ( httpBind == null ) ? new InetSocketAddress(httpPort) : new InetSocketAddress(InetAddress.getByName(httpBind),httpPort), 0);
                httpServer.createContext("/", new ZtexHttpHandler());
                httpServer.createContext("/", new ZtexHttpHandler());
                httpServer.setExecutor(null);
                httpServer.setExecutor(null);
                httpServer.start();
                httpServer.start();
            }
            }
 
 
// run socket server
// run socket server
            if ( socketPort > 0 ) {
            if ( socketPort > 0 ) {
                error ( "Listening for socket connections at port " + socketPort + " from addresses " + socketPermissions ); // not really an error
                error ( "Listening for socket connections at port " + socketPort + " from addresses " + socketPermissions ); // not really an error
                ServerSocket ss = (socketBind == null) ?  new ServerSocket ( socketPort, 20 ) : new ServerSocket ( socketPort, 20,  InetAddress.getByName(socketBind));
                ServerSocket ss = (socketBind == null) ?  new ServerSocket ( socketPort, 20 ) : new ServerSocket ( socketPort, 20,  InetAddress.getByName(socketBind));
                ss.setSoTimeout(500);
                ss.setSoTimeout(500);
                while ( ! quit ) {
                while ( ! quit ) {
                    if ( socketVector.size() < maxConnections ) {
                    if ( socketVector.size() < maxConnections ) {
                        try {
                        try {
                            Socket cs = ss.accept();
                            Socket cs = ss.accept();
                            if ( socketPermissions.checkAddress( cs.getInetAddress() ) ) {
                            if ( socketPermissions.checkAddress( cs.getInetAddress() ) ) {
                                new SocketThread( cs );
                                new SocketThread( cs );
                            }
                            }
                            else {
                            else {
                                info( "Connection from " + IPPermissions.toString( cs.getInetAddress() ) + " refused" );
                                info( "Connection from " + IPPermissions.toString( cs.getInetAddress() ) + " refused" );
                            }
                            }
                        }
                        }
                        catch ( SocketTimeoutException e ) {
                        catch ( SocketTimeoutException e ) {
                        }
                        }
                    }
                    }
                    else {
                    else {
                        sleep(1000);
                        sleep(1000);
                    }
                    }
                }
                }
            }
            }
            else {
            else {
                while ( ! quit ) {
                while ( ! quit ) {
                    sleep(1000);
                    sleep(1000);
                }
                }
            }
            }
 
 
// stop http server
// stop http server
            if ( httpServer!=null ) httpServer.stop(1);
            if ( httpServer!=null ) httpServer.stop(1);
 
 
        }
        }
        catch (Exception e) {
        catch (Exception e) {
            error("Error: "+e.getLocalizedMessage() );
            error("Error: "+e.getLocalizedMessage() );
        }
        }
   }
   }
 
 
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.