[Tinyos-beta-commits] CVS: tinyos-1.x/beta/TOSComm/comm ByteQueue.java, NONE, 1.1 JavaxCommSerialPort.java, NONE, 1.1 Makefile, NONE, 1.1 Makefile.win32, NONE, 1.1 NativeSerial.h, NONE, 1.1 NativeSerialEnums.h, NONE, 1.1 NativeSerial_win32.cpp, NONE, 1.1 SerialPort.java, NONE, 1.1 SerialPortEvent.java, NONE, 1.1 SerialPortListener.java, NONE, 1.1 TOSComm.i, NONE, 1.1 TOSCommLibraryLoader.java, NONE, 1.1 TOSSerial.java, NONE, 1.1 UnsupportedCommOperationException.java, NONE, 1.1

Cory Sharp cssharp at users.sourceforge.net
Tue Dec 21 17:31:51 PST 2004


Update of /cvsroot/tinyos/tinyos-1.x/beta/TOSComm/comm
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13517/comm

Added Files:
	ByteQueue.java JavaxCommSerialPort.java Makefile 
	Makefile.win32 NativeSerial.h NativeSerialEnums.h 
	NativeSerial_win32.cpp SerialPort.java SerialPortEvent.java 
	SerialPortListener.java TOSComm.i TOSCommLibraryLoader.java 
	TOSSerial.java UnsupportedCommOperationException.java 
Log Message:
TOSComm provides serial port access to Java through a native JNI shared
library.  TOSComm has been designed as a lighter weight replacement for
javax.comm, and its interfaces are similar.  See README.TOSComm or the
discussion on the TinyOS-Devel mailing list for summary of my motivation and
plan for writing this library.


--- NEW FILE: ByteQueue.java ---
//$Id: ByteQueue.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

public class ByteQueue
{
  byte buffer[];
  int nbegin;
  int nend;

  int num_free_back()
  {
    return buffer.length - nend;
  }

  void left_justify_into( byte dest[] )
  {
    for( int i=nbegin,j=0; i<nend; i++,j++ )
      dest[j] = buffer[i];
    nend -= nbegin;
    nbegin = 0;
    buffer = dest;
  }

  synchronized void ensure_free( int len )
  {
    if( (nbegin + num_free_back()) < len )
    {
      int newlen = buffer.length * 2;
      int total = available() + len;
      while( newlen < total )
        newlen *= 2;
      left_justify_into( new byte[newlen] );
    }
    else if( num_free_back() < len )
    {
      left_justify_into( buffer );
    }
  }

  public int available()
  {
    return nend - nbegin;
  }

  public void push_back( byte b )
  {
    ensure_free(1);
    buffer[nend++] = b;
  }

  public void push_back( byte b[] )
  {
    push_back( b, 0, b.length );
  }

  public void push_back( byte b[], int off, int len )
  {
    ensure_free( len );
    int bend = off + len;
    while( off < bend )
      buffer[nend++] = b[off++];
  }

  public int pop_front()
  {
    if( available() > 0 )
      return ((int)buffer[nbegin++]) & 255;
    return -1;
  }

  public int pop_front( byte b[] )
  {
    return pop_front( b, 0, b.length );
  }

  public int pop_front( byte b[], int off, int len )
  {
    int n = available();
    if( n > len )
      n = len;
    int bend = off + len;
    while( off < bend )
      b[off++] = buffer[nbegin++];
    return n;
  }

  public ByteQueue()
  {
    this(64);
  }

  public ByteQueue( int initial_buffer_length )
  {
    buffer = new byte[ initial_buffer_length ];
    nbegin = 0;
    nend = 0;
  }
}


--- NEW FILE: JavaxCommSerialPort.java ---
//$Id: JavaxCommSerialPort.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

import java.io.*;
import java.util.*;

public class JavaxCommSerialPort implements SerialPort, javax.comm.SerialPortEventListener
{
  javax.comm.SerialPort jx;
  Vector listeners = new Vector();

  public JavaxCommSerialPort( javax.comm.SerialPort jx )
  {
    this.jx = jx;
    try { jx.addEventListener(this); }
    catch( TooManyListenersException e ) { }
  }

  public InputStream getInputStream() throws IOException
    { return jx.getInputStream(); }

  public OutputStream getOutputStream() throws IOException
    { return jx.getOutputStream(); }

  public void close()
    { jx.close(); }

