/*! DeviceServer for the ZTEX USB-FPGA Modules Copyright (C) 2009-2014 ZTEX GmbH. http://www.ztex.de 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 published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see http://www.gnu.org/licenses/. !*/ /* ZTEX device server */ import java.io.*; import java.util.*; import java.text.*; import java.net.*; import com.sun.net.httpserver.*; import ch.ntb.usb.*; import ztex.*; // ***************************************************************************** // ******* ErrorBuffer ********************************************************* // ***************************************************************************** class ErrorBuffer { private static final int bufsize = 128; private static String cids[] = new String[bufsize]; private static StringBuilder messages[] = new StringBuilder[bufsize]; private static int id[] = new int[bufsize]; private static boolean initialized = false; private static int idcnt = 0; private static void initialize() { if ( ! initialized ) { for ( int i=0; i=0 && cid.equals(cids[i]) ) k=i; } if ( k>=0 ) { messages[k].append(message); } else { id[j] = idcnt; idcnt ++; messages[j] = message; cids[j] = cid; } } public static StringBuilder get (String cid) { if (cid==null) return null; initialize(); for ( int i=0; i=0 && cid.equals(cids[i]) ) { id[i] = -1; return messages[i]; } } return null; } } // ***************************************************************************** // ******* NonBlockingBufferedInputStream ************************************** // ***************************************************************************** class NonBlockingBufferedInputStream extends BufferedInputStream { private final int timeout = 1000; private final int delay = 10; NonBlockingBufferedInputStream(InputStream in) { super(in); } public int read( byte[] b, int off, int len) throws IOException { int cnt=0, a=1; while ( len > 0 && a>0 ) { a=available(); int to=0; while ( a<1 && to len ) a=len; if ( a > 0 ) super.read(b, off, a); off+=a; len-=a; cnt+=a; } return cnt; } public void close() { } } // ***************************************************************************** // ******* SocketThread ******************************************************** // ***************************************************************************** class SocketThread extends Thread { private Socket socket; private PrintStream printer = null; private BufferedOutputStream binOut = null; private NonBlockingBufferedInputStream in = null; // ******* SocketThread ******************************************************** public SocketThread ( Socket s ) { socket = s; DeviceServer.addSocket(socket); start(); } // ******* out ***************************************************************** private BufferedOutputStream binOut() throws IOException { if ( binOut == null ) binOut = new BufferedOutputStream( socket.getOutputStream() ); if ( printer != null ) { printer.flush(); printer = new PrintStream( binOut ); } return binOut; } // ******* writer ************************************************************** private PrintStream printer() throws IOException { if ( printer == null ) printer = new PrintStream( binOut==null ? socket.getOutputStream() : binOut, true); return printer; } // ******* printHelp *********************************************************** private void printHelp ( String cmd ) throws IOException { boolean all = cmd.equalsIgnoreCase("all"); PrintStream out = printer(); boolean b = false; if ( all || cmd.equalsIgnoreCase("help") ) { out.println( "Supported commands:\n" + " scan Scan buses\n" + " info Print device capabilities\n" + " upload Upload firmware\n" + " config Configure FPGA\n" + " read Read data from given endpoint\n" + " write Write data to given endpoint\n" + " errors Returns errors\n" + " help Help\n" + " quit Quit Device Server\n" + "\n" + "See help |all for detailed info\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("scan") ) { out.println( "[]scan [-bin]\n" + " (Re)scan buses and returns the device list. If and -bin are specified\n" + " errors are stored and can be read out using \"errors \". If -bin is not\n" + " specified errors are returned directly.\n" + " -bin print it in (computer friendly) binary format\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("info") ) { out.println( "info \n" + " Returns device capabilities.\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("upload") ) { out.println( "upload [-v] [-nv] [-e] [-f]\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" + " -nv upload to non-volatile memory\n" + " -e erase / disable firmware in non-volatile memory\n" + " -f force upload of incompatible firmware\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("config") ) { out.println( "config [-v] [-nv] [-e] [-f]\n" + " Configure FPGA. Returns errors, if any.\n" + " -v upload to volatile memory (default if -nv is not given)\n" + " -nv upload to non-volatile memory\n" + " -e erase / disable bitstream in non-volatile memory\n" + " -f force upload if already configured\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("read") ) { out.println( "[:]read []\n" + " Read data from endpoint and returns them. If if not specified\n" + " data is read until end. If is specified errors are stored and can be\n" + " read out using \"errors \" \n" ); b=true; } if ( all || cmd.equalsIgnoreCase("write") ) { out.println( "write \n" + " write data to endpoint. Returns errors, if any.\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("errors") ) { out.println( "errors \n" + " Returns errors stored under .\n" ); b=true; } if ( all || cmd.equalsIgnoreCase("quit") ) { out.println( "quit\n" + " Quit Device Server\n" ); b=true; } if ( ! b ) { out.println( "No help available for command " + cmd + "\n"); } } // ******* str2bin ************************************************************* private static void str2bin( String s, byte buf[], int start, int len ) { byte bytes[] = null; int l = 0; if ( s != null ) { bytes = s.getBytes(); l = Math.min(bytes.length,len); } for ( int i=0; i255 ) n=255; out.write(n); for ( int i=0; i: "); } for ( int i=0; i0 ) out.println("Capability: " + s); if ( ztex.config != null ) { out.println("ZTEX Product: " + ztex.config.getName()); out.println("FPGA: " + ztex.config.getFpga()); 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); try { s = ztex.getFpgaConfigurationStr(); out.println("FPGA State: " + s); } catch ( Exception e ) { } if ( eps!=null ) { for ( int i=0; i 0 ) { if ( argsN >= maxArgs ) throw new Exception("Error reading command: Argument buffer overflow"); args[argsN] = new String(buf,0,bufN); argsN+=1; bufN=0; } } else { if ( bufN >= bufSize ) throw new Exception("Error reading command: Buffer overflow"); buf[bufN] = (byte) b; bufN+=1; } } while (b!=10 && b>0); if ( argsN == 0 ) throw new Exception ("Command missed"); } catch (Exception e) { // DeviceServer.error("Error: "+e.getLocalizedMessage() ); try { printer().println("Error: "+e.getLocalizedMessage()); } catch (IOException f) { DeviceServer.error("Error: "+e.getLocalizedMessage() ); } } StringBuilder messages = new StringBuilder(); if ( args[0].indexOf(':') > 0 ) { int i = args[0].lastIndexOf(':'); cid = args[0].substring(0,i); args[0] = args[0].substring(i+1); } // process commands try { // quit if ( args[0].equalsIgnoreCase("quit") ) { DeviceServer.quit = true; } // help [] else if ( args[0].equalsIgnoreCase("help") ) { if ( argsN < 2 ) printHelp("help"); for ( int i=1; i:]scan [-bin] else if ( args[0].equalsIgnoreCase("scan") ) { 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 ) noErrors = true; scan( argsN==2 ); } // info else if ( args[0].equalsIgnoreCase("info") ) { if ( argsN !=3 ) throw new Exception("info: invalid number of parameters" ); info( Integer.valueOf(args[1]), Integer.valueOf(args[2]) ); } // upload [-v] [-nv] [-e] [-f] // config [-v] [-nv] [-e] [-f] else if ( args[0].equalsIgnoreCase("upload") || args[0].equalsIgnoreCase("config") ) { if ( argsN<3 ) throw new Exception(args[0]+": to less parameters" ); boolean vola=false, nonvola=false, erase=false, force=false; for ( int i=3; i " + busIdx + ":" + ndn + "\n"); DeviceServer.scanUSB(); } } else { DeviceServer.loadBitstream ( ztex, messages, in, IPPermissions.toString( socket.getInetAddress() ), force, vola, nonvola, erase ); } } // write else if ( args[0].equalsIgnoreCase("write") ) { if ( argsN !=4 ) throw new Exception("write: invalid number of parameters" ); int busIdx=Integer.valueOf(args[1]); int devNum=Integer.valueOf(args[2]); ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum); if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found"); Ztex1v1 ztex = new Ztex1v1(dev); EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum); try { DeviceServer.epUpload (ztex, eps.find(Integer.valueOf(args[3])), in, messages); } finally { DeviceServer.release(ztex); } } // [:]read [] else if ( args[0].equalsIgnoreCase("read") ) { noErrors = true; if ( argsN<4 || argsN>5 ) throw new Exception("read: invalid number of parameters" ); int busIdx=Integer.valueOf(args[1]); int devNum=Integer.valueOf(args[2]); ZtexDevice1 dev = DeviceServer.findDevice(busIdx, devNum); if ( dev == null ) throw new Exception("Device " + busIdx + ":" + devNum + " not found"); Ztex1v1 ztex = new Ztex1v1(dev); EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum); int max_size = argsN==5 ? Integer.valueOf(args[4]) : Integer.MAX_VALUE; try { DeviceServer.epDownload (ztex, eps.find(Integer.valueOf(args[3])), binOut(), max_size, messages); binOut.flush(); } finally { DeviceServer.release(ztex); } } // error else if ( args[0].equalsIgnoreCase("errors") ) { cid2 = cid; cid = null; if ( argsN > 2 ) throw new Exception("errors: to much parameters" ); if ( argsN == 2 ) cid2 = args[1]; messages = ErrorBuffer.get(cid2); if (messages != null) printer().print( messages ); messages = new StringBuilder(); } else { throw new Exception("Invalid command: "+args[0] ); } } catch ( IOException e) { DeviceServer.error("Error: "+e.getLocalizedMessage() ); } catch (NumberFormatException e) { messages.append("Error: Number expected: "+e.getLocalizedMessage()+"\n"); } catch (Exception e) { messages.append("Error: "+e.getLocalizedMessage()+"\n"); } try { if ( messages != null && messages.length()>0 ) { if ( ! noErrors ) printer().print(messages); ErrorBuffer.add(cid,messages); } } catch ( IOException e) { DeviceServer.error("Error2: "+e.getLocalizedMessage() ); } try { socket.getInputStream().close(); } catch (Exception e) { DeviceServer.error("Error closing input stream: "+e.getLocalizedMessage() ); } try { if ( binOut!=null ) binOut.close(); else if ( printer != null ) printer.close(); } catch (Exception e) { DeviceServer.error("Error closing output stream: "+e.getLocalizedMessage() ); } DeviceServer.removeSocket(socket); try { socket.close(); } catch (Exception e) { DeviceServer.error("Error closing output socket: "+e.getLocalizedMessage() ); } } } // ***************************************************************************** // ******* MultipartFormDataReader ******************************************** // ***************************************************************************** class MultipartFormDataReader { private final byte eol[] = { 13, 10 }; private InputStream in; private byte sep[] = null; private boolean eof = false; public String name = ""; public String fileName = ""; // ******* readTo ************************************************************** private boolean readTo ( OutputStream out, byte s[] ) { byte buf[] = new byte[s.length]; int eq = 0; while ( eq" + new String(sep) + "<--"); } else { readTo( null, eol ); } } catch ( IOException e ) { eof = true; } } while ( sep == null && !eof ); } // ******* readField *********************************************************** public boolean readField ( OutputStream data ) { if ( sep == null ) return false; ByteArrayOutputStream lineBuf = new ByteArrayOutputStream(); String line; name = ""; fileName = ""; do { readTo ( lineBuf, eol ); line = lineBuf.toString(); // System.out.println("line: "+line); int i=0; while ( i=i+19 && line.substring(i,i+19).equalsIgnoreCase("Content-Disposition") ) { String tokens[] = line.split(";"); for ( int j=1; j0 && z>a ) name=t.substring(a+1,z); } s=t.substring(i,i+9); if ( s.equalsIgnoreCase("filename ") || s.equalsIgnoreCase("filename=") ) { int a = t.indexOf("\""); int z = t.lastIndexOf("\""); if ( a>0 && z>a ) fileName=t.substring(a+1,z); } } // System.out.println("name: "+name); // System.out.println("filename: "+fileName); } lineBuf.reset(); } while ( line.length()>0 && !eof ); if ( ! eof ) readTo( data, sep ); boolean result = !eof; try { in.read(); in.read(); } catch ( IOException e ) { eof = true; } return result; } } // ***************************************************************************** // ******* ZtexHttpHandler ***************************************************** // ***************************************************************************** class ZtexHttpHandler implements HttpHandler { // ******* htmlHeader ********************************************************** private StringBuilder htmlHeader ( String title ) { StringBuilder sb = new StringBuilder(); sb.append("\n"); sb.append("\n"); sb.append("\n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append("" + title + "\n"); sb.append("\n"); sb.append("\n"); sb.append("\n"); sb.append("
\n"); sb.append("\n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append ( "
\n"); sb.append(" " + title + "\n"); sb.append("
\n"); return sb; } // ******* heading ************************************************************* private StringBuilder heading ( StringBuilder sb, String s ) { sb.append ( "
\n"); sb.append(" " + s + "\n"); sb.append("
\n"); return sb; } // ******* htmlConvert ********************************************************* private byte[] htmlConvert ( StringBuilder sb ) { sb.append ( "
\n"); sb.append ( "
\n"); sb.append ( "

\n"); sb.append ( "


\n"); sb.append ( "
\n"); sb.append ( " [ZTEX Homepage] \n"); sb.append ( " [ZTEX Wiki] \n"); sb.append ( " © ZTEX GmbH\n"); sb.append ( "
\n"); sb.append ( "" ); return sb.toString().getBytes(); } // ******* test **************************************************************** private byte[] test (HttpExchange t) throws IOException { InputStream in = new BufferedInputStream( t.getRequestBody() ); System.out.println("Request Body: " + in.available() + "Bytes"); int i; do { i = in.read(); if ( i>=0 ) System.out.print((char)i); } while (i>=0); Headers h = t.getResponseHeaders(); h.add("Content-Type", "text/html;Charset=iso-8859-1"); StringBuilder sb = htmlHeader ("Test"); sb.append ("
\n"); sb.append ("

Wählen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:
\n"); sb.append (" \n"); sb.append ("

\n"); sb.append (" Volatile Memory     \n"); sb.append (" Non-Volatile Memory     \n"); sb.append (" \n"); sb.append ("
\n"); return htmlConvert(sb); } // ******* test2 *************************************************************** private byte[] test2 (HttpExchange t) throws IOException { MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) ); ByteArrayOutputStream data = new ByteArrayOutputStream(); while ( form.readField( data ) ) { System.out.println( "Name=\"" + form.name + "\"" ); System.out.println( "Filename=\"" + form.fileName + "\"" ); System.out.println( "Data -->" + data + "<--" ); data.reset(); } Headers h = t.getResponseHeaders(); h.add("Content-Type", "text/html;Charset=iso-8859-1"); StringBuilder sb = htmlHeader ("Test2"); sb.append ("
\n"); sb.append ("

Wählen Sie eine Textdatei (txt, html usw.) von Ihrem Rechner aus:
\n"); sb.append (" \n"); sb.append ("

\n"); sb.append (" Volatile Memory     \n"); sb.append (" Non-Volatile Memory     \n"); sb.append (" \n"); sb.append ("
\n"); return htmlConvert(sb); } // ******* scan **************************************************************** private byte[] scan (HttpExchange t) { DeviceServer.scanUSB(); int n = DeviceServer.numberOfDevices(); Headers h = t.getResponseHeaders(); h.add("Content-Type", "text/html;Charset=iso-8859-1"); StringBuilder sb = htmlHeader ("Device overview"); sb.append ("\n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); sb.append (" \n"); if ( n<1 ) { sb.append(""); } else { for ( int i=0; i\n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); } catch ( IndexOutOfBoundsException e ) { } } } sb.append ("
Device Link /
<Bus Index>:<Device Number>
Bus NameProduct ID'sSerial Number StringManufacturer StringProduct String
(No devices)" + DeviceServer.busIdx(i) + ":" + DeviceServer.devNum(i) + "" + dev.dev().getBus().getDirname() + "" + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "" + ( dev.snString() == null ? "" : dev.snString() ) + "" + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "" + ( dev.productString() == null ? "" : dev.productString() ) + "
\n"); sb.append ("

\n"); sb.append ("\n"); return htmlConvert(sb); } // ******* device ************************************************************** private byte[] device ( HttpExchange t, int busIdx, int devNum, int epnum, ZtexDevice1 dev ) { StringBuilder messages = new StringBuilder(); EPDescriptorVector eps = DeviceServer.getEps(busIdx,devNum); Headers h = t.getResponseHeaders(); // *********** // * request * // *********** boolean fw_force = false; boolean fw_upload_v = false; boolean fw_upload_nv = false; boolean fw_erase = false; ByteArrayInputStream fw_data = null; String fw_data_name = null; boolean bs_force = false; boolean bs_upload_v = false; boolean bs_upload_nv = false; boolean bs_erase = false; byte bs_data[] = null; String bs_data_name = null; ByteArrayInputStream ep_data = null; String ep_data_name = null; int ep_data_num = -1; int ep_down_size = -1; MultipartFormDataReader form = new MultipartFormDataReader( new BufferedInputStream( t.getRequestBody() ) ); ByteArrayOutputStream data = new ByteArrayOutputStream(); while ( form.readField( data ) ) { /* System.out.println( "Name=\"" + form.name + "\"" ); System.out.println( "Filename=\"" + form.fileName + "\"" ); System.out.println( "Data -->" + data + "<--" ); */ if ( data.size()>0 ) { 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_nv" ) ) fw_upload_nv=true; else if ( form.name.equalsIgnoreCase("fw_erase" ) ) fw_erase=true; else if ( form.name.equalsIgnoreCase("fw_data" ) ) { fw_data = new ByteArrayInputStream(data.toByteArray()); 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_upload_v" ) ) bs_upload_v=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_data" ) ) { bs_data = data.toByteArray(); bs_data_name = IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ":" + form.fileName; } else if ( form.name.equalsIgnoreCase("ep_down_size" ) ) { try { ep_down_size = Integer.valueOf(data.toString()); } catch (Exception e) { ep_down_size = -1; } // System.out.println(ep_down_size); } else { for ( int i=0; eps!=null && i " + busIdx + ":" + devNum + "\n"); DeviceServer.scanUSB(); eps = DeviceServer.getEps(busIdx,devNum); } } } catch ( Exception e ) { messages.append( "Error: " + e.getLocalizedMessage() + '\n' ); } try { 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 ) { messages.append( "Error: " + e.getLocalizedMessage() + '\n' ); } try { if ( ep_data != null ) DeviceServer.epUpload (ztex, eps.find(ep_data_num), ep_data, messages); } catch ( Exception e ) { messages.append( "Error: " + e.getLocalizedMessage() + '\n' ); } try { if ( epnum>0 ){ ByteArrayOutputStream out = new ByteArrayOutputStream(); DeviceServer.epDownload (ztex, eps.find(epnum), out, ep_down_size, messages); h.add("Content-Type", "application/octet-stream"); return out.toByteArray(); } } catch ( Exception e ) { messages.append( "Error: " + e.getLocalizedMessage() + '\n' ); } DeviceServer.release (ztex); // ************ // * response * // ************ h.add("Content-Type", "text/html;Charset=iso-8859-1"); StringBuilder sb = htmlHeader ("Device " + busIdx + ":" + devNum + ( devNum!=oldDevNum ? ( " (was " + busIdx + ":" + oldDevNum +")" ) : "" ) ); // info sb.append ("\n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); sb.append(" \n"); if ( ztex != null ) { String s = ztex.capabilityInfo(", "); if ( s.length()>0 ) sb.append(" \n"); if ( ztex.config != null ) { sb.append(" \n"); sb.append(" \n"); if (ztex.config.getRamSize()>0) sb.append(" \n"); s = ztex.flashInfo(); if ( s.length()>0 ) sb.append(" \n"); } try { s = ztex.getFpgaConfigurationStr(); sb.append(" \n"); } catch ( Exception e ) { } } sb.append ("
Bus name: " + dev.dev().getBus().getDirname() + "
Device Number: " + devNum + "
USB ID's: " + Integer.toHexString(dev.usbVendorId()) + ":" + Integer.toHexString(dev.usbProductId()) + "
Product ID's: " + ( dev.valid() ? ( ZtexDevice1.byteArrayString(dev.productId()) ) : "(unconfigured)" ) + "
Firmware version: " + ( dev.valid() ? (dev.fwVersion() & 255) : "" ) + "
Serial Number String: " + ( dev.snString() == null ? "" : dev.snString() ) + "
Manufacturer String: " + ( dev.manufacturerString() == null ? "" : dev.manufacturerString() ) + "
Product String: " + ( dev.productString() == null ? "" : dev.productString() ) + "
Capabilities: " + s + "
ZTEX Product: " + ztex.config.getName() + "
FPGA: " + ztex.config.getFpga() + "
RAM: " + (ztex.config.getRamSize() >> 20) + " MByte " + ztex.config.getRamType() + "
Flash: " + s + "
FPGA State: " + s + "
\n"); sb.append ("

