From: rincon Date: Fri, 18 May 2007 18:27:03 +0000 (+0000) Subject: Previously, the serial forwarder would only release the COM port on exit. Now it... X-Git-Tag: release_tools_1_2_4_1~183 X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=commitdiff_plain;h=269e688e93ce8181515bf8df604c77f3fc6d6760;p=tinyos-2.x.git Previously, the serial forwarder would only release the COM port on exit. Now it provides the ability to temporarily release or reconnect to the COM port when you close/open your source. The SF GUI demonstrates this ability when you connect to your mote, stop the server and verify you can reprogram your mote at that time, restart the sf server and verify you can continue communicating with that mote... all without closing down your serial forwarder. --- diff --git a/support/sdk/java/net/tinyos/comm/NativeSerial.java b/support/sdk/java/net/tinyos/comm/NativeSerial.java index 6b370c23..d775820b 100644 --- a/support/sdk/java/net/tinyos/comm/NativeSerial.java +++ b/support/sdk/java/net/tinyos/comm/NativeSerial.java @@ -1,3 +1,6 @@ + +package net.tinyos.comm; + /* ---------------------------------------------------------------------------- * This file was automatically generated by SWIG (http://www.swig.org). * Version: 1.3.21 @@ -6,18 +9,65 @@ * the SWIG interface file instead. * ----------------------------------------------------------------------------- */ -package net.tinyos.comm; - +/** + * Updated to include the open() method, which allows us to keep this + * object while being temporarily disconnected from the serial port + */ public class NativeSerial { + + /** The handle to the serial port we're connected to */ private long swigCPtr; - protected boolean swigCMemOwn; - - protected NativeSerial(long cPtr, boolean cMemoryOwn) { + + /** True if we have an open serial port connection */ + private boolean swigCMemOwn; + + /** Name of the port */ + private String myPortname = ""; + + + /** + * Constructor + * @param portname + */ + public NativeSerial(String portname) { + this(TOSCommJNI.new_NativeSerial(portname), true); + } + + /** + * Constructor + * @param cPtr + * @param cMemoryOwn + */ + private NativeSerial(long cPtr, boolean cMemoryOwn) { swigCMemOwn = cMemoryOwn; swigCPtr = cPtr; } + + /** + * Reconnect to this serial port + * @return true if the connection is made + */ + public boolean open() { + if(!swigCMemOwn && !myPortname.matches("")) { + swigCPtr = TOSCommJNI.new_NativeSerial(myPortname); + swigCMemOwn = true; + return true; + } + + return false; + } + + public void close() { + // We can come here with swigCptr == 0 from finalize if the C++ + // constructor throws an exception. Ideally, we should guard all + // methods in the C++ code, but this is simpler. + if (swigCPtr != 0) { + TOSCommJNI.NativeSerial_close(swigCPtr); + } + } + protected NativeSerial() { this(0, false); } @@ -67,7 +117,11 @@ public class NativeSerial { } public boolean waitForEvent() { - return TOSCommJNI.NativeSerial_waitForEvent(swigCPtr); + try { + return TOSCommJNI.NativeSerial_waitForEvent(swigCPtr); + } catch (Exception e) { + return false; + } } public boolean cancelWait() { @@ -114,20 +168,14 @@ public class NativeSerial { TOSCommJNI.NativeSerial_sendBreak(swigCPtr, millis); } - public NativeSerial(String portname) { - this(TOSCommJNI.new_NativeSerial(portname), true); - } - public void close() { - // We can come here with swigCptr == 0 from finalize if the C++ - // constructor throws an exception. Ideally, we should guard all - // methods in the C++ code, but this is simpler. - if (swigCPtr != 0) - TOSCommJNI.NativeSerial_close(swigCPtr); - } public int available() { - return TOSCommJNI.NativeSerial_available(swigCPtr); + try { + return TOSCommJNI.NativeSerial_available(swigCPtr); + } catch (Exception e) { + return 0; + } } public int read() { diff --git a/support/sdk/java/net/tinyos/comm/SerialPort.java b/support/sdk/java/net/tinyos/comm/SerialPort.java index 995959c6..89e40502 100644 --- a/support/sdk/java/net/tinyos/comm/SerialPort.java +++ b/support/sdk/java/net/tinyos/comm/SerialPort.java @@ -1,5 +1,7 @@ //$Id$ +package net.tinyos.comm; + /* "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. * @@ -22,7 +24,6 @@ //@author Cory Sharp -package net.tinyos.comm; import java.io.*; @@ -43,8 +44,10 @@ public interface SerialPort public InputStream getInputStream() throws IOException; public OutputStream getOutputStream() throws IOException; + public boolean open(); public void close(); - + public void finalize(); + public void setSerialPortParams( int baudrate, int dataBits, int stopBits, boolean parity ) throws UnsupportedCommOperationException; diff --git a/support/sdk/java/net/tinyos/comm/TOSSerial.java b/support/sdk/java/net/tinyos/comm/TOSSerial.java index ee292c52..5fbac78b 100644 --- a/support/sdk/java/net/tinyos/comm/TOSSerial.java +++ b/support/sdk/java/net/tinyos/comm/TOSSerial.java @@ -21,158 +21,153 @@ */ //@author Cory Sharp - package net.tinyos.comm; import java.io.*; import java.util.*; import java.util.regex.*; -public class TOSSerial extends NativeSerial implements SerialPort -{ - class EventDispatcher extends Thread - { +public class TOSSerial extends NativeSerial implements SerialPort { + + class EventDispatcher extends Thread { boolean m_run; - public EventDispatcher() - { + public EventDispatcher() { m_run = true; } - void dispatch_event( int event ) - { - if( didEventOccur(event) ) - { - SerialPortEvent ev = new SerialPortEvent( TOSSerial.this, event ); - synchronized(m_listeners) { + public void open() { + synchronized (this) { + this.notify(); + m_run = true; + } + } + + public void close() { + m_run = false; + cancelWait(); + } + + private void dispatch_event(int event) { + if (didEventOccur(event)) { + SerialPortEvent ev = new SerialPortEvent(TOSSerial.this, event); + synchronized (m_listeners) { Iterator i = m_listeners.iterator(); - while( i.hasNext() ) - ((SerialPortListener)i.next()).serialEvent( ev ); + while (i.hasNext()) + ((SerialPortListener) i.next()).serialEvent(ev); } } } - public void run() - { - while( m_run ) - { - if( waitForEvent() ) - { - if( m_run ) - { - dispatch_event( SerialPortEvent.BREAK_INTERRUPT ); - dispatch_event( SerialPortEvent.CARRIER_DETECT ); - dispatch_event( SerialPortEvent.CTS ); - dispatch_event( SerialPortEvent.DATA_AVAILABLE ); - dispatch_event( SerialPortEvent.DSR ); - dispatch_event( SerialPortEvent.FRAMING_ERROR ); - dispatch_event( SerialPortEvent.OVERRUN_ERROR ); - dispatch_event( SerialPortEvent.OUTPUT_EMPTY ); - dispatch_event( SerialPortEvent.PARITY_ERROR ); - dispatch_event( SerialPortEvent.RING_INDICATOR ); - } - } + public void run() { + while (true) { + + synchronized (this) { + if (!m_run) { + try { + this.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + if (waitForEvent()) { + dispatch_event(SerialPortEvent.BREAK_INTERRUPT); + dispatch_event(SerialPortEvent.CARRIER_DETECT); + dispatch_event(SerialPortEvent.CTS); + dispatch_event(SerialPortEvent.DATA_AVAILABLE); + dispatch_event(SerialPortEvent.DSR); + dispatch_event(SerialPortEvent.FRAMING_ERROR); + dispatch_event(SerialPortEvent.OVERRUN_ERROR); + dispatch_event(SerialPortEvent.OUTPUT_EMPTY); + dispatch_event(SerialPortEvent.PARITY_ERROR); + dispatch_event(SerialPortEvent.RING_INDICATOR); + } } } - public void close() - { - m_run = false; - cancelWait(); - } } - - class SerialInputStream extends InputStream - { + class SerialInputStream extends InputStream { ByteQueue bq = new ByteQueue(128); - protected void gather() - { + protected void gather() { int navail = TOSSerial.this.available(); - if( navail > 0 ) - { + if (navail > 0) { byte buffer[] = new byte[navail]; - bq.push_back( buffer, 0, TOSSerial.this.read( buffer, 0, navail ) ); + bq.push_back(buffer, 0, TOSSerial.this.read(buffer, 0, navail)); } } - public int read() - { + public int read() { gather(); return bq.pop_front(); } - public int read( byte[] b ) - { + public int read(byte[] b) { gather(); return bq.pop_front(b); } - public int read( byte[] b, int off, int len ) - { + public int read(byte[] b, int off, int len) { gather(); - return bq.pop_front(b,off,len); + return bq.pop_front(b, off, len); } - public int available() - { + public int available() { gather(); return bq.available(); } } - - class SerialOutputStream extends OutputStream - { - public void write( int b ) - { + class SerialOutputStream extends OutputStream { + public void write(int b) { TOSSerial.this.write(b); } - public void write( byte[] b ) - { - TOSSerial.this.write(b,0,b.length); + public void write(byte[] b) { + TOSSerial.this.write(b, 0, b.length); } - public void write( byte[] b, int off, int len ) - { + public void write(byte[] b, int off, int len) { int nwritten = 0; - while( nwritten < len ) - nwritten += TOSSerial.this.write( b, nwritten, len-nwritten ); + while (nwritten < len) + nwritten += TOSSerial.this.write(b, nwritten, len - nwritten); } } + private SerialInputStream m_in; + + private SerialOutputStream m_out; - SerialInputStream m_in; - SerialOutputStream m_out; - Vector m_listeners = new Vector(); - EventDispatcher m_dispatch; + private Vector m_listeners = new Vector(); - static String map_portname( String mapstr, String portname ) - { + private EventDispatcher m_dispatch; + + static String map_portname(String mapstr, String portname) { // mapstr is of the form "from1=to1:from2=to2" // If "from", "to", and "portname" all end port numbers, then the ports in // "from" and "to" are used as a bias for the port in "portname", appended - // to the "to" string (without its original terminating digits). If more + // to the "to" string (without its original terminating digits). If more // than one port mapping matches, the one with the smallest non-negative // port number wins. // For instance, if - // mapstr="com1=COM1:com10=\\.\COM10" + // mapstr="com1=COM1:com10=\\.\COM10" // then - // com1 => COM1 - // com3 => COM3 - // com10 => \\.\COM10 - // com12 => \\.\COM12 + // com1 => COM1 + // com3 => COM3 + // com10 => \\.\COM10 + // com12 => \\.\COM12 // or if - // mapstr="com1=/dev/ttyS0:usb1=/dev/ttyS100" + // mapstr="com1=/dev/ttyS0:usb1=/dev/ttyS100" // then - // com1 => /dev/ttyS0 - // com3 => /dev/ttyS2 - // usb1 => /dev/ttyS100 - // usb3 => /dev/ttyS102 + // com1 => /dev/ttyS0 + // com3 => /dev/ttyS2 + // usb1 => /dev/ttyS100 + // usb3 => /dev/ttyS102 String maps[] = mapstr.split(":"); Pattern pkv = Pattern.compile("(.*?)=(.*?)"); @@ -182,111 +177,122 @@ public class TOSSerial extends NativeSerial implements SerialPort int match_distance = -1; String str_port_to = null; - for( int i=0; i= 0) && ((ndist < match_distance) || (match_distance == -1)) ) - { - match_distance = ndist; - str_port_to = mto.group(1) + nport_to; - } - } - else if( mkv.group(1).equalsIgnoreCase( portname ) ) - { - match_distance = 0; - str_port_to = mkv.group(2); - } + for (int i = 0; i < maps.length; i++) { + Matcher mkv = pkv.matcher(maps[i]); + if (mkv.matches()) { + Matcher mfrom = pnum.matcher(mkv.group(1)); + Matcher mto = pnum.matcher(mkv.group(2)); + if (mfrom.matches() && mto.matches() && mport.matches() + && mfrom.group(1).equalsIgnoreCase(mport.group(1))) { + int nfrom = Integer.parseInt(mfrom.group(2)); + int nto = Integer.parseInt(mto.group(2)); + int nport_from = Integer.parseInt(mport.group(2)); + int nport_to = nport_from - nfrom + nto; + int ndist = nport_from - nfrom; + + if ((ndist >= 0) + && ((ndist < match_distance) || (match_distance == -1))) { + match_distance = ndist; + str_port_to = mto.group(1) + nport_to; + } + } else if (mkv.group(1).equalsIgnoreCase(portname)) { + match_distance = 0; + str_port_to = mkv.group(2); + } } } return (str_port_to == null) ? portname : str_port_to; } - public TOSSerial( String portname ) - { - super( map_portname( NativeSerial.getTOSCommMap(), portname ) ); + public TOSSerial(String portname) { + super(map_portname(NativeSerial.getTOSCommMap(), portname)); m_in = new SerialInputStream(); m_out = new SerialOutputStream(); m_dispatch = new EventDispatcher(); m_dispatch.start(); } + + /** + * Open the serial port connection + */ + public boolean open() { + if (m_dispatch != null) { + m_dispatch.open(); + } + return super.open(); + } + + /** + * Close the serial port connection + */ + public void close() { + if(m_dispatch != null) { + m_dispatch.close(); + } + super.close(); + } - public void addListener( SerialPortListener l ) - { - synchronized(m_listeners) { - if( !m_listeners.contains(l) ) + public void addListener(SerialPortListener l) { + synchronized (m_listeners) { + if (!m_listeners.contains(l)) m_listeners.add(l); } } - public void removeListener( SerialPortListener l ) - { - synchronized(m_listeners) { + public void removeListener(SerialPortListener l) { + synchronized (m_listeners) { m_listeners.remove(l); } } - public InputStream getInputStream() - { + public InputStream getInputStream() { return m_in; } - public OutputStream getOutputStream() - { + public OutputStream getOutputStream() { return m_out; } - public void close() - { - if( m_dispatch != null ) + /** + * Finalize the serial port connection, do not expect to open it + * again + */ + public void finalize() { + // Be careful what you call here. The object may never have been + // created, so the underlying C++ object may not exist, and there's + // insufficient guarding to avoid a core dump. If you call other + // methods than super.close() or super.finalize(), be sure to + // add an if (swigCptr != 0) guard in NativeSerial.java. + if (m_dispatch != null) { m_dispatch.close(); + } - try { if( m_dispatch != null ) m_dispatch.join(); } - catch( InterruptedException e ) { } + /* + try { + if (m_dispatch != null) { + m_dispatch.join(); + } + } catch (InterruptedException e) { + } + */ super.close(); - try - { - if( m_in != null ) - m_in.close(); + try { + if (m_in != null) { + m_in.close(); + } - if( m_out != null ) - m_out.close(); - } - catch( IOException e ) - { + if (m_out != null) { + m_out.close(); + } + } catch (IOException e) { } m_dispatch = null; m_in = null; m_out = null; - } - - protected void finalize() - { - // Be careful what you call here. The object may never have been - // created, so the underlying C++ object may not exist, and there's - // insufficient guarding to avoid a core dump. If you call other - // methods than super.close() or super.finalize(), be sure to - // add an if (swigCptr != 0) guard in NativeSerial.java. - System.out.println("Java TOSSerial finalize"); - close(); super.finalize(); } } - diff --git a/support/sdk/java/net/tinyos/packet/Packetizer.java b/support/sdk/java/net/tinyos/packet/Packetizer.java index d27ff284..eec1498a 100644 --- a/support/sdk/java/net/tinyos/packet/Packetizer.java +++ b/support/sdk/java/net/tinyos/packet/Packetizer.java @@ -36,334 +36,339 @@ import java.util.*; import java.nio.*; /** - * The Packetizer class implements the new mote-PC protocol, using - * a ByteSource for low-level I/O + * The Packetizer class implements the new mote-PC protocol, using a ByteSource + * for low-level I/O */ public class Packetizer extends AbstractSource implements Runnable { - /* Protocol inspired by, but not identical to, RFC 1663. - * There is currently no protocol establishment phase, and a single - * byte ("packet type") to identify the kind/target/etc of each packet. - * - * The protocol is really, really not aiming for high performance. - * - * There is however a hook for future extensions: implementations are - * required to answer all unknown packet types with a P_UNKNOWN packet. - * - * To summarise the protocol: - * - the two sides (A & B) are connected by a (potentially unreliable) - * byte stream - * - the two sides exchange packets framed by 0x7e (SYNC_BYTE) bytes - * - each packet has the form - * <16-bit crc> - * where the crc (see net.tinyos.util.Crc) covers the packet type - * and bytes 1..n - * - bytes can be escaped by preceding them with 0x7d and their - * value xored with 0x20; 0x7d and 0x7e bytes must be escaped, - * 0x00 - 0x1f and 0x80-0x9f may be optionally escaped - * - There are currently 5 packet types: - * P_PACKET_NO_ACK: A user-packet, with no ack required - * P_PACKET_ACK: A user-packet with a prefix byte, ack required. - * The receiver must send a P_ACK packet with the prefix byte - * as its contents. - * P_ACK: ack for a previous P_PACKET_ACK packet - * P_UNKNOWN: unknown packet type received. On reception of an - * unknown packet type, the receicer must send a P_UNKNOWN packet, - * the first byte must be the unknown packet type. - * - Packets that are greater than a (private) MTU are silently dropped. - */ - final static boolean DEBUG = false; - - final static int SYNC_BYTE = Serial.HDLC_FLAG_BYTE; - final static int ESCAPE_BYTE = Serial.HDLC_CTLESC_BYTE; - final static int MTU = 256; - final static int ACK_TIMEOUT = 1000; // in milliseconds - - final static int P_ACK = Serial.SERIAL_PROTO_ACK; - final static int P_PACKET_ACK = Serial.SERIAL_PROTO_PACKET_ACK; - final static int P_PACKET_NO_ACK = Serial.SERIAL_PROTO_PACKET_NOACK; - final static int P_UNKNOWN = Serial.SERIAL_PROTO_PACKET_UNKNOWN; - - private ByteSource io; - private boolean inSync; - private byte[] receiveBuffer = new byte[MTU]; - private int seqNo; - - // Packets are received by a separate thread and placed in a - // per-packet-type queue. If received[x] is null, then x is an - // unknown protocol (but P_UNKNOWN and P_PACKET_ACK are handled - // specially) - private Thread reader; - private LinkedList[] received; - - /** - * Packetizers are built using the makeXXX methods in BuildSource - */ - Packetizer(String name, ByteSource io) { - super(name); - this.io = io; - inSync = false; - seqNo = 13; - reader = new Thread(this); - received = new LinkedList[256]; - received[P_ACK] = new LinkedList(); - received[P_PACKET_NO_ACK] = new LinkedList(); - } + /* + * Protocol inspired by, but not identical to, RFC 1663. There is currently no + * protocol establishment phase, and a single byte ("packet type") to identify + * the kind/target/etc of each packet. + * + * The protocol is really, really not aiming for high performance. + * + * There is however a hook for future extensions: implementations are required + * to answer all unknown packet types with a P_UNKNOWN packet. + * + * To summarise the protocol: - the two sides (A & B) are connected by a + * (potentially unreliable) byte stream - the two sides exchange packets + * framed by 0x7e (SYNC_BYTE) bytes - each packet has the form + * <16-bit crc> where the crc (see net.tinyos.util.Crc) + * covers the packet type and bytes 1..n - bytes can be escaped by preceding + * them with 0x7d and their value xored with 0x20; 0x7d and 0x7e bytes must be + * escaped, 0x00 - 0x1f and 0x80-0x9f may be optionally escaped - There are + * currently 5 packet types: P_PACKET_NO_ACK: A user-packet, with no ack + * required P_PACKET_ACK: A user-packet with a prefix byte, ack required. The + * receiver must send a P_ACK packet with the prefix byte as its contents. + * P_ACK: ack for a previous P_PACKET_ACK packet P_UNKNOWN: unknown packet + * type received. On reception of an unknown packet type, the receicer must + * send a P_UNKNOWN packet, the first byte must be the unknown packet type. - + * Packets that are greater than a (private) MTU are silently dropped. + */ + final static boolean DEBUG = false; + + final static int SYNC_BYTE = Serial.HDLC_FLAG_BYTE; + + final static int ESCAPE_BYTE = Serial.HDLC_CTLESC_BYTE; + + final static int MTU = 256; + + final static int ACK_TIMEOUT = 1000; // in milliseconds + + final static int P_ACK = Serial.SERIAL_PROTO_ACK; + + final static int P_PACKET_ACK = Serial.SERIAL_PROTO_PACKET_ACK; + + final static int P_PACKET_NO_ACK = Serial.SERIAL_PROTO_PACKET_NOACK; + + final static int P_UNKNOWN = Serial.SERIAL_PROTO_PACKET_UNKNOWN; + + private ByteSource io; + + private boolean inSync; + + private byte[] receiveBuffer = new byte[MTU]; + + private int seqNo; + + // Packets are received by a separate thread and placed in a + // per-packet-type queue. If received[x] is null, then x is an + // unknown protocol (but P_UNKNOWN and P_PACKET_ACK are handled + // specially) + private Thread reader; + + private LinkedList[] received; + + /** + * Packetizers are built using the makeXXX methods in BuildSource + */ + Packetizer(String name, ByteSource io) { + super(name); + this.io = io; + inSync = false; + seqNo = 13; + reader = new Thread(this); + received = new LinkedList[256]; + received[P_ACK] = new LinkedList(); + received[P_PACKET_NO_ACK] = new LinkedList(); + } - synchronized public void open(Messenger messages) throws IOException { - super.open(messages); - reader.start(); + synchronized public void open(Messenger messages) throws IOException { + super.open(messages); + if(!reader.isAlive()) { + reader.start(); } + } - protected void openSource() throws IOException { - io.open(); - } + protected void openSource() throws IOException { + io.open(); + } - protected void closeSource() { - io.close(); - } + protected void closeSource() { + io.close(); + } - protected byte[] readProtocolPacket(int packetType, long deadline) throws IOException { - LinkedList inPackets = received[packetType]; - - // Wait for a packet on inPackets - synchronized (inPackets) { - while (inPackets.isEmpty()) { - long now = System.currentTimeMillis(); - if (deadline != 0 && now >= deadline) { - return null; - } - try { - inPackets.wait(deadline != 0 ? deadline - now : 0); - } - catch (InterruptedException e) { - throw new IOException("interrupted"); - } - } - return (byte [])inPackets.removeFirst(); - } + protected byte[] readProtocolPacket(int packetType, long deadline) + throws IOException { + LinkedList inPackets = received[packetType]; + + // Wait for a packet on inPackets + synchronized (inPackets) { + while (inPackets.isEmpty()) { + long now = System.currentTimeMillis(); + if (deadline != 0 && now >= deadline) { + return null; + } + try { + inPackets.wait(deadline != 0 ? deadline - now : 0); + } catch (InterruptedException e) { + throw new IOException("interrupted"); + } + } + return (byte[]) inPackets.removeFirst(); } + } - // Place a packet in its packet queue, or reject unknown packet - // types (which don't have a queue) - protected void pushProtocolPacket(int packetType, byte[] packet) { - LinkedList inPackets = received[packetType]; - - if (inPackets != null) { - synchronized (inPackets) { - inPackets.add(packet); - inPackets.notify(); - } - } - else if (packetType != P_UNKNOWN) { - try { - writeFramedPacket(P_UNKNOWN, packetType, ackPacket, 0); - } - catch (IOException e) { } - message(name + ": ignoring unknown packet type 0x" + - Integer.toHexString(packetType)); - } + // Place a packet in its packet queue, or reject unknown packet + // types (which don't have a queue) + protected void pushProtocolPacket(int packetType, byte[] packet) { + LinkedList inPackets = received[packetType]; + + if (inPackets != null) { + synchronized (inPackets) { + inPackets.add(packet); + inPackets.notify(); + } + } else if (packetType != P_UNKNOWN) { + try { + writeFramedPacket(P_UNKNOWN, packetType, ackPacket, 0); + } catch (IOException e) { + } + message(name + ": ignoring unknown packet type 0x" + + Integer.toHexString(packetType)); } + } - protected byte[] readSourcePacket() throws IOException { - // Packetizer packet format is identical to PacketSource's - for (;;) { - byte[] packet = readProtocolPacket(P_PACKET_NO_ACK,0); - if (packet.length >= 1) { - return packet; - } - } + protected byte[] readSourcePacket() throws IOException { + // Packetizer packet format is identical to PacketSource's + for (;;) { + byte[] packet = readProtocolPacket(P_PACKET_NO_ACK, 0); + if (packet.length >= 1) { + return packet; + } } + } // Write an ack-ed packet protected boolean writeSourcePacket(byte[] packet) throws IOException { - writeFramedPacket(P_PACKET_ACK, ++seqNo, packet, packet.length); + writeFramedPacket(P_PACKET_ACK, ++seqNo, packet, packet.length); + + long deadline = System.currentTimeMillis() + ACK_TIMEOUT; + for (;;) { + byte[] ack = readProtocolPacket(P_ACK, deadline); + if (ack == null) { + if (DEBUG) { + message(name + ": ACK timed out"); + } + return false; + } + if (ack[0] == (byte) seqNo) { + if (DEBUG) { + message(name + ": Rcvd ACK"); + } + return true; + } + } - long deadline = System.currentTimeMillis() + ACK_TIMEOUT; + } + + static private byte ackPacket[] = new byte[0]; + + public void run() { + try { for (;;) { - byte[] ack = readProtocolPacket(P_ACK, deadline); - if (ack == null) { - if (DEBUG) { - message(name + ": ACK timed out"); - } - return false; - } - if (ack[0] == (byte)seqNo) { - if (DEBUG) { - message(name + ": Rcvd ACK"); - } - return true; - } + byte[] packet = readFramedPacket(); + int packetType = packet[0] & 0xff; + int pdataOffset = 1; + + if (packetType == P_PACKET_ACK) { + // send ack + writeFramedPacket(P_ACK, packet[1], ackPacket, 0); + // And merge with un-acked packets + packetType = P_PACKET_NO_ACK; + pdataOffset = 2; + } + int dataLength = packet.length - pdataOffset; + byte[] dataPacket = new byte[dataLength]; + System.arraycopy(packet, pdataOffset, dataPacket, 0, dataLength); + pushProtocolPacket(packetType, dataPacket); } - + } catch (IOException e) { + } } - static private byte ackPacket[] = new byte[0]; - - public void run() { - try { - for (;;) { - byte[] packet = readFramedPacket(); - int packetType = packet[0] & 0xff; - int pdataOffset = 1; - - if (packetType == P_PACKET_ACK) { - // send ack - writeFramedPacket(P_ACK, packet[1], ackPacket, 0); - // And merge with un-acked packets - packetType = P_PACKET_NO_ACK; - pdataOffset = 2; - } - int dataLength = packet.length - pdataOffset; - byte[] dataPacket = new byte[dataLength]; - System.arraycopy(packet, pdataOffset, dataPacket, 0, dataLength); - pushProtocolPacket(packetType, dataPacket); - } - } - catch (IOException e) { } + // Read system-level packet. If inSync is false, we currently don't + // have sync + private byte[] readFramedPacket() throws IOException { + int count = 0; + boolean escaped = false; + + for (;;) { + if (!inSync) { + message(name + ": resynchronising"); + // re-synchronise + while (io.readByte() != SYNC_BYTE) + ; + inSync = true; + count = 0; + escaped = false; + } + + if (count >= MTU) { + // Packet too long, give up and try to resync + message(name + ": packet too long"); + inSync = false; + continue; + } + + byte b = io.readByte(); + if (escaped) { + if (b == SYNC_BYTE) { + // sync byte following escape is an error, resync + message(name + ": unexpected sync byte"); + inSync = false; + continue; + } + b ^= 0x20; + escaped = false; + } else if (b == ESCAPE_BYTE) { + escaped = true; + continue; + } else if (b == SYNC_BYTE) { + if (count < 4) { + // too-small frames are ignored + count = 0; + continue; + } + byte[] packet = new byte[count - 2]; + System.arraycopy(receiveBuffer, 0, packet, 0, count - 2); + + int readCrc = (receiveBuffer[count - 2] & 0xff) + | (receiveBuffer[count - 1] & 0xff) << 8; + int computedCrc = Crc.calc(packet, packet.length); + + if (DEBUG) { + System.err.println("received: "); + Dump.printPacket(System.err, packet); + System.err.println(" rcrc: " + Integer.toHexString(readCrc) + + " ccrc: " + Integer.toHexString(computedCrc)); + } + + if (readCrc == computedCrc) { + return packet; + } else { + message(name + ": bad packet"); + /* + * We don't lose sync here. If we did, garbage on the line at startup + * will cause loss of the first packet. + */ + count = 0; + continue; + } + } + + receiveBuffer[count++] = b; + } + } + + // Class to build a framed, escaped and crced packet byte stream + static class Escaper { + byte[] escaped; + + int escapePtr; + + int crc; + + // We're building a length-byte packet + Escaper(int length) { + escaped = new byte[2 * length]; + escapePtr = 0; + crc = 0; + escaped[escapePtr++] = SYNC_BYTE; } - // Read system-level packet. If inSync is false, we currently don't - // have sync - private byte[] readFramedPacket() throws IOException { - int count = 0; - boolean escaped = false; - - for (;;) { - if (!inSync) { - message(name + ": resynchronising"); - // re-synchronise - while (io.readByte() != SYNC_BYTE) - ; - inSync = true; - count = 0; - escaped = false; - } - - if (count >= MTU) { - // Packet too long, give up and try to resync - message(name + ": packet too long"); - inSync = false; - continue; - } - - byte b = io.readByte(); - if (escaped) { - if (b == SYNC_BYTE) { - // sync byte following escape is an error, resync - message(name + ": unexpected sync byte"); - inSync = false; - continue; - } - b ^= 0x20; - escaped = false; - } - else if (b == ESCAPE_BYTE) { - escaped = true; - continue; - } - else if (b == SYNC_BYTE) { - if (count < 4) { - // too-small frames are ignored - count = 0; - continue; - } - byte[] packet = new byte[count - 2]; - System.arraycopy(receiveBuffer, 0, packet, 0, count - 2); - - int readCrc = (receiveBuffer[count - 2] & 0xff) | - (receiveBuffer[count - 1] & 0xff) << 8; - int computedCrc = Crc.calc(packet, packet.length); - - if (DEBUG) { - System.err.println("received: "); - Dump.printPacket(System.err, packet); - System.err.println(" rcrc: " + Integer.toHexString(readCrc) + - " ccrc: " + Integer.toHexString(computedCrc)); - } - - if (readCrc == computedCrc) { - return packet; - } - else { - message(name + ": bad packet"); - /* We don't lose sync here. If we did, garbage on the line - at startup will cause loss of the first packet. */ - count = 0; - continue; - } - } - - receiveBuffer[count++] = b; - } + static private boolean needsEscape(int b) { + return b == SYNC_BYTE || b == ESCAPE_BYTE; } - // Class to build a framed, escaped and crced packet byte stream - static class Escaper { - byte[] escaped; - int escapePtr; - int crc; - - // We're building a length-byte packet - Escaper(int length) { - escaped = new byte[2 * length]; - escapePtr = 0; - crc = 0; - escaped[escapePtr++] = SYNC_BYTE; - } - - static private boolean needsEscape(int b) { - return b == SYNC_BYTE || b == ESCAPE_BYTE; - } - - void nextByte(int b) { - b = b & 0xff; - crc = Crc.calcByte(crc, b); - if (needsEscape(b)) { - escaped[escapePtr++] = ESCAPE_BYTE; - escaped[escapePtr++] = (byte)(b ^ 0x20); - } - else { - escaped[escapePtr++] = (byte)b; - } - } - - void terminate() { - escaped[escapePtr++] = SYNC_BYTE; - } + void nextByte(int b) { + b = b & 0xff; + crc = Crc.calcByte(crc, b); + if (needsEscape(b)) { + escaped[escapePtr++] = ESCAPE_BYTE; + escaped[escapePtr++] = (byte) (b ^ 0x20); + } else { + escaped[escapePtr++] = (byte) b; + } } - // Write a packet of type 'packetType', first byte 'firstByte' - // and bytes 2..'count'+1 in 'packet' - private synchronized void writeFramedPacket(int packetType, int firstByte, - byte[] packet, int count) throws IOException { - if (DEBUG) { - System.err.println("sending: "); - Dump.printByte(System.err, packetType); - Dump.printByte(System.err, firstByte); - Dump.printPacket(System.err, packet); - System.err.println(); - } - - Escaper buffer = new Escaper(count + 6); - - buffer.nextByte(packetType); - buffer.nextByte(firstByte); - for (int i = 0; i < count; i++) { - buffer.nextByte(packet[i]); - } - - int crc = buffer.crc; - buffer.nextByte(crc & 0xff); - buffer.nextByte(crc >> 8); - - buffer.terminate(); - - byte[] realPacket = new byte[buffer.escapePtr]; - System.arraycopy(buffer.escaped, 0, realPacket, 0, buffer.escapePtr); - - if (DEBUG) { - Dump.dump("encoded", realPacket); - } - io.writeBytes(realPacket); + void terminate() { + escaped[escapePtr++] = SYNC_BYTE; } + } + + // Write a packet of type 'packetType', first byte 'firstByte' + // and bytes 2..'count'+1 in 'packet' + private synchronized void writeFramedPacket(int packetType, int firstByte, + byte[] packet, int count) throws IOException { + if (DEBUG) { + System.err.println("sending: "); + Dump.printByte(System.err, packetType); + Dump.printByte(System.err, firstByte); + Dump.printPacket(System.err, packet); + System.err.println(); + } + + Escaper buffer = new Escaper(count + 6); + + buffer.nextByte(packetType); + buffer.nextByte(firstByte); + for (int i = 0; i < count; i++) { + buffer.nextByte(packet[i]); + } + + int crc = buffer.crc; + buffer.nextByte(crc & 0xff); + buffer.nextByte(crc >> 8); + + buffer.terminate(); + + byte[] realPacket = new byte[buffer.escapePtr]; + System.arraycopy(buffer.escaped, 0, realPacket, 0, buffer.escapePtr); + + if (DEBUG) { + Dump.dump("encoded", realPacket); + } + io.writeBytes(realPacket); + } } diff --git a/support/sdk/java/net/tinyos/packet/SerialByteSource.java b/support/sdk/java/net/tinyos/packet/SerialByteSource.java index 32339f4f..73357f41 100644 --- a/support/sdk/java/net/tinyos/packet/SerialByteSource.java +++ b/support/sdk/java/net/tinyos/packet/SerialByteSource.java @@ -1,5 +1,7 @@ // $Id$ +package net.tinyos.packet; + /* tab:4 * "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. @@ -29,111 +31,104 @@ * 94704. Attention: Intel License Inquiry. */ - -package net.tinyos.packet; - -import java.util.*; import java.io.*; import net.tinyos.comm.*; /** * A serial port byte source using net.tinyos.comm */ -public class SerialByteSource extends StreamByteSource implements SerialPortListener -{ - private SerialPort serialPort; - private String portName; - private int baudRate; - - public SerialByteSource(String portName, int baudRate) { - this.portName = portName; - this.baudRate = baudRate; +public class SerialByteSource extends StreamByteSource implements + SerialPortListener { + private SerialPort serialPort; + + private String portName; + + private int baudRate; + + public SerialByteSource(String portName, int baudRate) { + this.portName = portName; + this.baudRate = baudRate; + } + + public void openStreams() throws IOException { + //if (serialPort == null) { + try { + serialPort = new TOSSerial(portName); + } catch (Exception e) { + throw new IOException("Could not open " + portName + ": " + + e.getMessage()); + } + /* + } else { + if (!serialPort.open()) { + throw new IOException("Could not re-open " + portName); + } } + */ - public void openStreams() throws IOException { - try { - serialPort = new TOSSerial(portName); - } - catch (Exception e) { - throw new IOException("Could not open " + portName + ": " + e.getMessage()); - } - - try { - //serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); - serialPort.setSerialPortParams(baudRate, - 8, - SerialPort.STOPBITS_1, - false ); - - serialPort.addListener(this); - serialPort.notifyOn( SerialPortEvent.DATA_AVAILABLE, true ); - } - catch (Exception e) { - serialPort.close(); - throw new IOException("Could not configure " + portName + ": " + e.getMessage() ); - } - - is = serialPort.getInputStream(); - os = serialPort.getOutputStream(); - } + try { + // serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); + serialPort.setSerialPortParams(baudRate, 8, SerialPort.STOPBITS_1, false); - public void closeStreams() throws IOException { - serialPort.close(); + serialPort.addListener(this); + serialPort.notifyOn(SerialPortEvent.DATA_AVAILABLE, true); + } catch (Exception e) { + serialPort.close(); + throw new IOException("Could not configure " + portName + ": " + + e.getMessage()); } - public String allPorts() { - /* - Enumeration ports = CommPortIdentifier.getPortIdentifiers(); - if (ports == null) - return "No comm ports found!"; - - boolean noPorts = true; - String portList = "Known serial ports:\n"; - while (ports.hasMoreElements()) { - CommPortIdentifier port = (CommPortIdentifier)ports.nextElement(); - - if (port.getPortType() == CommPortIdentifier.PORT_SERIAL) { - portList += "- " + port.getName() + "\n"; - noPorts = false; - } - } - if (noPorts) - return "No comm ports found!"; - else - return portList; - */ - return "Listing available comm ports is no longer supported."; + is = serialPort.getInputStream(); + os = serialPort.getOutputStream(); + } + + public void closeStreams() throws IOException { + serialPort.close(); + } + + public String allPorts() { + /* + * Enumeration ports = CommPortIdentifier.getPortIdentifiers(); if (ports == + * null) return "No comm ports found!"; + * + * boolean noPorts = true; String portList = "Known serial ports:\n"; while + * (ports.hasMoreElements()) { CommPortIdentifier port = + * (CommPortIdentifier)ports.nextElement(); + * + * if (port.getPortType() == CommPortIdentifier.PORT_SERIAL) { portList += "- " + + * port.getName() + "\n"; noPorts = false; } } if (noPorts) return "No comm + * ports found!"; else return portList; + */ + return "Listing available comm ports is no longer supported."; + } + + Object sync = new Object(); + + public byte readByte() throws IOException { + // On Linux at least, javax.comm input streams are not interruptible. + // Make them so, relying on the DATA_AVAILABLE serial event. + synchronized (sync) { + while (is.available() == 0) { + try { + sync.wait(); + } catch (InterruptedException e) { + close(); + throw new IOException("interrupted"); + } + } } - Object sync = new Object(); - - public byte readByte() throws IOException { - // On Linux at least, javax.comm input streams are not interruptible. - // Make them so, relying on the DATA_AVAILABLE serial event. - synchronized (sync) { - while (is.available() == 0) { - try { - sync.wait(); - } - catch (InterruptedException e) { - close(); - throw new IOException("interrupted"); - } - } - } - - return super.readByte(); - } + return super.readByte(); + } - public void serialEvent(SerialPortEvent ev) { - synchronized (sync) { - sync.notify(); - } + public void serialEvent(SerialPortEvent ev) { + synchronized (sync) { + sync.notify(); } + } - protected void finalize() { - System.out.println("SerialByteSource finalize"); - serialPort.close(); - } + protected void finalize() { + serialPort.finalize(); + } } diff --git a/support/sdk/java/tinyos.jar b/support/sdk/java/tinyos.jar index 546ffe78..cd6ec2e9 100644 Binary files a/support/sdk/java/tinyos.jar and b/support/sdk/java/tinyos.jar differ