  public void setSerialPortParams( 
    int baudrate, int dataBits, int stopBits, boolean parity )
    throws UnsupportedCommOperationException
  {
    try
    {
      int db = 0;
      switch(dataBits)
      {
        case 5: db=javax.comm.SerialPort.DATABITS_5; break;
        case 6: db=javax.comm.SerialPort.DATABITS_6; break;
        case 7: db=javax.comm.SerialPort.DATABITS_7; break;
        case 8: db=javax.comm.SerialPort.DATABITS_8; break;
      }

      int sb = 0;
      if(stopBits==SerialPort.STOPBITS_1) sb=javax.comm.SerialPort.STOPBITS_1;
      if(stopBits==SerialPort.STOPBITS_1_5) sb=javax.comm.SerialPort.STOPBITS_1_5;
      if(stopBits==SerialPort.STOPBITS_2) sb=javax.comm.SerialPort.STOPBITS_2;

      int p = javax.comm.SerialPort.PARITY_NONE;
      if( parity ) p = javax.comm.SerialPort.PARITY_EVEN;

      jx.setSerialPortParams(baudrate,db,sb,p);
    }
    catch( javax.comm.UnsupportedCommOperationException e )
    {
      throw new UnsupportedCommOperationException( e.getMessage() );
    }
  }

  public int getBaudRate()
    { return jx.getBaudRate(); }

  public int getDataBits()
  {
    switch( jx.getDataBits() )
    {
      case javax.comm.SerialPort.DATABITS_5: return 5;
      case javax.comm.SerialPort.DATABITS_6: return 6;
      case javax.comm.SerialPort.DATABITS_7: return 7;
      case javax.comm.SerialPort.DATABITS_8: return 8;
    }
    return 0;
  }

  public int getStopBits()
  {
    switch( jx.getStopBits() )
    {
      case javax.comm.SerialPort.STOPBITS_1: return SerialPort.STOPBITS_1;
      case javax.comm.SerialPort.STOPBITS_1_5: return SerialPort.STOPBITS_1_5;
      case javax.comm.SerialPort.STOPBITS_2: return SerialPort.STOPBITS_2;
    }
    return 0;
  }

  public boolean getParity()
  {
    switch( jx.getParity() )
    {
      case javax.comm.SerialPort.PARITY_NONE: return false;
      case javax.comm.SerialPort.PARITY_EVEN: return true;
    }
    return false;
  }

  public void sendBreak( int millis )
    { jx.sendBreak(millis); }

  public void setFlowControlMode( int flowcontrol )
    throws UnsupportedCommOperationException
  {
    try
    {
      jx.setFlowControlMode(flowcontrol);
    }
    catch( javax.comm.UnsupportedCommOperationException e )
    {
      throw new UnsupportedCommOperationException( e.getMessage() );
    }
  }

  public int getFlowControlMode()
    { return jx.getFlowControlMode(); }

  public void setDTR( boolean dtr ) { jx.setDTR(dtr); }
  public void setRTS( boolean rts ) { jx.setRTS(rts); }
  public boolean isDTR() { return jx.isDTR(); }
  public boolean isRTS() { return jx.isRTS(); }
  public boolean isCTS() { return jx.isCTS(); }
  public boolean isDSR() { return jx.isDSR(); }
  public boolean isRI() { return jx.isRI(); }
  public boolean isCD() { return jx.isCD(); }

  public void addListener( SerialPortListener l )
    { if( !listeners.contains(l) ) listeners.add(l); }

  public void removeListener( SerialPortListener l )
    { listeners.remove(l); }

  public void notifyOn( int se, boolean enable )
  {
    if(se==SerialPortEvent.BREAK_INTERRUPT) jx.notifyOnBreakInterrupt(enable);
    if(se==SerialPortEvent.CARRIER_DETECT) jx.notifyOnCarrierDetect(enable);
    if(se==SerialPortEvent.CTS) jx.notifyOnCTS(enable);
    if(se==SerialPortEvent.DATA_AVAILABLE) jx.notifyOnDataAvailable(enable);
    if(se==SerialPortEvent.DSR) jx.notifyOnDSR(enable);
    if(se==SerialPortEvent.FRAMING_ERROR) jx.notifyOnFramingError(enable);
    if(se==SerialPortEvent.OVERRUN_ERROR) jx.notifyOnOverrunError(enable);
    if(se==SerialPortEvent.OUTPUT_EMPTY) jx.notifyOnOutputEmpty(enable);
    if(se==SerialPortEvent.PARITY_ERROR) jx.notifyOnParityError(enable);
    if(se==SerialPortEvent.RING_INDICATOR) jx.notifyOnRingIndicator(enable);
  }