\n"); // firmware heading(sb,"Firmware Upload"); sb.append ("

\n"); sb.append ("
\n"); sb.append (" Firmware file:

\n"); sb.append (" Upload to volatile Memory     \n"); // try { // if ( ztex != null ) { // ztex.checkCapability(ztex.CAPABILITY_EEPROM); sb.append (" Upload to non-Volatile Memory     \n"); sb.append (" Erase firmware in non-volatile memory"); // } // } // catch ( Exception a ) { // } sb.append (" Enforce upload

"); sb.append (" (Before firmware can be loaded into non-volatile memory some firmware must be installed in volatile memory.)

\n"); sb.append ("

\n"); sb.append (" \n"); sb.append ("
\n"); // bitstream try { if ( ztex == null ) throw new Exception(); ztex.checkCapability(ztex.CAPABILITY_FPGA); heading(sb,"Bitstream Upload"); sb.append ("
\n"); sb.append ("
\n"); sb.append (" Bitstream file:

\n"); sb.append (" Upload to volatile Memory     \n"); try { if ( ztex != null && ztex.flashEnabled() ) { sb.append (" Upload to non-Volatile Memory     \n"); sb.append (" Erase bitstream in non-volatile memory"); } } catch ( Exception a ) { } sb.append (" Enforce upload

