Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 100 → Rev 101

/trunk/JavaSerial/src/com/rm5248/serial/NIOSerialPort.java
File deleted
/trunk/JavaSerial/src/com/rm5248/serial/SerialByteChannel.java
File deleted
/trunk/JavaSerial/src/com/rm5248/serial/IOSerialPort.java
File deleted
/trunk/JavaSerial/src/com/rm5248/serial/SerialPort.java
3,6 → 3,7
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
 
94,6 → 95,36
}
}
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;
}
}
/**
* Represents the BaudRate that the SerialPort uses.
*/
159,6 → 190,41
SOFTWARE
}
/**
* Flag to set if you do not want to get any control line notifications
*/
public static final int NO_CONTROL_LINE_CHANGE = 0x00;
/**
* Flag to set if you want to get notifications on Data Terminal Ready line change
*/
public static final int CONTROL_LINE_DTR_CHANGE = 0x01;
/**
* Flag to set if you want to get notifications on Request To Send line change
*/
public static final int CONTROL_LINE_RTS_CHANGE = 0x02;
/**
* Flag to set if you want to get notifications on Carrier Detect line change
*/
public static final int CONTROL_LINE_CD_CHANGE = 0x03;
/**
* Flag to set if you want to get notifications on Clear To Send line change
*/
public static final int CONTROL_LINE_CTS_CHANGE = 0x04;
/**
* Flag to set if you want to get notifications on Data Set Ready line change
*/
public static final int CONTROL_LINE_DSR_CHANGE = 0x05;
/**
* Flag to set if you want to get notifications on Ring Indicagor line change
*/
public static final int CONTROL_LINE_RI_CHANGE = 0x06;
/**
* All CONTROL_LINE_XXX_CHANGE values OR'd together
*/
public static final int ALL_CONTROL_LINES = CONTROL_LINE_DTR_CHANGE |
CONTROL_LINE_RTS_CHANGE | CONTROL_LINE_CD_CHANGE | CONTROL_LINE_CTS_CHANGE |
CONTROL_LINE_DSR_CHANGE | CONTROL_LINE_RI_CHANGE;
/* 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.
165,19 → 231,257
* 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.
*/
protected int handle;
private int handle;
/* Make sure we don't close ourselves twice */
protected boolean closed;
private boolean closed;
/* The name of the port that's currently open */
private String portName;
/* Cache of the last gotten serial line state */
protected volatile SerialLineState state;
private volatile SerialLineState state;
/* 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;
/* Runs in the background to check for serial port events */
private SerialStateListener serialListen;
/* Used for synchronizing serialListen */
private Object serialListenSync;
/* Depending on what control line changes we want to get back, this mask is set. */
private int controlLineFlags;
/**
* 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 SerialPort( String portName ) throws NoSuchPortException, NotASerialPortException {
this( portName, ALL_CONTROL_LINES );
}
/**
* Open the specified port, 9600 baud, 8 data bits, 1 stop bit, no parity, no flow control,
* looking for the specified control lines
*
* @param portName The name of the port to open
* @param controlLineFlags The control lines to get a notification for when they change.
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
public SerialPort( String portName, int controlLineFlags ) throws NoSuchPortException, NotASerialPortException {
this( portName, BaudRate.B9600, controlLineFlags );
}
/**
* Open up a serial port, but allow the user to keep the current settings of the serial port.
* Will notify on all control line changes.
*
* @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 {
this( portName, keepSettings, ALL_CONTROL_LINES );
}
 
/**
* 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 controlFlags The control flags to listen for changes for. This is a bitwise-OR of CONTROL_LINE_XXX_CHANGE, or
* NO_CONTROL_LINE_CHANGE if you don't care about getting notified about the control line changes.
* @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, int controlFlags ) throws NoSuchPortException, NotASerialPortException{
if( portName == null ){
throw new IllegalArgumentException( "portName must not be null" );
}
if( keepSettings ){
this.handle = openPort( portName );
this.portName = portName;
if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
inputStream = new SimpleSerialInputStream( handle );
}else{
SerialInputStream sis = new SerialInputStream( handle );
inputStream = sis;
bis = new BufferedSerialInputStream( sis, this );
}
outputStream = new SerialOutputStream( handle );
closed = false;
this.controlLineFlags = controlFlags;
 
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;
if( controlLineFlags != NO_CONTROL_LINE_CHANGE ){
serialListenSync = new Object();
new Thread( bis, "BufferedSerialReader-" + portName ).start();
}
}else{
doOpenSerialPort( portName, BaudRate.B9600, DataBits.DATABITS_8,
StopBits.STOPBITS_1, Parity.NONE, FlowControl.NONE, controlFlags );
}
}
 
/**
* Open the specified port, no flow control, 8 data bits
*
* @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, ALL_CONTROL_LINES );
}
/**
* 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 controlLines The control lines to be notifie don a change in.
* @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, int controlLines )
throws NoSuchPortException, NotASerialPortException {
this( portName, rate, DataBits.DATABITS_8, controlLines );
}
 
/**
* 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, ALL_CONTROL_LINES );
}
/**
* 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, int controlLineFlags )
throws NoSuchPortException, NotASerialPortException {
doOpenSerialPort( portName, rate, data,
StopBits.STOPBITS_1, Parity.NONE, FlowControl.NONE, controlLineFlags );
}
 
/**
* 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 {
doOpenSerialPort( portName, rate, data,
stop, Parity.NONE, FlowControl.NONE, ALL_CONTROL_LINES );
}
/**
* 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, int controlFlags )
throws NoSuchPortException, NotASerialPortException {
doOpenSerialPort( portName, rate, data,
stop, Parity.NONE, FlowControl.NONE, controlFlags );
}
 
/**
* Open the specified port, no flow control, with all control line flags
*
* @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 {
doOpenSerialPort( portName, rate, data, stop, parity, FlowControl.NONE, ALL_CONTROL_LINES );
}
/**
* Open the specified port, no flow control, with the specified control line flags
*
* @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
* @param controlLineFlags A bitwise OR of any the CONTORL_LINE_XXX_CHANGE flags, or NO_CONTROL_LINE_CHANGE
* @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, int controlLineFlags )
throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, parity, FlowControl.NONE, controlLineFlags );
}
/**
* 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 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
185,8 → 489,35
* @throws NoSuchPortException If this port does not exist
* @throws NotASerialPortException If the specified port is not a serial port
*/
protected SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow )
public SerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow )
throws NoSuchPortException, NotASerialPortException {
this( portName, rate, data, stop, parity, flow, ALL_CONTROL_LINES );
}
/**
* Open the specified port, defining all options
*
* @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
* @param flow The flow control of the line
* @param controlFlags The control flags to listen for changes for. This is a bitwise-OR of CONTROL_LINE_XXX_CHANGE, or
* NO_CONTROL_LINE_CHANGE if you don't care about getting notified about the control line changes.
* @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, int controlFlags )
throws NoSuchPortException, NotASerialPortException {
doOpenSerialPort( portName, rate, data, stop, parity, flow, controlFlags );
}
/**
* The actual method that opens up the serial port, unless we are keeping our settings.
*/
private void doOpenSerialPort( String portName, BaudRate rate, DataBits data, StopBits stop, Parity parity, FlowControl flow, int controlFlags )
throws NoSuchPortException, NotASerialPortException {
int myRate = 0;
int myData = 0;
int myStop = 0;
194,6 → 525,7
int myFlow = 0;
SerialLineState s;
int state;
SerialInputStream sis;
//Check for null values in our arguments
if( portName == null ){
223,6 → 555,7
//Okay, looks like we're good!
this.portName = portName;
closed = false;
this.controlLineFlags = controlFlags;
 
switch( rate ){
case B0 : myRate = 0; break;
268,6 → 601,14
}
 
handle = openPort(portName, myRate, myData, myStop, myParity, myFlow);
if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
inputStream = new SimpleSerialInputStream( handle );
}else{
sis = new SerialInputStream( handle );
inputStream = sis;
bis = new BufferedSerialInputStream( sis, this );
}
outputStream = new SerialOutputStream( handle );
 
s = new SerialLineState();
state = getSerialLineStateInternalNonblocking();
291,30 → 632,13
}
 