  public void serialEvent( javax.comm.SerialPortEvent ev )
  {
    int t = 0;
    switch( ev.getEventType() )
    {
      case javax.comm.SerialPortEvent.BI: t=SerialPortEvent.BREAK_INTERRUPT; break;
      case javax.comm.SerialPortEvent.CD: t=SerialPortEvent.CARRIER_DETECT; break;  
      case javax.comm.SerialPortEvent.CTS: t=SerialPortEvent.CTS; break;
      case javax.comm.SerialPortEvent.DATA_AVAILABLE: t=SerialPortEvent.DATA_AVAILABLE; break;  
      case javax.comm.SerialPortEvent.DSR: t=SerialPortEvent.DSR; break;  
      case javax.comm.SerialPortEvent.FE: t=SerialPortEvent.FRAMING_ERROR; break;  
      case javax.comm.SerialPortEvent.OE: t=SerialPortEvent.OVERRUN_ERROR; break;  
      case javax.comm.SerialPortEvent.OUTPUT_BUFFER_EMPTY: t=SerialPortEvent.OUTPUT_EMPTY; break;
      case javax.comm.SerialPortEvent.PE: t=SerialPortEvent.PARITY_ERROR; break;
      case javax.comm.SerialPortEvent.RI: t=SerialPortEvent.RING_INDICATOR; break; 
    }

    SerialPortEvent ev2 = new SerialPortEvent(this,t);
    Iterator i = listeners.iterator();
    while( i.hasNext() )
      ((SerialPortListener)i.next()).serialEvent(ev2);
  }
}


--- NEW FILE: Makefile ---
#-*-Makefile-*- vim:syntax=make
#$Id: Makefile,v 1.1 2004/12/22 01:31:48 cssharp Exp $

#@author Cory Sharp <cssharp at eecs.berkeley.edu>


ifndef PLATFORM
PLATFORM=linux
ifeq ($(shell [ -f /bin/cygwin1.dll ] && echo cygwin),cygwin)
PLATFORM=win32
endif
endif


TOSCOMMDIR ?= $(TOSDIR)/../tools/java/net/tinyos/comm
INSTALLDIR ?= /usr/local/bin
JAVADIR ?= $(shell echo "`which javac`/../..")
BUILDDIR ?= build_$(PLATFORM)


JAVADEPS = \
  build_$(PLATFORM)/NativeSerial.java \
  build_$(PLATFORM)/TOSComm.java \
  build_$(PLATFORM)/TOSCommJNI.java \
  ByteQueue.java \
  JavaxCommSerialPort.java \
  SerialPort.java \
  SerialPortEvent.java \
  SerialPortListener.java \
  TOSCommLibraryLoader.java \
  TOSSerial.java \
  UnsupportedCommOperationException.java

JAVAOBJS = \
  build_$(PLATFORM)/NativeSerial.class \
  build_$(PLATFORM)/TOSComm.class \
  build_$(PLATFORM)/TOSCommJNI.class \
  ByteQueue.class \
  JavaxCommSerialPort.class \
  SerialPort.class \
  SerialPortEvent.class \
  SerialPortListener.class \
  TOSCommLibraryLoader.class \
  TOSSerial$$EventDispatcher.class \
  TOSSerial$$SerialInputStream.class \
  TOSSerial$$SerialOutputStream.class \
  TOSSerial.class \
  UnsupportedCommOperationException.class

SWIGDEPS = \
  TOSComm.i \
  NativeSerial.h

SWIGOBJS0 = \
  NativeSerial.java \
  TOSComm.java \
  TOSCommJNI.java \
  TOSComm_wrap.cxx

SWIGOBJS = $(addprefix $(BUILDDIR)/,$(SWIGOBJS0))


all: lib java

swig: builddir $(SWIGOBJS)
	@:

java: builddir $(JAVAOBJS)
	@:

builddir: $(BUILDDIR)
	@:


include Makefile.$(PLATFORM)