"); sb.append ("

\n"); sb.append (" \n"); sb.append ("
\n"); } catch ( Exception a ) { } // endpoints if ( eps!=null && eps.size()>0) { heading(sb,"Endpoints"); sb.append ("\n"); for (int i=0; i\n" ); } else { sb.append(" \n" ); } } sb.append ("
IN EP " + ep.num() +": " + "
" + "Maximum size: " + "    " + "
OUT EP " + ep.num() +": " + "
" + "File: " + "    " + "
\n"); } // messages if ( messages.length() > 0 ) { heading(sb,"Messages"); sb.append ("
\n");
	    sb.append(messages);
	    sb.append ("
"); } return htmlConvert(sb); } // ******* handle ************************************************************** public void handle(HttpExchange t) throws IOException { String path = t.getRequestURI().getPath(); int responseCode = 200; byte buf[] = {}; if ( path.charAt(0) != '/' ) path = '/' + path; int rcvd = t.getRequestBody().available(); if ( ! DeviceServer.httpPermissions().checkAddress( t.getRemoteAddress().getAddress() ) ) { responseCode = 400; StringBuilder sb = htmlHeader ("400 Bad Request"); sb.append("Access denied" ); buf = htmlConvert(sb); } /* else if ( path.equalsIgnoreCase("/test") ) { buf = test(t); } else if ( path.equalsIgnoreCase("/test2") ) { buf = test2(t); } */ else if ( path.equalsIgnoreCase("/") || path.equalsIgnoreCase("/scan") ) { buf = scan(t); } else if ( path.indexOf(':') > 0 ) { try { int i = path.indexOf(':'); int j = path.lastIndexOf(':'); if (j<=i) j=path.length(); int busIdx = Integer.valueOf(path.substring(1,i)); int devNum = Integer.valueOf(path.substring(i+1,j )); int epNum = j < path.length() ? Integer.valueOf(path.substring(j+1)) : -1; ZtexDevice1 dev = DeviceServer.findDevice(busIdx,devNum); if ( dev == null ) throw new Exception(); buf = device(t, busIdx, devNum, epNum, dev); } catch ( Exception e ) { responseCode = 400; StringBuilder sb = htmlHeader ("400 Bad Request"); sb.append("Invalid device path: " + path ); sb.append ("

\n"); sb.append ("\n"); buf = htmlConvert(sb); } } else { responseCode = 404; StringBuilder sb = htmlHeader ("404 Not Found"); sb.append("Invalid path: " + path ); sb.append ("

\n"); sb.append ("\n"); buf = htmlConvert(sb); } DeviceServer.info( "Connection from " + IPPermissions.toString( t.getRemoteAddress().getAddress() ) + ": " + path + ": " + responseCode + ": received " + rcvd + " bytes, sent " + buf.length + " bytes" ); t.sendResponseHeaders(responseCode, buf.length); OutputStream os = t.getResponseBody(); os.write(buf); os.close(); } } // ***************************************************************************** // ******* IPPermissionList **************************************************** // ***************************************************************************** class IPPermissions { private byte ip[][] = { { 127, 0, 0, 1 } }; private boolean deny[] = { false }; private int mask[] = { 32 }; public IPPermissions(String adrs) throws UnknownHostException,IllegalArgumentException { String strs[] = adrs.split(","); ip = new byte[strs.length][]; deny = new boolean[strs.length]; mask = new int[strs.length]; for (int i=0; i>k == (rip[j] & 255)>>k ); } if ( eq ) allow = ! deny[i]; } } return allow; } public boolean checkAddress ( InetAddress adr ) { return checkAddress( adr.getAddress() ); } public static String toString(byte ip[]) { StringBuilder sb = new StringBuilder(); if ( ip.length<6 || (ip.length & 1) != 0 ) { for (int i=0; i0) sb.append('.'); sb.append(ip[i] & 255); } } else { for (int i=0; i+10) sb.append(':'); sb.append(Integer.toString( ((ip[i] & 255)<<8) | (ip[i+1] & 255), 16 ) ); } } return sb.toString(); } public static String toString(InetAddress adr) { return toString( adr.getAddress() ); } public String toString() { StringBuilder sb = new StringBuilder(); for (int i=0; i0) sb.append(','); if (deny[i]) sb.append('-'); sb.append(toString(ip[i])+"/"+mask[i]); } return sb.toString(); } } // ***************************************************************************** // ******* EPDescriptor ******************************************************** // ***************************************************************************** class EPDescriptor { private boolean in, bulk; public int num; public int size; public EPDescriptor ( boolean p_in, int p_num, boolean p_bulk, int p_size ) { in = p_in; num = p_num; bulk = p_bulk; size = p_size; // System.out.println((in ? "IN" : "OUT" ) + " EP "+num + ": " + (bulk ? "BULK" : "INT" ) + ", " + size); } public boolean in () { return in; } public int num () { return num; } public boolean bulk () { return bulk; } public int size () { return size; } } // ***************************************************************************** // ******* EPDescriptorVector ************************************************** // ***************************************************************************** class EPDescriptorVector extends Vector { public EPDescriptor find(int num) { for (int i=0; i socketVector = new Vector(); private static boolean verbose = false; private static boolean quiet = false; private static PrintStream logFile = null; private static PrintStream log2File = null; private static IPPermissions httpPermissions = new IPPermissions(); private static IPPermissions socketPermissions = new IPPermissions(); private static String httpBind = null, socketBind = null; private static ZtexScanBus1 scanBus; private static int busIdx[]; private static int devNum[]; private static int confNum[]; private static EPDescriptorVector eps[]; private static Vector dirnameDB = new Vector(); // ******* addSocket *********************************************************** public synchronized static void addSocket( Socket socket ) { info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " established" ); socketVector.addElement(socket); } // ******* removeSocket ******************************************************** public synchronized static void removeSocket(Socket socket) { info( "Connection from " + IPPermissions.toString( socket.getInetAddress() ) + " closed" ); socketVector.remove(socket); } // ******* httpPermissions ***************************************************** public static IPPermissions httpPermissions() { return httpPermissions; } // ******* sleep *************************************************************** public static void sleep(int ms) { try { Thread.sleep(ms); } catch ( InterruptedException e ) { } } // ******* info **************************************************************** public synchronized static void info (String msg) { if ( verbose ) System.err.println( msg ); if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg ); } // ******* error *************************************************************** public synchronized static void error (String msg) { if ( ! quiet ) System.err.println( msg ); if ( logFile != null ) logFile.println( msgDateFormat.format(new Date()) + ": " + msg ); if ( log2File != null ) log2File.println( msgDateFormat.format(new Date()) + ": " + msg ); } // ******* getDirnameNum ******************************************************* public static int getDirnameIdx ( String dirname ) { if ( dirname == null ) return -1; for ( int i=0; i 0 ) { busIdx = new int[n]; devNum = new int[n]; confNum = new int[n]; eps = new EPDescriptorVector[n]; for ( int i=0; i0) out.write(buf,0,i); } while (i>0); loadBitstream(ztex, messages, out.toByteArray(), inName, force, toVolatile, toNonVolatile, eraseFlash); } // ******* claim *************************************************************** public synchronized static void claim ( Ztex1v1 ztex, StringBuilder messages ) { int c = 1; for (int i=0; i0 ) 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); 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"); } // ******* epDownload ********************************************************** public synchronized static void epDownload ( Ztex1v1 ztex, EPDescriptor ep, OutputStream out, int maxSize, StringBuilder messages ) throws Exception { if ( ztex == null ) return; if ( ep == null || ! ep.in() ) throw new UsbException(ztex.dev().dev(), "No valid endpoint defined"); if ( maxSize < 1 ) maxSize = Integer.MAX_VALUE; claim(ztex,messages); int bufSize = ep.num()==1 ? 64 : 256*1024; byte buf[] = new byte[bufSize]; int r,i; int j=0; do { r = Math.min(bufSize,maxSize); 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); if (i>0) out.write(buf,0,i); // System.out.println("r: "+i); j++; } while (maxSize>0 && r==i); if (i<0) throw new UsbException("Read error: " + LibusbJava.usb_strerror()); } // ******* numberOfDevices ***************************************************** public synchronized static int numberOfDevices() { return scanBus.numberOfDevices(); } // ******* device ************************************************************** public synchronized static ZtexDevice1 device (int i) throws IndexOutOfBoundsException { return scanBus.device(i); } // ******* findDevice ********************************************************** public synchronized static ZtexDevice1 findDevice (int b, int d) { int n = numberOfDevices(); for ( int i=0; i=busIdx.length) throw new IndexOutOfBoundsException( "Device number out of range. Valid numbers are 0.." + (busIdx.length-1) ); return busIdx[i]; } // ******* devNum ************************************************************** 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) ); return devNum[i]; } // ******* getEps ************************************************************* public synchronized static EPDescriptorVector getEps (int b, int d) { int n = numberOfDevices(); for ( int i=0; i Scan for devices with given Vendor ID and Product ID\n"+ " -sp Port number for the socket interface (default: 9081; <0: disabled)\n"+ " -hp Port number for the HTTP interface (default: 9080; <0: disabled)\n"+ " -sa [-]