this.state = s;
}
/**
* 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
*/
protected 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;
this.closed = false;
}else{
this.handle = openPort( portName, 9600, 8, 1, 0, 0 );
if( controlLineFlags != NO_CONTROL_LINE_CHANGE ){
serialListenSync = new Object();
new Thread( bis, "BufferedSerialReader-" + portName ).start();
}
}
 
/**
* Set the Baud Rate for this port.
366,10 → 690,45
if( closed ) return;
closed = true;
doClose();
if( serialListen != null ){
serialListen.doStop();
}
if( serialListenSync != null ){
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
}
/**
* Get the input stream used to talk to this device.
*/
public InputStream getInputStream(){
if( isClosed() ){
throw new IllegalStateException( "Cannot get the input stream once the port has been closed." );
}
 
if( controlLineFlags == NO_CONTROL_LINE_CHANGE ){
return inputStream;
}
 
return bis;
}
 
/**
* Get the OutputStream used to talk to this device.
*/
public OutputStream getOutputStream(){
if( isClosed() ){
throw new IllegalStateException( "Cannot get the output stream once the port has been closed." );
}
 
return outputStream;
}
 
/**
* Set the stop bits of the serial port, after the port has been opened.
*
* @param stop
500,6 → 859,8
// this.postSerialChangedEvent( state );
// }
}
 
/**
* Get the baud rate of the serial port.
666,6 → 1027,15
* @param listen The listener which gets events
*/
public void setSerialChangeListener( SerialChangeListener listen ){
if( serialListen != null ){
serialListen.doStop();
}
 
if( listen != null && !(controlLineFlags == NO_CONTROL_LINE_CHANGE) ){
serialListen = new SerialStateListener( listen );
new Thread( serialListen, "SerialListen-" + portName ).start();
}
 
}
 