$(JAVAOBJS): $(JAVADEPS)
	javac *java $(BUILDDIR)/*java

$(BUILDDIR):
	mkdir $(BUILDDIR)


clean: FORCE
	rm -f *.class
	rm -rf $(BUILDDIR)


.PHONY: all lib swig java builddir install uninstall clean FORCE


--- NEW FILE: Makefile.win32 ---
#-*-Makefile-*- vim:syntax=make
#$Id: Makefile.win32,v 1.1 2004/12/22 01:31:48 cssharp Exp $

#@author Cory Sharp <cssharp at eecs.berkeley.edu>


TOSCOMMLIB = $(BUILDDIR)/TOSComm.dll
TOSCOMMDEPS = \
  NativeSerialEnums.h \
  NativeSerial_win32.cpp \
  $(BUILDDIR)/TOSComm_wrap.cxx

lib: builddir $(TOSCOMMLIB)
	@:

$(TOSCOMMLIB): $(TOSCOMMDEPS)
	g++ -O2 -s -mno-cygwin -shared \
	  -I$(BUILDDIR) -I$(JAVADIR)/include -I$(JAVADIR)/include/win32 \
	  -o $(TOSCOMMLIB) NativeSerial_win32.cpp

$(SWIGOBJS): $(SWIGDEPS)
	cd $(BUILDDIR) && swig -I.. -java -package net.tinyos.comm -c++ TOSComm.i
	cd $(BUILDDIR) && perl -i.orig -pe ' \
	  s{^}{//} if /For gcc on Windows/; \
	  s/\b(JNICALL) (Java_)/$$1 _$$2/; \
	' TOSComm_wrap.cxx && rm -f TOSComm_wrap.cxx.orig

install: FORCE
	install -d $(TOSCOMMDIR)
	install *.class $(BUILDDIR)/*.class $(TOSCOMMDIR)
	install $(TOSCOMMLIB) $(INSTALLDIR)

uninstall: FORCE
	rm -rf $(TOSCOMMDIR)/../comm $(INSTALLDIR)/TOSComm.dll


--- NEW FILE: NativeSerial.h ---
//$Id: NativeSerial.h,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

#include <stdexcept>

class NativeSerial
{
public:
  void setSerialPortParams( int baudrate, int databits, int stopbits, bool parity );
  int getBaudRate();
  int getDataBits();
  int getStopBits();
  bool getParity();

  void notifyOn( int event, bool enable );
  bool isNotifyOn( int event );
  bool waitForEvent();
  bool cancelWait();
  bool didEventOccur( int event );

  void setDTR( bool high );
  void setRTS( bool high );
  bool isDTR();
  bool isRTS();
  bool isCTS();
  bool isDSR();
  bool isRI();
  bool isCD();

  void sendBreak( int millis );

  NativeSerial( const char* portname );
  ~NativeSerial();

  void close();

  int available();
  int read();
  int read( signed char buffer_out[], int off, int len );
  int write( int b );
  int write( const signed char buffer_in[], int off, int len );
};


--- NEW FILE: NativeSerialEnums.h ---
//$Id: NativeSerialEnums.h,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

namespace NativeSerialEnums
{
  enum event_type
  {
    DATA_AVAILABLE = (1<<0),
    OUTPUT_EMPTY = (1<<1),
    CTS = (1<<2),
    DSR = (1<<3),
    RING_INDICATOR = (1<<4),
    CARRIER_DETECT = (1<<5),
    OVERRUN_ERROR = (1<<6),
    PARITY_ERROR = (1<<7),
    FRAMING_ERROR = (1<<8),
    BREAK_INTERRUPT = (1<<9),
  };

  enum
  {
    STOPBITS_1 = 1,
    STOPBITS_2 = 2,
    STOPBITS_1_5 = 3,
  };
};


--- NEW FILE: NativeSerial_win32.cpp ---
//$Id: NativeSerial_win32.cpp,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

#include <windows.h>
#include <stdexcept>
#include <sstream>
#include <iostream>

#include "NativeSerialEnums.h"
using namespace NativeSerialEnums;


class comm_port_error : public std::runtime_error
{
  public:
    comm_port_error( const char* msg ): std::runtime_error(msg) { }
};


class W32Overlapped
{
public:
  OVERLAPPED o;

  W32Overlapped()
  {
    o.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
    o.Internal = 0;
    o.InternalHigh = 0;
    o.Offset = 0;
    o.OffsetHigh = 0;
    if( o.hEvent == NULL )
      throw comm_port_error("could not create Overlapped event");
  }

  ~W32Overlapped()
  {
    if( o.hEvent != NULL )
      CloseHandle( o.hEvent );
  }
};


class NativeSerial
{
private:

  HANDLE hComm;
  W32Overlapped oread;
  W32Overlapped owrite;
  W32Overlapped owait;
  W32Overlapped oavail;

  std::string m_portname;
  int m_events_in;
  int m_events_out;
  bool m_dtr;
  bool m_rts;

protected:

  void test_comm_success( bool success, const char* extra_msg )
  {
    if( !success )
    {
      DWORD err = GetLastError();
      std::ostringstream os;
      char msg[1024];
      FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, msg, sizeof(msg), NULL );
      os << "Error " << err << ".\n   " << msg;
      if( extra_msg != NULL ) { os << "   in " << extra_msg; }
      throw comm_port_error(os.str().c_str());
    }
  }

  DCB get_comm_state()
  {
    DCB dcb;
    test_comm_success( GetCommState( hComm, &dcb ), "get_comm_state.GetCommState" );
    return dcb;
  }

  DWORD get_modem_status()
  {
    DWORD status = 0;
    test_comm_success( GetCommModemStatus( hComm, &status ), "get_modem_stauts.GetCommModemStatus" );
    return status;
  }

  static DWORD map_events_to_win32( int event )
  {
    DWORD ev = 0;
    if( event & DATA_AVAILABLE ) ev |= EV_RXCHAR;
    if( event & OUTPUT_EMPTY ) ev |= EV_TXEMPTY;
    if( event & CTS ) ev |= EV_CTS;
    if( event & DSR ) ev |= EV_DSR;
    if( event & RING_INDICATOR ) ev |= EV_RING;
    if( event & CARRIER_DETECT ) ev |= EV_RLSD;
    if( event & OVERRUN_ERROR ) ev |= EV_ERR;
    if( event & PARITY_ERROR ) ev |= EV_ERR;
    if( event & FRAMING_ERROR ) ev |= EV_ERR;
    if( event & BREAK_INTERRUPT ) ev |= EV_BREAK;
    return ev;
  }

  static int map_events_from_win32( DWORD ev, DWORD errors )
  {
    int event = 0;
    if( ev & EV_RXCHAR ) event |= DATA_AVAILABLE;
    if( ev & EV_TXEMPTY ) event |= OUTPUT_EMPTY;
    if( ev & EV_CTS ) event |= CTS;
    if( ev & EV_DSR ) event |= DSR;
    if( ev & EV_RING ) event |= RING_INDICATOR;
    if( ev & EV_RLSD ) event |= CARRIER_DETECT;
    if( ev & EV_ERR )
    {
      if( errors & CE_BREAK ) event |= BREAK_INTERRUPT;
      if( errors & CE_FRAME ) event |= FRAMING_ERROR;
      if( errors & CE_IOE ) throw comm_port_error("Win32 Comm IO Error");
      if( errors & CE_MODE ) throw comm_port_error("Win32 Comm Invalid Mode");
      if( errors & CE_OVERRUN ) event |= OVERRUN_ERROR;
      if( errors & CE_RXOVER ) event |= OVERRUN_ERROR; //?? okay
      if( errors & CE_RXPARITY ) event |= PARITY_ERROR;
      if( errors & CE_TXFULL ) event |= OVERRUN_ERROR; //?? okay
    }
    if( ev & EV_BREAK ) event |= BREAK_INTERRUPT;
    return event;
  }

public:

  void setSerialPortParams( int baudrate, int databits, int stopbits, bool parity )
  {
    DCB dcb = get_comm_state();
    dcb.BaudRate = baudrate;
    dcb.ByteSize = databits;
    switch( stopbits )
    {
      case 0: dcb.StopBits = ONE5STOPBITS; break;
      case 2: dcb.StopBits = TWOSTOPBITS; break;
      default: dcb.StopBits = ONESTOPBIT;
    }
    dcb.Parity = (parity ? 1 : 0);
    test_comm_success( SetCommState( hComm, &dcb ), "set_params.SetCommState" );
  }

  int getBaudRate()
  {
    int baud_rate = get_comm_state().BaudRate;
    switch( baud_rate )
    {
      case CBR_110:    return 110;
      case CBR_300:    return 300;
      case CBR_600:    return 600;
      case CBR_1200:   return 1200;
      case CBR_2400:   return 2400;
      case CBR_4800:   return 4800;
      case CBR_9600:   return 9600;
      case CBR_14400:  return 14400;
      case CBR_19200:  return 19200;
      case CBR_38400:  return 38400;
      case CBR_56000:  return 56000;
      case CBR_57600:  return 57600;
      case CBR_115200: return 115200;
      case CBR_128000: return 128000;
      case CBR_256000: return 256000;
    }
    return baud_rate;
  }

  int getDataBits()
  {
    return get_comm_state().ByteSize;
  }

  int getStopBits()
  {
    switch( get_comm_state().StopBits )
    {
      case ONESTOPBIT: return 0;
      case ONE5STOPBITS: return 1;
      case TWOSTOPBITS: return 2;
    }
    return 0;
  }

  bool getParity()
  {
    return (get_comm_state().fParity != 0);
  }

  int read( signed char* buffer, int off, int len )
  {
    DWORD nread = 0;
    if( !ReadFile( hComm, buffer+off, len, &nread, &oread.o ) )
    {
      test_comm_success( GetLastError() == ERROR_IO_PENDING, "read.WriteFile" );
      DWORD rvwait = WaitForSingleObject(oread.o.hEvent,INFINITE);
      test_comm_success( rvwait != WAIT_FAILED, "read.WaitForSingleObject" );
      if( rvwait != WAIT_OBJECT_0 )
	return 0;
      test_comm_success( GetOverlappedResult(hComm,&oread.o,&nread,TRUE), "read.GetOverlappedresult" );
    }
    return nread;
  }

  int write( const signed char* buffer, int off, int len )
  {
    DWORD nread = 0;
    DWORD nwritten = 0;
    if( !WriteFile( hComm, buffer+off, len, &nwritten, &owrite.o ) )
    {
      test_comm_success( GetLastError() == ERROR_IO_PENDING, "write.WriteFile" );
      DWORD rvwait = WaitForSingleObject(owrite.o.hEvent,INFINITE);
      test_comm_success( rvwait != WAIT_FAILED, "write.WaitForSingleObject" );
      if( rvwait != WAIT_OBJECT_0 )
	return 0;
      test_comm_success( GetOverlappedResult(hComm,&owrite.o,&nwritten,TRUE), "write.GetOverlappedresult" );
    }
    return nwritten;
  }

  int read()
  {
    signed char byte;
    return (read(&byte,0,1) > 0) ? ((unsigned char)byte) : -1;
  }

  int write( int b )
  {
    signed char byte = b;
    return write( &byte, 0, 1 );
  }

  int available()
  {
    COMSTAT cs;
    DWORD errors = 0;
    test_comm_success( ClearCommError( hComm, &errors, &cs ), "available.ClearCommError" );
    return cs.cbInQue;
  }

  void notifyOn( int event, bool enable )
  {
    if( enable )
      m_events_in |= event;
    else
      m_events_in &= ~event;
    test_comm_success( SetEvent( owait.o.hEvent ), "enable_event.SetEvent" );
  }

  bool isNotifyOn( int event )
  {
    return (m_events_in & event) != 0;
  }

  bool waitForEvent()
  {
    DWORD evMaskIn = map_events_to_win32( m_events_in );
    DWORD evMaskOut = 0;
    m_events_out = 0;
    if( evMaskIn != 0 )
    {
      test_comm_success( SetCommMask( hComm, evMaskIn ), "wait_for_event.SetCommMask" );
      if( !WaitCommEvent(hComm,&evMaskOut,&owait.o) )
      {
	DWORD nbytes = 0;
	test_comm_success( GetLastError() == ERROR_IO_PENDING, "wait_for_event.WaitCommEvent" );
	DWORD rvwait = WaitForSingleObject(owait.o.hEvent,INFINITE);
	test_comm_success( rvwait != WAIT_FAILED, "wait_for_event.WaitForSingleObject" );
	if( rvwait != WAIT_OBJECT_0 )
	  return 0;
	test_comm_success( GetOverlappedResult(hComm,&owait.o,&nbytes,TRUE), "write.GetOverlappedresult" );
      }
      //evMaskOut &= evMaskIn;
      DWORD errors = 0;
      test_comm_success( ClearCommError( hComm, &errors, NULL ), "wait_for_event.ClearCommError" );
      m_events_out = map_events_from_win32( evMaskOut, errors );
    }
    else
    {
      test_comm_success( ResetEvent( owait.o.hEvent ), "wait_for_event.ResetEvent" );
      DWORD rvwait = WaitForSingleObject( owait.o.hEvent, INFINITE );
      test_comm_success( rvwait != WAIT_FAILED, "wait_for_event.WaitForSingleObject" );
    }
    return (m_events_out != 0);
  }

  bool cancelWait()
  {
    test_comm_success( SetEvent( owait.o.hEvent ), "cancel_wait.SetEvent" );
    return true;
  }

  bool didEventOccur( int event )
  {
    return (m_events_out & event) != 0;
  }

  void setDTR( bool high )
  {
    test_comm_success( EscapeCommFunction( hComm, (high ? SETDTR : CLRDTR) ), "setDTR.EscapeCommFunction" );
    m_dtr = high;
  }

  void setRTS( bool high )
  {
    test_comm_success( EscapeCommFunction( hComm, (high ? SETRTS : CLRRTS) ), "setRTS.EscapeCommFunction" );
    m_rts = high;
  }

  bool isDTR()
  {
    return m_dtr;
  }

  bool isRTS()
  {
    return m_rts;
  }

  bool isCTS()
  {
    return (get_modem_status() & MS_CTS_ON) != 0;
  }

  bool isDSR()
  {
    return (get_modem_status() & MS_DSR_ON) != 0;
  }

  bool isRI()
  {
    return (get_modem_status() & MS_RING_ON) != 0;
  }

  bool isCD()
  {
    return (get_modem_status() & MS_RLSD_ON) != 0;
  }

  void sendBreak( int millis )
  {
  }

  NativeSerial( const char* portname ):
    m_events_in(0), 
    m_events_out(0),
    m_dtr(false),
    m_rts(false)
  {
    hComm = CreateFile( portname,
      GENERIC_READ | GENERIC_WRITE,
      0,  // exclusive access
      NULL,  // default security attributes
      OPEN_EXISTING,
      FILE_FLAG_OVERLAPPED,
      NULL
    );

    test_comm_success( hComm != INVALID_HANDLE_VALUE, "NativeSerialPort.CreateFile" );

    setDTR(false);
    setRTS(false);

    DWORD errors;
    test_comm_success( PurgeComm( hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ), "NativeSerialPort.PurgeComm" );
    test_comm_success( ClearCommError( hComm, &errors, NULL ), "NativeSerialPort.ClearCommErrors" );
  }

  ~NativeSerial()
  {
    close();
  }

  void close()
  {
    CloseHandle( hComm );
    SetEvent( oread.o.hEvent );
    SetEvent( owrite.o.hEvent );
    SetEvent( owait.o.hEvent );
    SetEvent( oavail.o.hEvent );
  }
};


#include "TOSComm_wrap.cxx"


--- NEW FILE: SerialPort.java ---
//$Id: SerialPort.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

import java.io.*;

public interface SerialPort
{
  public static final int STOPBITS_1 = 1;
  public static final int STOPBITS_2 = 2;
  public static final int STOPBITS_1_5 = 3;

  /*
  public static final int FLOWCONTROL_NONE = 0;
  public static final int FLOWCONTROL_RTSCTS_IN = 1;
  public static final int FLOWCONTROL_RTSCTS_OUT = 2;
  public static final int FLOWCONTROL_XONXOFF_IN = 4;
  public static final int FLOWCONTROL_XONXOFF_OUT = 8;
  */

  public InputStream getInputStream() throws IOException;
  public OutputStream getOutputStream() throws IOException;

  public void close();

  public void setSerialPortParams( 
    int baudrate, int dataBits, int stopBits, boolean parity )
    throws UnsupportedCommOperationException;
  public int getBaudRate();
  public int getDataBits();
  public int getStopBits();
  public boolean getParity();

  public void sendBreak( int millis );

  /*
  public void setFlowControlMode( int flowcontrol )
    throws UnsupportedCommOperationException;
  public int getFlowControlMode();
  */

  public void setDTR( boolean dtr );
  public void setRTS( boolean rts );
  public boolean isDTR();
  public boolean isRTS();
  public boolean isCTS();
  public boolean isDSR();
  public boolean isRI();
  public boolean isCD();

  public void addListener( SerialPortListener l );
  public void removeListener( SerialPortListener l );
  public void notifyOn( int serialEvent, boolean enable );
}