[/][,...] Allow (permit if '-' is given) HTTP connection from this address(es),\n"+ " 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+ " -ha [-]
[/][,...] Allow (permit if '-' is given) HTTP connection from this address(es),\n"+ " 24 is equivalent to 255.255.255.0, default: 127.0.0.1\n"+ " -sb
Bind socket server to this address (default: listen on all interfaces)\n"+ " -hb
Bind HTTP server to this address (default: listen on all interfaces)\n"+ " -v Be verbose\n"+ " -q Be quiet\n"+ " -l Log file\n"+ " -l2 Verbose log file\n"+ " -h Help" ); // process parameters try { for (int i=0; i=args.length) throw new Exception(); usbVendorId = Integer.decode( args[i] ); } catch (Exception e) { System.err.println("Error: Vendor ID expected after -id"); System.err.println(helpMsg); System.exit(1); } i++; try { if (i>=args.length) throw new Exception(); usbProductId = Integer.decode( args[i] ); } catch (Exception e) { System.err.println("Error: Product ID expected after -id "); System.err.println(helpMsg); System.exit(1); } } else if ( args[i].equals("-hp") ) { i++; try { if (i>=args.length) throw new Exception(); httpPort = Integer.parseInt( args[i] ); } catch (Exception e) { System.err.println("Error: Port number expected after -hp"); System.err.println(helpMsg); System.exit(1); } } else if ( args[i].equals("-sp") ) { i++; try { if (i>=args.length) throw new Exception(); socketPort = Integer.parseInt( args[i] ); } catch (Exception e) { System.err.println("Error: Port number expected after -sp"); System.err.println(helpMsg); System.exit(1); } } else if ( args[i].equals("-ha") ) { i++; try { if (i>=args.length) throw new Exception("Argument expected after -ha"); httpPermissions = new IPPermissions( args[i] ); } catch (Exception e) { System.err.println("Error parsing HTTP permissions:"); System.exit(1); } } else if ( args[i].equals("-sa") ) { i++; try { if (i>=args.length) throw new Exception("Argument expected after -hs"); socketPermissions = new IPPermissions( args[i] ); } catch (Exception e) { System.err.println("Error parsing socket permissions:"); System.exit(1); } } else if ( args[i].equals("-hb") ) { i++; try { if (i>=args.length) throw new Exception("Argument expected after -hb"); httpBind = args[i]; } catch (Exception e) { System.err.println("Error parsing HTTP permissions:"); System.exit(1); } } else if ( args[i].equals("-sb") ) { i++; try { if (i>=args.length) throw new Exception("Argument expected after -sb"); socketBind = args[i]; } catch (Exception e) { System.err.println("Error parsing HTTP permissions:"); System.exit(1); } } else if ( args[i].equals("-hb") ) { i++; try { if (i>=args.length) throw new Exception("Argument expected after -hb"); httpBind = args[i]; } catch (Exception e) { System.err.println("Error parsing HTTP permissions:"); System.exit(1); } } else if ( args[i].equals("-v") ) { verbose = true; } else if ( args[i].equals("-q") ) { quiet = true; } else if ( args[i].equals("-l") ) { i++; if (i>=args.length) { System.err.println("Error: File name expected after `-l'"); System.err.println(helpMsg); System.exit(1); } try { logFile = new PrintStream ( new FileOutputStream ( args[i], true ), true ); } catch (Exception e) { System.err.println("Error: File name expected after `-l': "+e.getLocalizedMessage() ); System.err.println(helpMsg); System.exit(1); } } else if ( args[i].equals("-l2") ) { i++; if (i>=args.length) { System.err.println("Error: File name expected after `-l2'"); System.err.println(helpMsg); System.exit(1); } try { log2File = new PrintStream ( new FileOutputStream ( args[i], true ), true ); } catch (Exception e) { System.err.println("Error: File name expected after `-l2': "+e.getLocalizedMessage() ); System.err.println(helpMsg); System.exit(1); } } else if ( args[i].equals("-h") ) { System.err.println(helpMsg); System.exit(0); } else { System.err.println("Error: Invalid option: `"+args[i]+"'"); System.err.println(helpMsg); System.exit(1); } } if ( httpPort < 0 && socketPort < 0 ) { error("neither HTTP nor socket interface enabled: exiting"); System.exit(0); } // init USB stuff LibusbJava.usb_init(); LibusbJava.usb_find_busses(); Usb_Bus bus = LibusbJava.usb_get_busses(); while ( bus != null ) { getDirnameIdx(bus.getDirname()); bus = bus.getNext(); } scanUSB(); // start http server HttpServer httpServer = null; if ( httpPort > 0 ) { 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.createContext("/", new ZtexHttpHandler()); httpServer.setExecutor(null); httpServer.start(); } // run socket server if ( socketPort > 0 ) { 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)); ss.setSoTimeout(500); while ( ! quit ) { if ( socketVector.size() < maxConnections ) { try { Socket cs = ss.accept(); if ( socketPermissions.checkAddress( cs.getInetAddress() ) ) { new SocketThread( cs ); } else { info( "Connection from " + IPPermissions.toString( cs.getInetAddress() ) + " refused" ); } } catch ( SocketTimeoutException e ) { } } else { sleep(1000); } } } else { while ( ! quit ) { sleep(1000); } } // stop http server if ( httpServer!=null ) httpServer.stop(1); } catch (Exception e) { error("Error: "+e.getLocalizedMessage() ); } } }

Error running this command: diff -w -U 5 "/tmp/50HK63" ""

diff: : No such file or directory