/**
676,6 → 1046,52
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 ) ){
SerialLineState oldState = state;
boolean update = false;
state = newState;
 
//At this point, we know what has changed, but we must check our bitmask to see if we should
//propogate this change back up to the interested class.
if( oldState.carrierDetect != newState.carrierDetect &&
(controlLineFlags & CONTROL_LINE_CD_CHANGE) != 0 ){
update = true;
}
if( oldState.clearToSend != newState.clearToSend &&
(controlLineFlags & CONTROL_LINE_CTS_CHANGE) != 0){
update = true;
}
if( oldState.dataSetReady != newState.dataSetReady &&
(controlLineFlags & CONTROL_LINE_DSR_CHANGE) != 0 ){
update = true;
}
if( oldState.dataTerminalReady != newState.dataTerminalReady &&
(controlLineFlags & CONTROL_LINE_DTR_CHANGE) != 0 ){
update = true;
}
if( oldState.requestToSend != newState.requestToSend &&
(controlLineFlags & CONTROL_LINE_RTS_CHANGE) != 0 ){
update = true;
}
if( oldState.ringIndicator != newState.ringIndicator &&
(controlLineFlags & CONTROL_LINE_RI_CHANGE) != 0 ){
update = true;
}
if( update ){
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
}
}
/**
* Open the specified port, return an internal handle to the data structure for this port.
*
/trunk/JavaSerial/src/com/rm5248/serial/BufferedSerialInputStream.java
20,15 → 20,15
private byte[] buffer;
private int bufferBegin;
private int bufferEnd;
private IOSerialPort callback;
private SerialPort callback;
private IOException exceptionToThrow;
 
BufferedSerialInputStream( SerialInputStream s, IOSerialPort callback ){
BufferedSerialInputStream( SerialInputStream s, SerialPort serialPort ){
stream = s;
buffer = new byte[ 500 ];
bufferBegin = 0;
bufferEnd = 0;
this.callback = callback;
this.callback = serialPort;
exceptionToThrow = null;
}