--- NEW FILE: SerialPortEvent.java ---
//$Id: SerialPortEvent.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

public class SerialPortEvent extends java.util.EventObject
{
  public final static int DATA_AVAILABLE = (1<<0);
  public final static int OUTPUT_EMPTY = (1<<1);
  public final static int CTS = (1<<2);
  public final static int DSR = (1<<3);
  public final static int RING_INDICATOR = (1<<4);
  public final static int CARRIER_DETECT = (1<<5);
  public final static int OVERRUN_ERROR = (1<<6);
  public final static int PARITY_ERROR = (1<<7);
  public final static int FRAMING_ERROR = (1<<8);
  public final static int BREAK_INTERRUPT = (1<<9);

  public SerialPort port;
  int eventType;

  public SerialPortEvent( SerialPort _port, int _eventType )
  {
    super(_port);
    port = _port;
    eventType = _eventType;
  }

  public int getEventType()
  {
    return eventType;
  }
}


--- NEW FILE: SerialPortListener.java ---
//$Id: SerialPortListener.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

public interface SerialPortListener
{
  public void serialEvent( SerialPortEvent ev );
}


--- NEW FILE: TOSComm.i ---
//$Id: TOSComm.i,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

%module TOSComm

%{
%}

%include "arrays_java.i";

%pragma(java) jniclasscode=%{
  static { TOSCommLibraryLoader.load(); }
%}

