Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 94 → Rev 95

/trunk/JavaSerial/src/com/rm5248/serial/SerialPort.java
1,951 → 1,195
package com.rm5248.serial;
 
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
/**
* A SerialPort object represents a SerialPort object on the system.
*
* When creating a SerialPort object, you give the SerialPort the name of the port that you
* wish to open.
*
* When opening a SerialPort and setting values, an {@link IllegalArgumentException} may be thrown
* if any of the values are NULL.
*
* When getting and settings the properties of the SerialPort using one of the {@code getXXX() }
* or {@code setXXX() } methods, an IllegalStateException will be thrown if the port has been closed.
*
* @author rm5248
*
*/
public class SerialPort implements Closeable {
 
static{
System.loadLibrary( "javaserial" );
}
 
/**
* Represents the BaudRate that the SerialPort uses.
*/
public enum BaudRate{
/** Not available in Windows */
B0,
/** Not available in Windows */
B50,
/** Not available in Windows */
B75,
B110,
/** Not available in Windows */
B134,
/** Not available in Windows */
B150,
B200,
B300,
B600,
B1200,
/** Not available in Windows */
B1800,
B2400,
B4800,
B9600,
B38400,
B115200
}
 
/**
* Represents the number of bits that the serial port uses.
* Typically, this is 8-bit characters.
*/
public enum DataBits{
DATABITS_5,
DATABITS_6,
DATABITS_7,
DATABITS_8
}
 
/**
* The number of stop bits for data. Typically this is 1.
*/
public enum StopBits{
STOPBITS_1,
STOPBITS_2
}
 
/**
* The parity bit for the data. Typically None.
*/
public enum Parity{
NONE,
EVEN,
ODD
}
 
/**
* The Flow control scheme for the data, typically None.
*/
public enum FlowControl{
NONE,
HARDWARE,
SOFTWARE
}
 
private class SerialStateListener implements Runnable{
private volatile boolean stop;
private SerialChangeListener listen;
SerialStateListener( SerialChangeListener listen ){
stop = false;
this.listen = listen;
}
 
@Override
public void run() {
while( !stop ){
synchronized( serialListenSync ){
try {
serialListenSync.wait();
if( stop ){
break;
}
listen.serialStateChanged( state );
} catch (Exception e) {}
}
}
}
void doStop(){
stop = true;
}
}
 
/* The handle to our internal data structure which keeps track of the port settings.
* We need a special structure, as on windows we have a HANDLE type, which is void*,
* yet on Linux we have a file descriptor, which is an int.
* This is not just a pointer to memory, because if we're running on a 64-bit
* system, then we might have problems putting it in 32-bits. Better safe than sorry.
*/
private int handle;
/* The input stream that user code uses to read from the serial port. */
private SerialInputStream inputStream;
/* The buffered serial input stream which filters out events for us. */
private BufferedSerialInputStream bis;
/* The output stream that user code uses to write to the serial port. */
private SerialOutputStream outputStream;
/* Make sure we don't close ourselves twice */
private boolean closed;
/* The name of the port that's currently open */
private String portName;
/* Cache of the last gotten serial line state */
private volatile SerialLineState state;
/* Runs in the background to check for serial port events */
private SerialStateListener serialListen;
/* Used for synchronizing serialListen */
private Object serialListenSync;
 
/**
* Open the specified port, 9600 baud, 8 data bits, 1 stop bit, no parity, no flow control
*
* @param portName The name of the port to open
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName ) throws NoSuchPortException, NotASerialPortException {
this( portName, BaudRate.B9600 );
}
 
/**
* Open up a serial port, but allow the user to keep the current settings of the serial port.
*
* @param portName The port to open
* @param keepSettings If true, will simply open the serial port without setting anything. If false, this method
* acts the same as {@link #SerialPort(String) SerialPort( String portName ) }
* @throws NoSuchPortException If the port does not exist
* @throws NotASerialPortException If the port is not in fact a serial port
*/
public SerialPort( String portName, boolean keepSettings ) throws NoSuchPortException, NotASerialPortException{
if( portName == null ){
throw new IllegalArgumentException( "portName must not be null" );
}
if( keepSettings ){
this.handle = openPort( portName );
this.portName = portName;
inputStream = new SerialInputStream( handle );
bis = new BufferedSerialInputStream( inputStream, this );
outputStream = new SerialOutputStream( handle );
closed = false;
 
SerialLineState s = new SerialLineState();
int state = getSerialLineStateInternalNonblocking();
// do some sort of bitwise operations here....
if( ( state & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( state & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( state & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( state & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( state & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( state & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
this.state = s;
serialListenSync = new Object();
}else{
this.handle = openPort( portName, 9600, 8, 1, 0, 0 );
}
new Thread( bis, "BufferedSerialReader" ).start();
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, BaudRate rate )throws NoSuchPortException, NotASerialPortException {
this( portName, rate, DataBits.DATABITS_8 );
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, BaudRate rate, DataBits data ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, StopBits.STOPBITS_1 );
}
 
/**
* Open the specified port, no parity or flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, Parity.NONE );
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @param parity The parity of the line
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, parity, FlowControl.NONE );
}
 
/**
* Open the specified port, defining all options
*
* @param portName The name of the port to open
* @param rate The Buad Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @param parity The parity of the line
* @param flow The flow control of the line
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow ) throws NoSuchPortException, NotASerialPortException {
int myRate = 0;
int myData = 0;
int myStop = 0;
int myParity = 0;
int myFlow = 0;
SerialLineState s;
int state;
//Check for null values in our arguments
if( portName == null ){
throw new IllegalArgumentException( "portName must not be null" );
}
if( rate == null ){
throw new IllegalArgumentException( "rate must not be null" );
}
if( data == null ){
throw new IllegalArgumentException( "data must not be null" );
}
if( stop == null ){
throw new IllegalArgumentException( "stop must not be null" );
}
if( parity == null ){
throw new IllegalArgumentException( "parity must not be null" );
}
if( flow == null ){
throw new IllegalArgumentException( "flow must not be null" );
}
 
//Okay, looks like we're good!
this.portName = portName;
closed = false;
 
switch( rate ){
case B0 : myRate = 0; break;
case B50 : myRate = 50; break;
case B75 : myRate = 75; break;
case B110 : myRate = 110; break;
case B134 : myRate = 134; break;
case B150 : myRate = 150; break;
case B200 : myRate = 200; break;
case B300 : myRate = 300; break;
case B600 : myRate = 600; break;
case B1200 : myRate = 1200; break;
case B1800 : myRate = 1800; break;
case B2400 : myRate = 2400; break;
case B4800 : myRate = 4800; break;
case B9600 : myRate = 9600; break;
case B38400 : myRate = 38400; break;
case B115200: myRate = 115200; break;
}
 
switch( data ){
case DATABITS_5: myData = 5; break;
case DATABITS_6: myData = 6; break;
case DATABITS_7: myData = 7; break;
case DATABITS_8: myData = 8; break;
}
 
switch( stop ){
case STOPBITS_1: myStop = 1; break;
case STOPBITS_2: myStop = 2; break;
}
 
switch( parity ){
case NONE: myParity = 0; break;
case ODD: myParity = 1; break;
case EVEN: myParity = 2; break;
}
 
switch( flow ){
case NONE: myFlow = 0; break;
case HARDWARE: myFlow = 1; break;
case SOFTWARE: myFlow = 2; break;
}
 
handle = openPort(portName, myRate, myData, myStop, myParity, myFlow);
inputStream = new SerialInputStream( handle );
bis = new BufferedSerialInputStream( inputStream, this );
outputStream = new SerialOutputStream( handle );
 
s = new SerialLineState();
state = getSerialLineStateInternalNonblocking();
if( ( state & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( state & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( state & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( state & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( state & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( state & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
this.state = s;
serialListenSync = new Object();
new Thread( bis, "BufferedSerialReader" ).start();
}
 
/**
* Set the Baud Rate for this port.
*
* @param rate
*/
public void setBaudRate( BaudRate rate ){
int myRate = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the BaudRate once the port has been closed." );
}
if( rate == null ){
throw new IllegalArgumentException( "rate must not be null" );
}
 
switch( rate ){
case B0 : myRate = 0; break;
case B50 : myRate = 50; break;
case B75 : myRate = 75; break;
case B110 : myRate = 110; break;
case B134 : myRate = 134; break;
case B150 : myRate = 150; break;
case B200 : myRate = 200; break;
case B300 : myRate = 300; break;
case B600 : myRate = 600; break;
case B1200 : myRate = 1200; break;
case B1800 : myRate = 1800; break;
case B2400 : myRate = 2400; break;
case B4800 : myRate = 4800; break;
case B9600 : myRate = 9600; break;
case B38400 : myRate = 38400; break;
case B115200: myRate = 115200; break;
}
 
setBaudRate( myRate );
}
 
/**
* Get the input stream to be used to read from this SerialPort.
*
* @return The input stream.
*/
public InputStream getInputStream(){
if( closed ){
throw new IllegalStateException( "Cannot get the input stream once the port has been closed." );
}
 
return bis;
}
 
/** Get the output stream used to write data to this device.
*
* @return The output stream.
*/
public OutputStream getOutputStream(){
if( closed ){
throw new IllegalStateException( "Cannot get the output stream once the port has been closed." );
}
 
return outputStream;
}
 
/**
* Close the serial port, and all input streams
*/
public void close(){
if( closed ) return;
closed = true;
doClose();
if( serialListen != null ){
serialListen.doStop();
}
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
 
/**
* See if the port has been closed already.
* @return
*/
public boolean isClosed(){
return closed;
}
 
public void finalize(){
close();
}
 
/**
* Set the stop bits of the serial port, after the port has been opened.
*
* @param stop
*/
public void setStopBits( StopBits stop ){
int myStop = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the StopBits once the port has been closed." );
}
if( stop == null ){
throw new IllegalArgumentException( "stop must not be null" );
}
 
switch( stop ){
case STOPBITS_1: myStop = 1; break;
case STOPBITS_2: myStop = 2; break;
}
 
setStopBits( myStop );
}
 
/**
* Set the data bits size, after the port has been opened.
*
* @param data
*/
public void setDataSize( DataBits data ){
int myData = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the DataBits once the port has been closed." );
}
if( data == null ){
throw new IllegalArgumentException( "data must not be null" );
}
 
switch( data ){
case DATABITS_5: myData = 5; break;
case DATABITS_6: myData = 6; break;
case DATABITS_7: myData = 7; break;
case DATABITS_8: myData = 8; break;
}
 
setCharSize( myData );
}
 
/**
* Set the parity of the serial port, after the port has been opened.
*
* @param parity
*/
public void setParity( Parity parity ){
int myParity = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the parity once the port has been closed." );
}
 
if( parity == null ){
throw new IllegalArgumentException( "parity must not be null" );
}
switch( parity ){
case NONE: myParity = 0; break;
case ODD: myParity = 1; break;
case EVEN: myParity = 2; break;
}
 
setParity( myParity );
}
 
/**
* Get the serial line state for the specified serial port.
*
* @return
*/
public SerialLineState getSerialLineState() throws IOException{
if( closed ){
throw new IllegalStateException( "Cannot get the serial line state once the port has been closed." );
}
 
int gotState = getSerialLineStateInternalNonblocking();
 
SerialLineState s = new SerialLineState();
// do some sort of bitwise operations here....
if( ( gotState & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( gotState & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( gotState & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( gotState & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( gotState & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( gotState & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
return s;
}
 
/**
* Set the serial line state to the parameters given.
*
* @param state
*/
public void setSerialLineState( SerialLineState state ){
if( closed ){
throw new IllegalStateException( "Cannot set the serial line state once the port has been closed." );
}
setSerialLineStateInternal( state );
//Now, because Windows is weird, we need to post a serial changed event here.
//however, since we can only set DTR and RTS, only post an event if those are
//the things that changed
if( this.state.dataTerminalReady != state.dataTerminalReady ||
this.state.requestToSend != state.requestToSend ){
this.postSerialChangedEvent( state );
}
}
 
/**
* Get the baud rate of the serial port.
*
* @return
*/
public SerialPort.BaudRate getBaudRate(){
int baudRate;
BaudRate toReturn;
if( closed ){
throw new IllegalStateException( "Cannot get the baud rate once the port has been closed." );
}
baudRate = getBaudRateInternal();
toReturn = BaudRate.B0;
 
switch( baudRate ){
case 0 : toReturn = BaudRate.B0 ; break;
case 50 : toReturn = BaudRate.B50 ; break;
case 75 : toReturn = BaudRate.B75 ; break;
case 110 : toReturn = BaudRate.B110 ; break;
case 134 : toReturn = BaudRate.B134 ; break;
case 150 : toReturn = BaudRate.B150 ; break;
case 200 : toReturn = BaudRate.B200 ; break;
case 300 : toReturn = BaudRate.B300 ; break;
case 600 : toReturn = BaudRate.B600 ; break;
case 1200 : toReturn = BaudRate.B1200 ; break;
case 1800 : toReturn = BaudRate.B1800 ; break;
case 2400 : toReturn = BaudRate.B2400 ; break;
case 4800 : toReturn = BaudRate.B4800 ; break;
case 9600 : toReturn = BaudRate.B9600 ; break;
case 38400 : toReturn = BaudRate.B38400 ; break;
case 115200: toReturn = BaudRate.B115200; break;
}
 
return toReturn;
}
 
/**
* Get the number of data bits.
*
* @return
*/
public SerialPort.DataBits getDataBits(){
int dataBits;
DataBits bits;
if( closed ){
throw new IllegalStateException( "Cannot get the data bits once the port has been closed." );
}
dataBits = getCharSizeInternal();
bits = DataBits.DATABITS_8;
 
switch( dataBits ){
case 8: bits = DataBits.DATABITS_8; break;
case 7: bits = DataBits.DATABITS_7; break;
case 6: bits = DataBits.DATABITS_6; break;
case 5: bits = DataBits.DATABITS_5; break;
}
 
return bits;
}
 
/**
* Get the number of stop bits.
*
* @return
*/
public SerialPort.StopBits getStopBits(){
int stopBits;
StopBits bits;
if( closed ){
throw new IllegalStateException( "Cannot get stop bits once the port has been closed." );
}
stopBits = getStopBitsInternal();
bits = StopBits.STOPBITS_1;
 
switch( stopBits ){
case 1: bits = StopBits.STOPBITS_1; break;
case 2: bits = StopBits.STOPBITS_2; break;
}
 
return bits;
}
 
/**
* Get the parity of the serial port.
*
* @return
*/
public SerialPort.Parity getParity(){
int parity;
Parity par;
if( closed ){
throw new IllegalStateException( "Cannot get the parity once the port has been closed." );
}
parity = getParityInternal();
par = Parity.NONE;
 
switch( parity ){
case 0: par = Parity.NONE; break;
case 1: par = Parity.ODD; break;
case 2: par = Parity.EVEN; break;
}
 
return par;
}
 
/**
* Get the flow control for the serial port.
*
* @return
*/
public SerialPort.FlowControl getFlowControl(){
int flowControl;
FlowControl cont;
if( closed ){
throw new IllegalStateException( "Cannot get the flow once the port has been closed." );
}
flowControl = getFlowControlInternal();
cont = FlowControl.NONE;
 
switch( flowControl ){
case 0: cont = FlowControl.NONE; break;
case 1: cont = FlowControl.HARDWARE; break;
case 2: cont = FlowControl.SOFTWARE; break;
}
 
return cont;
}
/**
* Set the flow control for the serial port
*
* @param flow
*/
public void setFlowControl( FlowControl flow ){
if( closed ){
throw new IllegalStateException( "Cannot set flow once the port has been closed." );
}
switch( flow ){
case HARDWARE: setFlowControl( 1 ); break;
case NONE: setFlowControl( 0 ); break;
case SOFTWARE: setFlowControl( 2 ); break;
}
}
 
/**
* Set the listener which will get events when there is activity on the serial port.
* Note that this activity does NOT include receive and transmit events - this is
* changes on the lines of the serial port, such as RI, DSR, and DTR.
*
* If listen is null, will remove the listener.
*
* @param listen The listener which gets events
*/
public void setSerialChangeListener( SerialChangeListener listen ){
if( serialListen != null ){
serialListen.doStop();
}
if( listen != null ){
serialListen = new SerialStateListener( listen );
new Thread( serialListen, "SerialListen" ).start();
}
 
}
 
public String toString(){
return "Serial Port " + portName + ":" + getBaudRate();
}
 
/**
* Get the name of the serial port that this object represents.
* @return
*/
public String getPortName(){
return portName;
}
/**
* This method is called when the state of the serial lines is changed.
*
* @param newState
*/
void postSerialChangedEvent( SerialLineState newState ){
if( !state.equals( newState ) ){
state = newState;
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
}
 
/**
* Open the specified port, return an internal handle to the data structure for this port.
*
* @param portName
* @return
*/
private native int openPort( String portName, int baudRate, int dataBits, int stopBits, int parity, int flowControl ) throws NoSuchPortException, NotASerialPortException;
 
/**
* Open the specified port, return an internal handle for the data of this port.
* This method DOES NOT set any of the serial port settings
*
* @param portName The port to open
* @return
*/
private native int openPort( String portName ) throws NoSuchPortException, NotASerialPortException;
 
/**
* Close this port, release all native resources
*/
private native void doClose();
 
/**
* Set the baud rate in the native code.
*
* @param baudRate
* @return
*/
private native boolean setBaudRate( int baudRate );
 
private native int getBaudRateInternal();
 
/**
* Set the number of stop bits, once the port has been opened.
*
* @param stopBits
* @return
*/
private native boolean setStopBits( int stopBits );
 
private native int getStopBitsInternal();
 
/**
* Set the character size, once the port has been opened.
* This should probably be called 'setDataBits'
*
* @param charSize
* @return
*/
private native boolean setCharSize( int charSize );
 
private native int getCharSizeInternal();
 
/** Set the parity once the port has been opened.
*
* @param parity 0 = None, 1 = Odd, 2 = Even
* @return
*/
private native boolean setParity( int parity );
 
private native int getParityInternal();
 
/** Set the flow control once the port has been opened.
*
*
* @param flowControl 0 = None, 1 = hardware, 2 = software
* @return
*/
private native boolean setFlowControl( int flowControl );
 
private native int getFlowControlInternal();
 
/** Get the serial line state, but don't block when getting it
*
* @return
*/
private native int getSerialLineStateInternalNonblocking();
/**
* Set the state of the serial line.
* @return
*/
private native int setSerialLineStateInternal( SerialLineState s );
//
// Static Methods
//
/**
* Get the major version of this library. For example, if this is version
* 0.2, this returns 0
*/
public static int getMajorVersion(){
return 0;
}
/**
* Get the minor version of this library. For example, if this is version
* 0.2, this returns 2.
*/
public static int getMinorVersion(){
return 4;
}
/**
* Get the major version of the native code. This should match up with
* {@link #getMajorVersion() getMajorVersion()}, although this is not
* guaranteed. For example, if this is version 0.2, this returns 0
*/
public static native int getMajorNativeVersion();
/**
* Get the minor version of the native code. This should match up with
* {@link #getMinorVersion() getMinorVersion()}, although this is not
* guaranteed. For example, if this is version 0.2, this returns 2.
*/
public static native int getMinorNativeVersion();
/**
* <p>
* Get an array of all the serial ports on the system. For example, on
* Windows this will return {@code { "COM1", "COM3", .... } } depending on how
* many serial devices you have plugged in. On Linux, this returns
* {@code { "/dev/ttyS0", "/dev/ttyUSB0", "/dev/symlink", ... } }
* It will not resolve symlinks, such that if there is a symlink
* from {@code /dev/symlink } to {@code /dev/ttyUSB0 }, they will both show up.
* </p>
* <p>
* <b>NOTE:</b> this will only return ports that you have permissions to
* open.
* </p>
*
* @return
*/
public static native String[] getSerialPorts();
 
}
package com.rm5248.serial;
 
import java.io.IOException;
 
/**
* A SerialPort represents a serial port on the system.
*
* All SerialPorts must implement this class.
*
* See the documentation for the subclasses on how to create
* a specific instance of a SerialPort.
*
* @author rm5248
*
*/
public interface SerialPort {
/**
* Represents the BaudRate that the SerialPort uses.
*/
public enum BaudRate{
/** Not available in Windows */
B0,
/** Not available in Windows */
B50,
/** Not available in Windows */
B75,
B110,
/** Not available in Windows */
B134,
/** Not available in Windows */
B150,
B200,
B300,
B600,
B1200,
/** Not available in Windows */
B1800,
B2400,
B4800,
B9600,
B38400,
B115200
}
 
/**
* Represents the number of bits that the serial port uses.
* Typically, this is 8-bit characters.
*/
public enum DataBits{
DATABITS_5,
DATABITS_6,
DATABITS_7,
DATABITS_8
}
 
/**
* The number of stop bits for data. Typically this is 1.
*/
public enum StopBits{
STOPBITS_1,
STOPBITS_2
}
 
/**
* The parity bit for the data. Typically None.
*/
public enum Parity{
NONE,
EVEN,
ODD
}
 
/**
* The Flow control scheme for the data, typically None.
*/
public enum FlowControl{
NONE,
HARDWARE,
SOFTWARE
}
 
/**
* Set the Baud Rate for this port.
*
* @param rate
*/
public abstract void setBaudRate(BaudRate rate);
 
/**
* Close the serial port, and all input streams
*/
public abstract void close();
 
/**
* See if the port has been closed already.
* @return
*/
public abstract boolean isClosed();
 
/**
* Set the stop bits of the serial port, after the port has been opened.
*
* @param stop
*/
public abstract void setStopBits(StopBits stop);
 
/**
* Set the data bits size, after the port has been opened.
*
* @param data
*/
public abstract void setDataSize(DataBits data);
 
/**
* Set the parity of the serial port, after the port has been opened.
*
* @param parity
*/
public abstract void setParity(Parity parity);
 
/**
* Get the serial line state for the specified serial port.
*
* @return
*/
public abstract SerialLineState getSerialLineState() throws IOException;
 
/**
* Set the serial line state to the parameters given.
*
* @param state
*/
public abstract void setSerialLineState(SerialLineState state);
 
/**
* Get the baud rate of the serial port.
*
* @return
*/
public abstract IOSerialPort.BaudRate getBaudRate();
 
/**
* Get the number of data bits.
*
* @return
*/
public abstract IOSerialPort.DataBits getDataBits();
 
/**
* Get the number of stop bits.
*
* @return
*/
public abstract IOSerialPort.StopBits getStopBits();
 
/**
* Get the parity of the serial port.
*
* @return
*/
public abstract IOSerialPort.Parity getParity();
 
/**
* Get the flow control for the serial port.
*
* @return
*/
public abstract IOSerialPort.FlowControl getFlowControl();
 
/**
* Set the flow control for the serial port
*
* @param flow
*/
public abstract void setFlowControl(FlowControl flow);
 
/**
* Set the listener which will get events when there is activity on the serial port.
* Note that this activity does NOT include receive and transmit events - this is
* changes on the lines of the serial port, such as RI, DSR, and DTR.
*
* If listen is null, will remove the listener.
*
* @param listen The listener which gets events
*/
public abstract void setSerialChangeListener(SerialChangeListener listen);
 
/**
* Get the name of the serial port that this object represents.
* @return
*/
public abstract String getPortName();
 
}
/trunk/JavaSerial/src/com/rm5248/serial/NIOSerialPort.java
0,0 → 1,111
package com.rm5248.serial;
 
import java.io.IOException;
 
/**
* An implementation of a serial port that uses NIO.
* Note that this <b>DOES NOT</b> automatically listen for changes in
* the serial line state.
*
* @author rm5248
*
*/
public class NIOSerialPort implements SerialPort {
 
@Override
public void setBaudRate(BaudRate rate) {
// TODO Auto-generated method stub
}
 
@Override
public void close() {
// TODO Auto-generated method stub
}
 
@Override
public boolean isClosed() {
// TODO Auto-generated method stub
return false;
}
 
@Override
public void setStopBits(StopBits stop) {
// TODO Auto-generated method stub
}
 
@Override
public void setDataSize(DataBits data) {
// TODO Auto-generated method stub
}
 
@Override
public void setParity(Parity parity) {
// TODO Auto-generated method stub
}
 
@Override
public SerialLineState getSerialLineState() throws IOException {
// TODO Auto-generated method stub
return null;
}
 
@Override
public void setSerialLineState(SerialLineState state) {
// TODO Auto-generated method stub
}
 
@Override
public BaudRate getBaudRate() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public DataBits getDataBits() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public StopBits getStopBits() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public Parity getParity() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public FlowControl getFlowControl() {
// TODO Auto-generated method stub
return null;
}
 
@Override
public void setFlowControl(FlowControl flow) {
// TODO Auto-generated method stub
}
 
@Override
public void setSerialChangeListener(SerialChangeListener listen) {
// TODO Auto-generated method stub
}
 
@Override
public String getPortName() {
// TODO Auto-generated method stub
return null;
}
 
}
/trunk/JavaSerial/src/com/rm5248/serial/SerialInputStream.java
4,7 → 4,9
import java.io.InputStream;
 
/**
* Input stream for the serial port.
* Input stream for the serial port. This implementation passes back the
* status of the control lines in the upper bits of {@code read()}, and
* thus must be parsed properly.
*/
class SerialInputStream extends InputStream{
/* The handle to read from. Needed for native implementation */
29,4 → 31,33
private native int readByte() throws IOException;
 
private native int getAvailable() throws IOException;
}
 
/**
* A SimpleSerialInputStream does not pass back the status of the control
* lines on the serial port - just the raw bytes.
*/
class SimpleSerialInputStream extends InputStream {
/* The handle to read from. Needed for native implementation */
@SuppressWarnings("unused")
private int handle;
 
SimpleSerialInputStream( int handle ){
this.handle = handle;
}
 
@Override
public int read() throws IOException{
return readByte();
}
 
@Override
public int available() throws IOException{
return getAvailable();
}
 
private native int readByte() throws IOException;
 
private native int getAvailable() throws IOException;
}
/trunk/JavaSerial/src/com/rm5248/serial/IOSerialPort.java
0,0 → 1,894
package com.rm5248.serial;
 
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
/**
* A SerialPort object represents a SerialPort object on the system. This implementation uses
* the STREAMS(IO) based method of accessing a serial port.
*
* When creating a SerialPort object, you give the SerialPort the name of the port that you
* wish to open.
*
* When opening a SerialPort and setting values, an {@link IllegalArgumentException} may be thrown
* if any of the values are NULL.
*
* When getting and settings the properties of the SerialPort using one of the {@code getXXX() }
* or {@code setXXX() } methods, an IllegalStateException will be thrown if the port has been closed.
*
* @author rm5248
*
*/
public class IOSerialPort implements Closeable, SerialPort {
 
static{
System.loadLibrary( "javaserial" );
}
 
private class SerialStateListener implements Runnable{
private volatile boolean stop;
private SerialChangeListener listen;
SerialStateListener( SerialChangeListener listen ){
stop = false;
this.listen = listen;
}
 
@Override
public void run() {
while( !stop ){
synchronized( serialListenSync ){
try {
serialListenSync.wait();
if( stop ){
break;
}
listen.serialStateChanged( state );
} catch (Exception e) {}
}
}
}
void doStop(){
stop = true;
}
}
 
/* The handle to our internal data structure which keeps track of the port settings.
* We need a special structure, as on windows we have a HANDLE type, which is void*,
* yet on Linux we have a file descriptor, which is an int.
* This is not just a pointer to memory, because if we're running on a 64-bit
* system, then we might have problems putting it in 32-bits. Better safe than sorry.
*/
private int handle;
/* The input stream that user code uses to read from the serial port. */
private InputStream inputStream;
/* The buffered serial input stream which filters out events for us. */
private BufferedSerialInputStream bis;
/* The output stream that user code uses to write to the serial port. */
private SerialOutputStream outputStream;
/* Make sure we don't close ourselves twice */
private boolean closed;
/* The name of the port that's currently open */
private String portName;
/* Cache of the last gotten serial line state */
private volatile SerialLineState state;
/* Runs in the background to check for serial port events */
private SerialStateListener serialListen;
/* Used for synchronizing serialListen */
private Object serialListenSync;
/* Depending on if we have a BufferedSerialInputStream or a normal InputStream,
* this will be set.
* Note that 'ignoring control lines' really means that we ignore CHANGES on
* the control lines; it should still be possible to get the state of the lines,
* you just won't be notified immediately.
*/
private boolean ignoringControlLines;
 
/**
* Open the specified port, 9600 baud, 8 data bits, 1 stop bit, no parity, no flow control,
* not ignoring control lines
*
* @param portName The name of the port to open
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName ) throws NoSuchPortException, NotASerialPortException {
this( portName, BaudRate.B9600 );
}
 
/**
* Open up a serial port, but allow the user to keep the current settings of the serial port.
*
* @param portName The port to open
* @param keepSettings If true, will simply open the serial port without setting anything. If false, this method
* acts the same as {@link #SerialPort(String) SerialPort( String portName ) }
* @param ignoreControlLines If true, all control line changes will be ignored and not propogated
* back through a {@link SerialChangeListener}.
* @throws NoSuchPortException If the port does not exist
* @throws NotASerialPortException If the port is not in fact a serial port
*/
public IOSerialPort( String portName, boolean keepSettings, boolean ignoreControlLines ) throws NoSuchPortException, NotASerialPortException{
if( portName == null ){
throw new IllegalArgumentException( "portName must not be null" );
}
if( keepSettings ){
this.handle = openPort( portName );
this.portName = portName;
this.ignoringControlLines = ignoreControlLines;
if( ignoreControlLines ){
SimpleSerialInputStream ssis = new SimpleSerialInputStream( handle );
inputStream = ssis;
}else{
SerialInputStream sis = new SerialInputStream( handle );
inputStream = sis;
bis = new BufferedSerialInputStream( sis, this );
}
outputStream = new SerialOutputStream( handle );
closed = false;
 
SerialLineState s = new SerialLineState();
int state = getSerialLineStateInternalNonblocking();
// do some sort of bitwise operations here....
if( ( state & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( state & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( state & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( state & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( state & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( state & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
this.state = s;
serialListenSync = new Object();
}else{
this.handle = openPort( portName, 9600, 8, 1, 0, 0 );
}
if( !ignoreControlLines ){
new Thread( bis, "BufferedSerialReader-" + portName ).start();
}
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName, BaudRate rate )throws NoSuchPortException, NotASerialPortException {
this( portName, rate, DataBits.DATABITS_8 );
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName, BaudRate rate, DataBits data ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, StopBits.STOPBITS_1 );
}
 
/**
* Open the specified port, no parity or flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName, BaudRate rate, DataBits data, StopBits stop ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, Parity.NONE );
}
 
/**
* Open the specified port, no flow control
*
* @param portName The name of the port to open
* @param rate The Baud Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @param parity The parity of the line
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity ) throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, parity, FlowControl.NONE );
}
 
/**
* Open the specified port, defining all options
*
* @param portName The name of the port to open
* @param rate The Buad Rate to open this port at
* @param data The number of data bits
* @param stop The number of stop bits
* @param parity The parity of the line
* @param flow The flow control of the line
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public IOSerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow ) throws NoSuchPortException, NotASerialPortException {
int myRate = 0;
int myData = 0;
int myStop = 0;
int myParity = 0;
int myFlow = 0;
SerialLineState s;
int state;
SerialInputStream sis;
//Check for null values in our arguments
if( portName == null ){
throw new IllegalArgumentException( "portName must not be null" );
}
if( rate == null ){
throw new IllegalArgumentException( "rate must not be null" );
}
if( data == null ){
throw new IllegalArgumentException( "data must not be null" );
}
if( stop == null ){
throw new IllegalArgumentException( "stop must not be null" );
}
if( parity == null ){
throw new IllegalArgumentException( "parity must not be null" );
}
if( flow == null ){
throw new IllegalArgumentException( "flow must not be null" );
}
 
//Okay, looks like we're good!
this.portName = portName;
closed = false;
ignoringControlLines = false;
 
switch( rate ){
case B0 : myRate = 0; break;
case B50 : myRate = 50; break;
case B75 : myRate = 75; break;
case B110 : myRate = 110; break;
case B134 : myRate = 134; break;
case B150 : myRate = 150; break;
case B200 : myRate = 200; break;
case B300 : myRate = 300; break;
case B600 : myRate = 600; break;
case B1200 : myRate = 1200; break;
case B1800 : myRate = 1800; break;
case B2400 : myRate = 2400; break;
case B4800 : myRate = 4800; break;
case B9600 : myRate = 9600; break;
case B38400 : myRate = 38400; break;
case B115200: myRate = 115200; break;
}
 
switch( data ){
case DATABITS_5: myData = 5; break;
case DATABITS_6: myData = 6; break;
case DATABITS_7: myData = 7; break;
case DATABITS_8: myData = 8; break;
}
 
switch( stop ){
case STOPBITS_1: myStop = 1; break;
case STOPBITS_2: myStop = 2; break;
}
 
switch( parity ){
case NONE: myParity = 0; break;
case ODD: myParity = 1; break;
case EVEN: myParity = 2; break;
}
 
switch( flow ){
case NONE: myFlow = 0; break;
case HARDWARE: myFlow = 1; break;
case SOFTWARE: myFlow = 2; break;
}
 
handle = openPort(portName, myRate, myData, myStop, myParity, myFlow);
sis = new SerialInputStream( handle );
inputStream = sis;
bis = new BufferedSerialInputStream( sis, this );
outputStream = new SerialOutputStream( handle );
 
s = new SerialLineState();
state = getSerialLineStateInternalNonblocking();
if( ( state & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( state & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( state & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( state & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( state & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( state & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
this.state = s;
serialListenSync = new Object();
new Thread( bis, "BufferedSerialReader" ).start();
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setBaudRate(com.rm5248.serial.SerialPort.BaudRate)
*/
@Override
public void setBaudRate( BaudRate rate ){
int myRate = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the BaudRate once the port has been closed." );
}
if( rate == null ){
throw new IllegalArgumentException( "rate must not be null" );
}
 
switch( rate ){
case B0 : myRate = 0; break;
case B50 : myRate = 50; break;
case B75 : myRate = 75; break;
case B110 : myRate = 110; break;
case B134 : myRate = 134; break;
case B150 : myRate = 150; break;
case B200 : myRate = 200; break;
case B300 : myRate = 300; break;
case B600 : myRate = 600; break;
case B1200 : myRate = 1200; break;
case B1800 : myRate = 1800; break;
case B2400 : myRate = 2400; break;
case B4800 : myRate = 4800; break;
case B9600 : myRate = 9600; break;
case B38400 : myRate = 38400; break;
case B115200: myRate = 115200; break;
}
 
setBaudRate( myRate );
}
 
/**
* Get the input stream used to talk to this device.
*/
public InputStream getInputStream(){
if( closed ){
throw new IllegalStateException( "Cannot get the input stream once the port has been closed." );
}
 
if( ignoringControlLines ){
return inputStream;
}
return bis;
}
 
/**
* Get the OutputStream used to talk to this device.
*/
public OutputStream getOutputStream(){
if( closed ){
throw new IllegalStateException( "Cannot get the output stream once the port has been closed." );
}
 
return outputStream;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#close()
*/
@Override
public void close(){
if( closed ) return;
closed = true;
doClose();
if( serialListen != null ){
serialListen.doStop();
}
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#isClosed()
*/
@Override
public boolean isClosed(){
return closed;
}
 
public void finalize(){
close();
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setStopBits(com.rm5248.serial.SerialPort.StopBits)
*/
@Override
public void setStopBits( StopBits stop ){
int myStop = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the StopBits once the port has been closed." );
}
if( stop == null ){
throw new IllegalArgumentException( "stop must not be null" );
}
 
switch( stop ){
case STOPBITS_1: myStop = 1; break;
case STOPBITS_2: myStop = 2; break;
}
 
setStopBits( myStop );
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setDataSize(com.rm5248.serial.SerialPort.DataBits)
*/
@Override
public void setDataSize( DataBits data ){
int myData = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the DataBits once the port has been closed." );
}
if( data == null ){
throw new IllegalArgumentException( "data must not be null" );
}
 
switch( data ){
case DATABITS_5: myData = 5; break;
case DATABITS_6: myData = 6; break;
case DATABITS_7: myData = 7; break;
case DATABITS_8: myData = 8; break;
}
 
setCharSize( myData );
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setParity(com.rm5248.serial.SerialPort.Parity)
*/
@Override
public void setParity( Parity parity ){
int myParity = 0;
 
if( closed ){
throw new IllegalStateException( "Cannot set the parity once the port has been closed." );
}
 
if( parity == null ){
throw new IllegalArgumentException( "parity must not be null" );
}
switch( parity ){
case NONE: myParity = 0; break;
case ODD: myParity = 1; break;
case EVEN: myParity = 2; break;
}
 
setParity( myParity );
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getSerialLineState()
*/
@Override
public SerialLineState getSerialLineState() throws IOException{
if( closed ){
throw new IllegalStateException( "Cannot get the serial line state once the port has been closed." );
}
 
int gotState = getSerialLineStateInternalNonblocking();
 
SerialLineState s = new SerialLineState();
// do some sort of bitwise operations here....
if( ( gotState & 0x01 ) > 0 ){
s.carrierDetect = true;
}
if( ( gotState & (0x01 << 1 ) ) > 0 ){
s.clearToSend = true;
}
if( ( gotState & (0x01 << 2 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( gotState & (0x01 << 3 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( gotState & (0x01 << 4 ) ) > 0 ){
s.requestToSend = true;
}
if( ( gotState & (0x01 << 5 ) ) > 0 ){
s.ringIndicator = true;
}
 
return s;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setSerialLineState(com.rm5248.serial.SerialLineState)
*/
@Override
public void setSerialLineState( SerialLineState state ){
if( closed ){
throw new IllegalStateException( "Cannot set the serial line state once the port has been closed." );
}
setSerialLineStateInternal( state );
//Now, because Windows is weird, we need to post a serial changed event here.
//however, since we can only set DTR and RTS, only post an event if those are
//the things that changed
if( this.state.dataTerminalReady != state.dataTerminalReady ||
this.state.requestToSend != state.requestToSend ){
this.postSerialChangedEvent( state );
}
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getBaudRate()
*/
@Override
public IOSerialPort.BaudRate getBaudRate(){
int baudRate;
BaudRate toReturn;
if( closed ){
throw new IllegalStateException( "Cannot get the baud rate once the port has been closed." );
}
baudRate = getBaudRateInternal();
toReturn = BaudRate.B0;
 
switch( baudRate ){
case 0 : toReturn = BaudRate.B0 ; break;
case 50 : toReturn = BaudRate.B50 ; break;
case 75 : toReturn = BaudRate.B75 ; break;
case 110 : toReturn = BaudRate.B110 ; break;
case 134 : toReturn = BaudRate.B134 ; break;
case 150 : toReturn = BaudRate.B150 ; break;
case 200 : toReturn = BaudRate.B200 ; break;
case 300 : toReturn = BaudRate.B300 ; break;
case 600 : toReturn = BaudRate.B600 ; break;
case 1200 : toReturn = BaudRate.B1200 ; break;
case 1800 : toReturn = BaudRate.B1800 ; break;
case 2400 : toReturn = BaudRate.B2400 ; break;
case 4800 : toReturn = BaudRate.B4800 ; break;
case 9600 : toReturn = BaudRate.B9600 ; break;
case 38400 : toReturn = BaudRate.B38400 ; break;
case 115200: toReturn = BaudRate.B115200; break;
}
 
return toReturn;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getDataBits()
*/
@Override
public IOSerialPort.DataBits getDataBits(){
int dataBits;
DataBits bits;
if( closed ){
throw new IllegalStateException( "Cannot get the data bits once the port has been closed." );
}
dataBits = getCharSizeInternal();
bits = DataBits.DATABITS_8;
 
switch( dataBits ){
case 8: bits = DataBits.DATABITS_8; break;
case 7: bits = DataBits.DATABITS_7; break;
case 6: bits = DataBits.DATABITS_6; break;
case 5: bits = DataBits.DATABITS_5; break;
}
 
return bits;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getStopBits()
*/
@Override
public IOSerialPort.StopBits getStopBits(){
int stopBits;
StopBits bits;
if( closed ){
throw new IllegalStateException( "Cannot get stop bits once the port has been closed." );
}
stopBits = getStopBitsInternal();
bits = StopBits.STOPBITS_1;
 
switch( stopBits ){
case 1: bits = StopBits.STOPBITS_1; break;
case 2: bits = StopBits.STOPBITS_2; break;
}
 
return bits;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getParity()
*/
@Override
public IOSerialPort.Parity getParity(){
int parity;
Parity par;
if( closed ){
throw new IllegalStateException( "Cannot get the parity once the port has been closed." );
}
parity = getParityInternal();
par = Parity.NONE;
 
switch( parity ){
case 0: par = Parity.NONE; break;
case 1: par = Parity.ODD; break;
case 2: par = Parity.EVEN; break;
}
 
return par;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getFlowControl()
*/
@Override
public IOSerialPort.FlowControl getFlowControl(){
int flowControl;
FlowControl cont;
if( closed ){
throw new IllegalStateException( "Cannot get the flow once the port has been closed." );
}
flowControl = getFlowControlInternal();
cont = FlowControl.NONE;
 
switch( flowControl ){
case 0: cont = FlowControl.NONE; break;
case 1: cont = FlowControl.HARDWARE; break;
case 2: cont = FlowControl.SOFTWARE; break;
}
 
return cont;
}
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setFlowControl(com.rm5248.serial.SerialPort.FlowControl)
*/
@Override
public void setFlowControl( FlowControl flow ){
if( closed ){
throw new IllegalStateException( "Cannot set flow once the port has been closed." );
}
switch( flow ){
case HARDWARE: setFlowControl( 1 ); break;
case NONE: setFlowControl( 0 ); break;
case SOFTWARE: setFlowControl( 2 ); break;
}
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#setSerialChangeListener(com.rm5248.serial.SerialChangeListener)
*/
@Override
public void setSerialChangeListener( SerialChangeListener listen ){
if( serialListen != null ){
serialListen.doStop();
}
if( listen != null ){
serialListen = new SerialStateListener( listen );
new Thread( serialListen, "SerialListen" ).start();
}
 
}
 
public String toString(){
return "Serial Port " + portName + ":" + getBaudRate();
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#getPortName()
*/
@Override
public String getPortName(){
return portName;
}
/**
* This method is called when the state of the serial lines is changed.
*
* @param newState
*/
void postSerialChangedEvent( SerialLineState newState ){
if( !state.equals( newState ) ){
state = newState;
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
}
 
/**
* Open the specified port, return an internal handle to the data structure for this port.
*
* @param portName
* @return
*/
private native int openPort( String portName, int baudRate, int dataBits, int stopBits, int parity, int flowControl ) throws NoSuchPortException, NotASerialPortException;
 
/**
* Open the specified port, return an internal handle for the data of this port.
* This method DOES NOT set any of the serial port settings
*
* @param portName The port to open
* @return
*/
private native int openPort( String portName ) throws NoSuchPortException, NotASerialPortException;
 
/**
* Close this port, release all native resources
*/
private native void doClose();
 
/**
* Set the baud rate in the native code.
*
* @param baudRate
* @return
*/
private native boolean setBaudRate( int baudRate );
 
private native int getBaudRateInternal();
 
/**
* Set the number of stop bits, once the port has been opened.
*
* @param stopBits
* @return
*/
private native boolean setStopBits( int stopBits );
 
private native int getStopBitsInternal();
 
/**
* Set the character size, once the port has been opened.
* This should probably be called 'setDataBits'
*
* @param charSize
* @return
*/
private native boolean setCharSize( int charSize );
 
private native int getCharSizeInternal();
 
/** Set the parity once the port has been opened.
*
* @param parity 0 = None, 1 = Odd, 2 = Even
* @return
*/
private native boolean setParity( int parity );
 
private native int getParityInternal();
 
/** Set the flow control once the port has been opened.
*
*
* @param flowControl 0 = None, 1 = hardware, 2 = software
* @return
*/
private native boolean setFlowControl( int flowControl );
 
private native int getFlowControlInternal();
 
/** Get the serial line state, but don't block when getting it
*
* @return
*/
private native int getSerialLineStateInternalNonblocking();
/**
* Set the state of the serial line.
* @return
*/
private native int setSerialLineStateInternal( SerialLineState s );
//
// Static Methods
//
/**
* Get the major version of this library. For example, if this is version
* 0.2, this returns 0
*/
public static int getMajorVersion(){
return 0;
}
/**
* Get the minor version of this library. For example, if this is version
* 0.2, this returns 2.
*/
public static int getMinorVersion(){
return 4;
}
/**
* Get the major version of the native code. This should match up with
* {@link #getMajorVersion() getMajorVersion()}, although this is not
* guaranteed. For example, if this is version 0.2, this returns 0
*/
public static native int getMajorNativeVersion();
/**
* Get the minor version of the native code. This should match up with
* {@link #getMinorVersion() getMinorVersion()}, although this is not
* guaranteed. For example, if this is version 0.2, this returns 2.
*/
public static native int getMinorNativeVersion();
/**
* <p>
* Get an array of all the serial ports on the system. For example, on
* Windows this will return {@code { "COM1", "COM3", .... } } depending on how
* many serial devices you have plugged in. On Linux, this returns
* {@code { "/dev/ttyS0", "/dev/ttyUSB0", "/dev/symlink", ... } }
* It will not resolve symlinks, such that if there is a symlink
* from {@code /dev/symlink } to {@code /dev/ttyUSB0 }, they will both show up.
* </p>
* <p>
* <b>NOTE:</b> this will only return ports that you have permissions to
* open.
* </p>
*
* @return
*/
public static native String[] getSerialPorts();
 
}
/trunk/JavaSerial/src/com/rm5248/serial/BufferedSerialInputStream.java
20,10 → 20,10
private byte[] buffer;
private int bufferBegin;
private int bufferEnd;
private SerialPort callback;
private IOSerialPort callback;
private IOException exceptionToThrow;
 
BufferedSerialInputStream( SerialInputStream s, SerialPort callback ){
BufferedSerialInputStream( SerialInputStream s, IOSerialPort callback ){
stream = s;
buffer = new byte[ 500 ];
bufferBegin = 0;