%exception {
  try {
    $action
  } catch (comm_port_error &e) {
    jclass clazz = jenv->FindClass("java/lang/Exception");
    std::string s = "TOSComm JNI library runtime error: ";
    s += + e.what();
    jenv->ThrowNew( clazz, s.c_str() );
    return $null;
  }
}

%include "NativeSerial.h"

char* getenv( const char* name );


--- NEW FILE: TOSCommLibraryLoader.java ---
//$Id: TOSCommLibraryLoader.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

public class TOSCommLibraryLoader
{
  static void load()
  {
    try
    {
      System.loadLibrary("TOSComm");
    }
    catch( Throwable t )
    {
      System.err.println(
        "The TOSComm JNI library was not found.\n"
      + "Please make sure the net.tinyos.comm package is properly installed.\n"
      //+ "See tinyos-1.x/tools/java/net/tinyos/comm/README.TOSComm for more details.\n"
      + "See tinyos-1.x/beta/TOSComm/README.TOSComm for more details.\n"
      + "Aborting."
      );
      System.exit(1);
    }
  }
}


--- NEW FILE: TOSSerial.java ---
//$Id: TOSSerial.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

import java.io.*;
import java.util.*;

public class TOSSerial extends NativeSerial implements SerialPort
{
  class EventDispatcher extends Thread
  {
    boolean m_run;
    TOSSerial m_serial;

    public EventDispatcher( TOSSerial serial )
    {
      m_run = true;
      m_serial = serial;
    }

    void dispatch_event( int event )
    {
      if( m_serial.didEventOccur(event) )
      {
	SerialPortEvent ev = new SerialPortEvent( m_serial, event );
	Iterator i = m_serial.m_listeners.iterator();
	while( i.hasNext() )
	  ((SerialPortListener)i.next()).serialEvent( ev );
      }
    }

    public void run()
    {
      while( m_run )
      {
	if( m_serial.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 close()
    {
      m_run = false;
      m_serial.cancelWait();
    }
  }


  class SerialInputStream extends InputStream
  {
    NativeSerial serial;
    ByteQueue bq = new ByteQueue(128);

    protected void gather()
    {
      int navail = serial.available();
      if( navail > 0 )
      {
        byte buffer[] = new byte[navail];
        bq.push_back( buffer, 0, serial.read( buffer, 0, navail ) );
      }
    }

    public SerialInputStream( NativeSerial _serial )
    {
      serial = _serial;
    }

    public int read()
    {
      gather();
      return bq.pop_front();
    }

    public int read( byte[] b )
    {
      gather();
      return bq.pop_front(b);
    }

    public int read( byte[] b, int off, int len )
    {
      gather();
      return bq.pop_front(b,off,len);
    }

    public int available()
    {
      gather();
      return bq.available();
    }
  }


  class SerialOutputStream extends OutputStream
  {
    NativeSerial serial;

    public SerialOutputStream( NativeSerial _serial )
    {
      serial = _serial;
    }

    public void write( int b )
    {
      serial.write(b);
    }

    public void write( byte[] b )
    {
      write(b,0,b.length);
    }

    public void write( byte[] b, int off, int len )
    {
      int nwritten = 0;
      while( nwritten < len )
	nwritten += serial.write( b, nwritten, len-nwritten );
    }
  }


  SerialInputStream m_in;
  SerialOutputStream m_out;
  Vector m_listeners = new Vector();
  EventDispatcher m_dispatch;

  static String map_portname( String name )
  {
    String map = TOSComm.getenv("TOSCOMMMAP");
    //System.err.println("TOSCOMMMAP="+map);

    if( name.matches("(?i)com\\d+") )
      return "\\\\.\\" + name;
    return name;
  }

  public TOSSerial( String portname )
  {
    super( map_portname(portname) );
    m_in = new SerialInputStream( this );
    m_out = new SerialOutputStream( this );
    m_dispatch = new EventDispatcher( this );
    m_dispatch.start();
  }

  public void addListener( SerialPortListener l )
  {
    if( !m_listeners.contains(l) )
      m_listeners.add(l);
  }

  public void removeListener( SerialPortListener l )
  {
    m_listeners.remove(l);
  }

  public InputStream getInputStream()
  {
    return m_in;
  }

  public OutputStream getOutputStream()
  {
    return m_out;
  }

  public void close()
  {
    m_dispatch.close();
    super.close();
    try
    {
      m_in.close();
      m_out.close();
    }
    catch( IOException e )
    {
    }

    try { m_dispatch.join(); }
    catch( InterruptedException e ) { }

    m_dispatch = null;
    m_in = null;
    m_out = null;
  }
}


--- NEW FILE: UnsupportedCommOperationException.java ---
//$Id: UnsupportedCommOperationException.java,v 1.1 2004/12/22 01:31:48 cssharp Exp $

/* "Copyright (c) 2000-2003 The Regents of the University of California.  
 * All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without written agreement
 * is hereby granted, provided that the above copyright notice, the following
 * two paragraphs and the author appear in all copies of this software.
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
 * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 */

//@author Cory Sharp <cssharp at eecs.berkeley.edu>

package net.tinyos.comm;

public class UnsupportedCommOperationException
  extends Exception
{
  public UnsupportedCommOperationException(String str)
  {
    super(str);
  }

  public UnsupportedCommOperationException()
  {
    super();
  }
}




More information about the Tinyos-beta-commits mailing list