Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 97 → Rev 98

/branches/JavaSerialNIO/src/com/rm5248/serial/NIOSerialPort.java
0,0 → 1,28
package com.rm5248.serial;
 
import java.io.IOException;
import java.nio.channels.ByteChannel;
 
/**
* An implementation of a serial port that uses NIO.
*
* @author rm5248
*
*/
public class NIOSerialPort extends SerialPort {
/* The channel that we read/write */
private SerialByteChannel byteChannel;
 
public NIOSerialPort(String portName, BaudRate rate, DataBits data,
StopBits stop, Parity parity, FlowControl flow)
throws NoSuchPortException, NotASerialPortException {
super(portName, rate, data, stop, parity, flow);
// TODO Auto-generated constructor stub
byteChannel = new SerialByteChannel( handle, this );
}
 
public ByteChannel getByteChannel(){
return byteChannel;
}
}
/branches/JavaSerialNIO/src/com/rm5248/serial/IOSerialPort.java
0,0 → 1,319
package com.rm5248.serial;
 
import java.io.Closeable;
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 extends SerialPort implements Closeable {
 
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 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 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{
super( portName, keepSettings );
 
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 );
 
SerialLineState s = new SerialLineState();
int state = 0;//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( !ignoreControlLines ){
serialListenSync = new Object();
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 {
super( portName, rate, data, stop, parity, flow );
SerialInputStream sis;
SerialLineState s;
int state;
 
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();
}
 
/**
* 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( ignoringControlLines ){
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;
}
 
/* (non-Javadoc)
* @see com.rm5248.serial.SerialPortI#close()
*/
@Override
public void close(){
if( isClosed() ) return;
super.close();
if( serialListen != null ){
serialListen.doStop();
}
if( serialListenSync != null ){
synchronized( serialListenSync ){
serialListenSync.notify();
}
}
}
 
public String toString(){
return "IOSerial Port " + getPortName() + ":" + getBaudRate();
}
 
 
/**
* 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();
}
}
}
 
@Override
public void setSerialChangeListener( SerialChangeListener listen ){
if( serialListen != null ){
serialListen.doStop();
}
 
if( listen != null && !ignoringControlLines ){
serialListen = new SerialStateListener( listen );
new Thread( serialListen, "SerialListen" ).start();
}
 
}
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialByteChannel.java
0,0 → 1,54
package com.rm5248.serial;
 
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
 
/**
* An implementation of the ByteChannel interface for use with serial ports.
*
* @author rm5248
*
*/
class SerialByteChannel implements ByteChannel {
@SuppressWarnings("unused")
private int handle;
private SerialPort parent;
SerialByteChannel( int handle, SerialPort parent ){
this.handle = handle;
this.parent = parent;
}
 
@Override
public int read(ByteBuffer arg0) throws IOException {
// TODO Auto-generated method stub
System.out.println( "remaining: " + arg0.remaining() );
return 0;
}
 
@Override
public void close() throws IOException {
// You must close the SerialPort, not the channel.
}
 
@Override
public boolean isOpen() {
return parent.closed;
}
 
@Override
public int write(ByteBuffer arg0) throws IOException {
// TODO Auto-generated method stub
byte[] bb = new byte[ arg0.remaining() ];
System.out.println( "arg0 pos: " + arg0.position() );
System.out.println( "arg0 remain: " + arg0.remaining() );
arg0.get( bb, arg0.position(), arg0.remaining() );
System.out.println( "bb size: " + bb.length );
return 0;
}
 
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialPort.java
0,0 → 1,817
package com.rm5248.serial;
 
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
 
/**
* A SerialPort represents a serial port on the system.
*
* All SerialPorts must extend this class. It is unable to be instantiated, except
* by subclasses.
*
* See the documentation for the subclasses on how to create
* a specific instance of a SerialPort. The two main subclasses are IOSerialPort and
* NIOSerialPort.
*
* @author rm5248
*
*/
public class SerialPort {
//The first time this class is referenced, we need to load the library.
static{
loadNativeLibrary();
}
/**
* Load the native library.
*
* There are two important system properties that can be set here:
*
* com.rm5248.javaserial.lib.path - give the directory name that the JNI code is located in
* com.rm5248.javaserial.lib.name - explicitly give the name of the library(the default is 'javaserial')
*
* This is based largely off of SQLite-JDBC( https://github.com/xerial/sqlite-jdbc )
*/
private static void loadNativeLibrary() {
String nativeLibraryPath = System.getProperty( "com.rm5248.javaserial.lib.path" );
String nativeLibraryName = System.getProperty( "com.rm5248.javaserial.lib.name" );
if( nativeLibraryName == null ){
nativeLibraryName = System.mapLibraryName( "javaserial" );
if( nativeLibraryName.endsWith( "dylib" ) ){
//mac uses jnilib instead of dylib for some reason
nativeLibraryName.replace( "dylib", "jnilib" );
}
}
if( nativeLibraryPath != null ){
File libToLoad = new File(nativeLibraryPath, nativeLibraryName);
System.load( libToLoad.getAbsolutePath() );
return;
}
//if we get here, that means that we must extract the JNI from the jar
try {
File extractedLib;
Path tempFolder;
String osName;
String arch;
InputStream library;
osName = System.getProperty( "os.name" );
if( osName.contains( "Windows" ) ){
osName = "Windows";
}else if( osName.contains( "Mac" ) || osName.contains( "Darwin" ) ){
osName = "Mac";
}else if( osName.contains( "Linux" ) ){
osName = "Linux";
}else{
osName = osName.replaceAll( "\\W", "" );
}
arch = System.getProperty( "os.arch" );
arch.replaceAll( "\\W", "" );
//create the temp folder to extract the library to
tempFolder = Files.createTempDirectory( "jserial" );
tempFolder.toFile().deleteOnExit();
extractedLib = new File( tempFolder.toFile(), nativeLibraryName );
//now let's extract the proper library
library = SerialPort.class.getResourceAsStream( "NativeCode/" +
osName + "/" + arch + "/" + nativeLibraryName );
Files.copy( library, extractedLib.toPath() );
System.load( extractedLib.getAbsolutePath() );
} catch (IOException e) {
throw new UnsatisfiedLinkError( "Unable to create temp directory or extract: " + e.getMessage() );
}
}
/**
* 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
}
/* 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.
*/
protected int handle;
/* Make sure we don't close ourselves twice */
protected 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;
/**
* 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
*/
protected 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);
 
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;
}
/**
* 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 );
}
}
 
/**
* 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 );
}
public boolean isClosed(){
return closed;
}
 
public void finalize(){
close();
}
public void close(){
if( closed ) return;
closed = true;
doClose();
}
 
/**
* 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 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 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 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 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 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 ){
}
 
/**
* Get the name of the serial port that this object represents.
* @return
*/
public String getPortName(){
return portName;
}
/**
* 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
*/
protected 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 5;
}
/**
* 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();
 
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialInputStream.java
0,0 → 1,63
package com.rm5248.serial;
 
import java.io.IOException;
import java.io.InputStream;
 
/**
* 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 */
@SuppressWarnings("unused")
private int handle;
 
SerialInputStream( 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;
}
 
/**
* 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;
}
/branches/JavaSerialNIO/src/com/rm5248/serial/BufferedSerialInputStream.java
0,0 → 1,157
package com.rm5248.serial;
 
import java.io.IOException;
import java.io.InputStream;
 
/**
* Okay, so the problem here is that we need to be continually reading from the serial port,
* because on Windows we can't simultaneously listen for events and listen for changes on
* the serial port. We can only do that in one place. So, to get around that problem,
* this BufferedSerialInputStream simply wraps the normal SerialInputStream and only
* returns actual data. SerialInputStream gives us back data on the status of the serial line,
* as well as if the byte it gave us is real or not.
*
* @author rm5248
*
*/
class BufferedSerialInputStream extends InputStream implements Runnable {
 
private SerialInputStream stream;
private byte[] buffer;
private int bufferBegin;
private int bufferEnd;
private IOSerialPort callback;
private IOException exceptionToThrow;
 
BufferedSerialInputStream( SerialInputStream s, IOSerialPort callback ){
stream = s;
buffer = new byte[ 500 ];
bufferBegin = 0;
bufferEnd = 0;
this.callback = callback;
exceptionToThrow = null;
}
 
@Override
public int read() throws IOException {
int byteToReturn;
if( bufferBegin != bufferEnd ){
//we already have a character
byteToReturn = buffer[ bufferBegin++ ];
if( bufferBegin >= buffer.length ){
//wrap around to the start of the array
bufferBegin = 0;
}
}else{
synchronized( buffer ){
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if( exceptionToThrow != null ){
throw exceptionToThrow;
}
}
byteToReturn = buffer[ bufferBegin++ ];
if( bufferBegin >= buffer.length ){
//wrap around to the start of the array
bufferBegin = 0;
}
}
return byteToReturn;
}
 
@Override
public void run() {
while( true ){
int byteRead = 0;
try {
byteRead = stream.read();
} catch (IOException e) {
synchronized( buffer ){
exceptionToThrow = e;
buffer.notify();
}
break;
}
SerialLineState s = new SerialLineState();
 
if( ( byteRead & ( 0x01 << 9) ) > 0 ){
s.carrierDetect = true;
}
if( ( byteRead & (0x01 << 10 ) ) > 0 ){
s.clearToSend = true;
}
if( ( byteRead & (0x01 << 11 ) ) > 0 ){
s.dataSetReady = true;
}
if( ( byteRead & (0x01 << 12 ) ) > 0 ){
s.dataTerminalReady = true;
}
if( ( byteRead & (0x01 << 13 ) ) > 0 ){
s.requestToSend = true;
}
if( ( byteRead & (0x01 << 14 ) ) > 0 ){
s.ringIndicator = true;
}
 
if( ( byteRead & ( 0x01 << 15 ) ) > 0 ){
//this is a valid byte
synchronized( buffer ){
if( bufferEnd + 1 >= buffer.length ){
//loop back around to the beginning
bufferEnd = 0;
}
buffer[ bufferEnd++ ] = (byte)( byteRead & 0xFF );
if( bufferEnd == bufferBegin ){
//the end has wrapped around, increment the beginning
bufferBegin++;
if( bufferBegin >= buffer.length ){
bufferBegin = 0;
}
}
buffer.notify();
}
}
callback.postSerialChangedEvent( s );
}
}
@Override
public int available(){
if( bufferEnd < bufferBegin ){
//special case - we have looped around
return ( buffer.length - bufferBegin ) + bufferEnd;
}else{
return bufferEnd - bufferBegin;
}
}
@Override
public int read( byte[] b, int off, int len ) throws IOException{
int readSoFar = 0;
if( len == 0 ){
return 0;
}
for( int x = off; x < len; x++ ){
b[x] = (byte)read();
readSoFar++;
if( readSoFar > 0 && available() == 0 ){
break;
}
}
return readSoFar;
}
 
}
/branches/JavaSerialNIO/src/com/rm5248/serial/NoSuchPortException.java
0,0 → 1,24
package com.rm5248.serial;
 
/**
* This exception is thrown when you attempt to open up a port that does not exist.
*
* @author rm5248
*
*/
public class NoSuchPortException extends Exception {
 
/**
* Generated by Eclipse
*/
private static final long serialVersionUID = -5218448691940726352L;
 
/**
* Create a new exception with the specified error.
*
* @param status
*/
public NoSuchPortException( String status ){
super( status );
}
}
/branches/JavaSerialNIO/src/com/rm5248/serial/NotASerialPortException.java
0,0 → 1,23
package com.rm5248.serial;
 
/**
* This exception is thrown when the device that you have opened is not a serial port.
*
* @author rm5248
*
*/
public class NotASerialPortException extends Exception {
 
/**
* Generated by Eclipse
*/
private static final long serialVersionUID = 5606767768689212862L;
 
/** Create a new exception if this is not a serial port
*
* @param message
*/
public NotASerialPortException( String message ){
super( message );
}
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialLineState.java
0,0 → 1,56
package com.rm5248.serial;
 
/**
* This class represents the current state of the lines on the serial port.
* You can also use this class to set the state of the serial port.
*
* Note that all of these options may not be available depending on the
* serial port that is in use, and/or the platform that you are running on.
*
*/
public class SerialLineState {
public boolean carrierDetect;
public boolean clearToSend;
public boolean dataSetReady;
public boolean dataTerminalReady;
public boolean ringIndicator;
public boolean requestToSend;
public SerialLineState(){
carrierDetect = false;
clearToSend = false;
dataSetReady = false;
dataTerminalReady = false;
ringIndicator = false;
requestToSend = false;
}
@Override
public boolean equals( Object o ){
if( o instanceof SerialLineState ){
SerialLineState s = (SerialLineState)o;
return ( s.carrierDetect == carrierDetect ) &&
( s.clearToSend == clearToSend ) &&
( s.dataSetReady == dataSetReady ) &&
( s.dataTerminalReady == dataTerminalReady ) &&
( s.ringIndicator == ringIndicator ) &&
( s.requestToSend == requestToSend );
}
return false;
}
@Override
public String toString(){
return "[SerialLineState: " +
"CD: " + carrierDetect +
" CTS: " + clearToSend +
" DSR: " + dataSetReady +
" DTR: " + dataTerminalReady +
" RI: " + ringIndicator +
" RTS: " + requestToSend + "]";
}
 
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialOutputStream.java
0,0 → 1,28
package com.rm5248.serial;
 
import java.io.IOException;
import java.io.OutputStream;
 
class SerialOutputStream extends OutputStream{
/* The handle to write to */
@SuppressWarnings("unused")
private int handle;
 
SerialOutputStream( int handle ){
this.handle = handle;
}
 
@Override
public void write(int b) throws IOException {
writeByte( b );
}
@Override
public void write( byte[] arr ) throws IOException{
writeByteArray( arr );
}
 
private native void writeByte( int toWrite ) throws IOException;
private native void writeByteArray( byte[] array ) throws IOException;
}
/branches/JavaSerialNIO/src/com/rm5248/serial/SerialChangeListener.java
0,0 → 1,16
package com.rm5248.serial;
 
/**
* This interface lets the user do something when the serial line state changes.
* The state is defined by how the lines are currently set.
*
*/
public interface SerialChangeListener {
 
/**
* Fired when the state on the serial line changes.
*
* @param state
*/
public void serialStateChanged( SerialLineState state );
}
/branches/JavaSerialNIO/.classpath
0,0 → 1,20
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
/branches/JavaSerialNIO/NativeCode/com_rm5248_serial_SerialInputStream.h
0,0 → 1,31
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_rm5248_serial_SerialInputStream */
 
#ifndef _Included_com_rm5248_serial_SerialInputStream
#define _Included_com_rm5248_serial_SerialInputStream
#ifdef __cplusplus
extern "C" {
#endif
#undef com_rm5248_serial_SerialInputStream_MAX_SKIP_BUFFER_SIZE
#define com_rm5248_serial_SerialInputStream_MAX_SKIP_BUFFER_SIZE 2048L
/*
* Class: com_rm5248_serial_SerialInputStream
* Method: readByte
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_readByte
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialInputStream
* Method: getAvailable
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_getAvailable
(JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif
/branches/JavaSerialNIO/NativeCode/SerialPortImpl.c
0,0 → 1,1719
#ifdef _WIN32
#include <windows.h>
/* Make inline functions work */
#define inline __inline
#define SPEED_SWITCH(SPD,io) case SPD: io.BaudRate = CBR_##SPD; break;
#define GET_SPEED_SWITCH(SPD,io) case CBR_##SPD: return SPD;
#define GET_SERIAL_PORT_STRUCT( port, io_name ) DCB io_name = {0};\
io_name.DCBlength = sizeof( io_name ); \
if (!GetCommState( port, &io_name ) ) { \
printf("bad get comm\n");\
return -1;\
}
#define SET_SERIAL_PORT_STRUCT( port, io_name ) if( !SetCommState( port, &io_name ) ){\
printf("bad set comm\n");\
return 0;\
}
#define close(handle) CloseHandle(handle)
#else
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <errno.h>
 
#ifndef ENOMEDIUM
#define ENOMEDIUM ENODEV
#endif
 
#ifdef CRTSCTS
#define HW_FLOW CRTSCTS
#elif CNEW_RTSCTS
#define HW_FLOW CNEW_RTSCTS
#endif
#define SPEED_SWITCH(SPD,io) case SPD: cfsetospeed( &io, B##SPD ); cfsetispeed( &io, B##SPD ); break;
#define GET_SPEED_SWITCH(SPD,io) case B##SPD: return SPD;
#define GET_SERIAL_PORT_STRUCT( port, io_name ) struct termios io_name; \
if( tcgetattr( port, &io_name ) < 0 ){ \
return -1; \
}
#define SET_SERIAL_PORT_STRUCT( port, io_name ) if( tcsetattr( port, TCSANOW, &io_name ) < 0 ){\
return -1;\
}
#endif
 
#include <stdlib.h>
#include <errno.h>
#include <string.h>
 
//
// Local Includes
//
#include "com_rm5248_serial_SerialPort.h"
#include "com_rm5248_serial_SerialInputStream.h"
#include "com_rm5248_serial_SerialOutputStream.h"
#include "com_rm5248_serial_SimpleSerialInputStream.h"
 
//
// Struct Definitions
//
struct port_descriptor{
#ifdef _WIN32
HANDLE port;
#else
int port;
/* There appears to be a case where we can free() the port_descriptor
* after the select() call in SerialInputStream_readByte().
* This means that we segfault on the FD_SET() call.
* This mutex will keep us alive until we have exited the
* readByte() call.
*/
pthread_mutex_t in_use;
#endif
};
 
//
// Local Variables
//
static struct port_descriptor** port_list = NULL;
static int port_list_size;
 
#ifdef _WIN32
//Unfortunately, Windows does not let us get the state of the DTR/RTS lines.
//So, we need to keep track of that manually.
int winDTR = 0;
int winRTS = 0;
#endif
 
//
// Helper Methods
//
static inline jint get_handle(JNIEnv * env, jobject obj){
jfieldID fid;
jint array_pos;
jclass cls = (*env)->GetObjectClass( env, obj );
 
fid = (*env)->GetFieldID( env, cls, "handle", "I" );
if( fid == 0 ){
return -1;
}
 
array_pos = (*env)->GetIntField( env, obj, fid );
 
return array_pos;
}
 
static inline jboolean get_bool( JNIEnv* env, jobject obj, const char* name ){
jfieldID fid;
jboolean boolVal;
jclass cls = (*env)->GetObjectClass( env, obj );
 
fid = (*env)->GetFieldID( env, cls, name, "Z" );
if( fid == 0 ){
return 0; //not really sure what error to set here...
}
 
boolVal = (*env)->GetBooleanField( env, obj, fid );
 
return boolVal;
}
 
static inline int set_baud_rate( struct port_descriptor* desc, int baud_rate ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
switch( baud_rate ){
#ifndef _WIN32
/* Note that Windows only supports speeds of 110 and above */
SPEED_SWITCH(0,newio);
SPEED_SWITCH(50,newio);
SPEED_SWITCH(75,newio);
#endif
SPEED_SWITCH(110,newio);
#ifndef _WIN32
/* Windows does not support speeds of 134, 150, or 200 */
SPEED_SWITCH(134,newio);
SPEED_SWITCH(150,newio);
SPEED_SWITCH(200,newio);
#endif
SPEED_SWITCH(300,newio);
SPEED_SWITCH(600,newio);
SPEED_SWITCH(1200,newio);
#ifndef _WIN32
/* Windows does not support 1800 */
SPEED_SWITCH(1800,newio);
#endif
SPEED_SWITCH(2400,newio);
SPEED_SWITCH(4800,newio);
SPEED_SWITCH(9600,newio);
SPEED_SWITCH(19200,newio);
SPEED_SWITCH(38400,newio);
SPEED_SWITCH(115200,newio);
}
 
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
static inline int set_raw_input( struct port_descriptor* desc ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
newio.fBinary = TRUE;
newio.fParity = TRUE;
newio.fOutxCtsFlow = FALSE;
newio.fOutxDsrFlow = FALSE;
newio.fDtrControl = DTR_CONTROL_DISABLE;
newio.fDsrSensitivity = FALSE;
newio.fOutX = FALSE;
newio.fInX = FALSE;
newio.fNull = FALSE;
newio.fRtsControl = FALSE;
//Set the timeouts
{
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
if( SetCommTimeouts( desc->port, &timeouts ) == 0 ){
printf("bad timeout\n"); fflush(stdout);}
}
#else
newio.c_iflag |= IGNBRK;
newio.c_iflag &= ~BRKINT;
newio.c_iflag &= ~ICRNL;
newio.c_oflag = 0;
newio.c_lflag = 0;
newio.c_cc[VTIME] = 0;
newio.c_cc[VMIN] = 1;
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
/**
* @param data_bits The number of data bits
*/
static inline int set_data_bits( struct port_descriptor* desc, int data_bits ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
newio.ByteSize = data_bits;
#else
newio.c_cflag &= ~CSIZE;
if( data_bits == 8 ){
newio.c_cflag |= CS8;
}else if( data_bits == 7 ){
newio.c_cflag |= CS7;
}else if( data_bits == 6 ){
newio.c_cflag |= CS6;
}else if( data_bits == 5 ){
newio.c_cflag |= CS5;
}
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
/**
* @param stop_bits 1 for 1, 2 for 2
*/
static inline int set_stop_bits( struct port_descriptor* desc, int stop_bits ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
if( stop_bits == 1 ){
newio.StopBits = ONESTOPBIT;
}else if( stop_bits == 2 ){
newio.StopBits = TWOSTOPBITS;
}
#else
if( stop_bits == 1 ){
newio.c_cflag &= ~CSTOPB;
}else if( stop_bits == 2 ){
newio.c_cflag |= CSTOPB;
}
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
/**
* @param parity 0 for no parity, 1 for odd parity, 2 for even parity
*/
static inline int set_parity( struct port_descriptor* desc, int parity ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
if( parity == 0 ){
newio.Parity = NOPARITY;
}else if( parity == 1 ){
newio.Parity = ODDPARITY;
}else if( parity == 2 ){
newio.Parity = EVENPARITY;
}
#else
newio.c_iflag &= ~IGNPAR;
newio.c_cflag &= ~( PARODD | PARENB );
if( parity == 0 ){
newio.c_iflag |= IGNPAR;
}else if( parity == 1 ){
newio.c_cflag |= PARODD;
}else if( parity == 2 ){
newio.c_cflag |= PARENB;
}
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
/**
* @param flow_control 0 for none, 1 for hardware, 2 for software
*/
static inline int set_flow_control( struct port_descriptor* desc, int flow_control ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
if( flow_control == 0 ){
newio.fOutxCtsFlow = FALSE;
newio.fRtsControl = FALSE;
newio.fOutX = FALSE;
newio.fInX = FALSE;
}else if( flow_control == 1 ){
newio.fOutxCtsFlow = TRUE;
newio.fRtsControl = TRUE;
newio.fOutX = FALSE;
newio.fInX = FALSE;
}else if( flow_control == 2 ){
newio.fOutxCtsFlow = FALSE;
newio.fRtsControl = FALSE;
newio.fOutX = TRUE;
newio.fInX = TRUE;
}
#else
newio.c_iflag &= ~( IXON | IXOFF | IXANY );
newio.c_cflag &= ~HW_FLOW;
if( flow_control == 0 ){
newio.c_iflag &= ~( IXON | IXOFF | IXANY );
}else if( flow_control == 1 ){
newio.c_cflag |= HW_FLOW;
}else if( flow_control == 2 ){
newio.c_iflag |= ( IXON | IXOFF | IXANY );
}
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
static inline void throw_io_exception( JNIEnv * env, int errorNumber ){
#ifdef _WIN32
LPTSTR error_text = NULL;
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorNumber,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&error_text,
0,
NULL );
(*env)->ThrowNew(env, exception_class, error_text );
LocalFree( error_text );
#else
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errorNumber ) );
#endif /* _WIN32 */
}
 
static inline void throw_io_exception_message( JNIEnv * env, const char* message ){
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, message );
}
 
static inline struct port_descriptor* get_port_descriptor( JNIEnv* env, jobject obj ){
int array_pos;
struct port_descriptor* desc;
array_pos = get_handle( env, obj );
if( array_pos < 0 || array_pos > port_list_size ){
throw_io_exception_message( env, "Unable to get handle" );
return NULL;
}
desc = port_list[ array_pos ];
if( desc == NULL ){
throw_io_exception_message( env, "Unable to get descriptor" );
return NULL;
}
return desc;
}
 
//
// JNI Methods
//
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: openPort
* Signature: (Ljava/lang/String;IIIII)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort
(JNIEnv * env, jobject obj, jstring port, jint baudRate, jint dataBits, jint stopBits, jint parity, jint flowControl){
struct port_descriptor* new_port;
int list_pos;
int found = 0;
const char* port_to_open;
jboolean iscopy;
 
port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy );
 
if( port_list == NULL ){
port_list = malloc( sizeof( struct port_descriptor* ) * 10 );
port_list_size = 10;
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
port_list[ list_pos ] = NULL;
}
}
 
//Search thru the port_list, find the first one that is NULL
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
if( port_list[ list_pos ] == NULL ){
found = 1;
break;
}
}
 
if( !found ){
//no free slots. Expand our array by 10 elements
struct port_descriptor** tmpPortDesc;
tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) );
 
//put all elements into the new array
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
tmpPortDesc[ list_pos ] = port_list[ list_pos ];
}
++list_pos; //put the place to insert the new record one past the old records
 
port_list_size += 10;
//free the old array, set it to the new one
free( port_list );
port_list = tmpPortDesc;
}
 
//at this point, list_pos points to a NULL location in our array
new_port = malloc( sizeof( struct port_descriptor ) );
 
//Now, let's get to the actual opening of our port
#ifdef _WIN32
{
//GOD DAMN IT WINDOWS http://support.microsoft.com/kb/115831
char* special_port = malloc( strlen( port_to_open ) + 5 );
memcpy( special_port, "\\\\.\\", 4 );
memcpy( special_port + 4, port_to_open, strlen( port_to_open ) + 1 );
new_port->port = CreateFile( special_port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
free( special_port );
}
if( new_port->port == INVALID_HANDLE_VALUE ){
if( GetLastError() == ERROR_FILE_NOT_FOUND ){
LPTSTR error_text = NULL;
jclass exception_class;
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&error_text,
0,
NULL );
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, error_text );
free( new_port );
LocalFree( error_text );
return -1;
}
}
{
//Let's check to see if this is a serial port
DCB io_name = {0};
io_name.DCBlength = sizeof( io_name );
if (!GetCommState( new_port->port, &io_name ) ) {
LPTSTR error_text = NULL;
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
free( new_port );
return -1;
}
}
#else
pthread_mutex_init( &(new_port->in_use), NULL );
new_port->port = open( port_to_open, O_RDWR );
if( new_port->port < 0 && errno == ENOENT ){
//That's not a valid serial port, error out
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
}else if( new_port->port < 0 ){
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
}
{
struct termios io_name;
if( tcgetattr( new_port->port, &io_name ) < 0 ){
if( errno == ENOTTY ){
//This is apparently not a serial port
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
free( new_port );
return -1;
}
}
}
#endif /* __WIN32 */
 
 
//Set the baud rate
if( set_baud_rate( new_port, baudRate ) < 0 ){
throw_io_exception_message( env, "Unable to set baud rate" );
return 0;
}
set_raw_input( new_port );
//Set the data bits( character size )
set_data_bits( new_port, dataBits );
//Set the stop bits
set_stop_bits( new_port, stopBits );
//Set the parity
set_parity( new_port, parity );
//Set the flow control
set_flow_control( new_port, flowControl );
 
//Only set the new_port to be in our array as the last instruction
//If there are any errors, we will have returned long before this
port_list[ list_pos ] = new_port;
return list_pos;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: openPort
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2
(JNIEnv * env, jobject obj, jstring port){
struct port_descriptor* new_port;
int list_pos;
int found = 0;
const char* port_to_open;
jboolean iscopy;
 
port_to_open = (*env)->GetStringUTFChars( env, port, &iscopy );
 
if( port_list == NULL ){
port_list = malloc( sizeof( struct port_descriptor* ) * 10 );
port_list_size = 10;
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
port_list[ list_pos ] = NULL;
}
}
 
//Search thru the port_list, find the first one that is NULL
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
if( port_list[ list_pos ] == NULL ){
found = 1;
break;
}
}
 
if( !found ){
//no free slots. Expand our array by 10 elements
struct port_descriptor** tmpPortDesc;
tmpPortDesc = malloc( sizeof( struct port_descriptor* ) * ( port_list_size + 10 ) );
 
//put all elements into the new array
for( list_pos = 0; list_pos < port_list_size; ++list_pos ){
tmpPortDesc[ list_pos ] = port_list[ list_pos ];
}
++list_pos; //put the place to insert the new record one past the old records
 
port_list_size += 10;
//free the old array, set it to the new one
free( port_list );
port_list = tmpPortDesc;
}
 
//at this point, list_pos points to a NULL location in our array
new_port = malloc( sizeof( struct port_descriptor ) );
 
//Now, let's get to the actual opening of our port
#ifdef _WIN32
{
char* special_port = malloc( strlen( port_to_open ) + 5 );
memcpy( special_port, "\\\\.\\", 4 );
memcpy( special_port + 4, port_to_open, strlen( port_to_open ) + 1 );
new_port->port = CreateFile( special_port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
free( special_port );
}
if( new_port->port == INVALID_HANDLE_VALUE ){
if( GetLastError() == ERROR_FILE_NOT_FOUND ){
LPTSTR error_text = NULL;
jclass exception_class;
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&error_text,
0,
NULL );
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, error_text );
free( new_port );
LocalFree( error_text );
return -1;
}
}
{
//Let's check to see if this is a serial port
DCB io_name = {0};
io_name.DCBlength = sizeof( io_name );
if (!GetCommState( new_port->port, &io_name ) ) {
LPTSTR error_text = NULL;
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
free( new_port );
return -1;
}
}
#else
pthread_mutex_init( &(new_port->in_use), NULL );
new_port->port = open( port_to_open, O_RDWR );
if( new_port->port < 0 && errno == ENOENT ){
//That's not a valid serial port, error out
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
}else if( new_port->port < 0 ){
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
}
{
struct termios io_name;
if( tcgetattr( new_port->port, &io_name ) < 0 ){
if( errno == ENOTTY ){
//This is apparently not a serial port
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
(*env)->ThrowNew(env, exception_class, "You are attempting to open something which is not a serial port" );
free( new_port );
return -1;
}
}
}
#endif /* __WIN32 */
 
//Only set the new_port to be in our array as the last instruction
//If there are any errors, we will have returned long before this
port_list[ list_pos ] = new_port;
 
return list_pos;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: doClose
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialPort_doClose
(JNIEnv * env, jobject obj){
//Note: We can't use get_serial_port_struct here, beacuse we need to set
//the position in the array to NULL
int array_pos;
struct port_descriptor* desc;
array_pos = get_handle( env, obj );
if( array_pos < 0 || array_pos > port_list_size ){
throw_io_exception_message( env, "Unable to get handle" );
return;
}
desc = port_list[ array_pos ];
if( desc == NULL ){
throw_io_exception_message( env, "Unable to get descriptor" );
return;
}
close( desc->port );
#ifndef _WIN32
pthread_mutex_lock( &(desc->in_use) );
pthread_mutex_unlock( &(desc->in_use) );
#endif
free( port_list[ array_pos ] );
port_list[ array_pos ] = NULL;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setBaudRate
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setBaudRate
(JNIEnv * env, jobject obj, jint baud_rate ){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
 
if( desc == NULL ){
return 0;
}
 
return set_baud_rate( desc, baud_rate );
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getBaudRateInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getBaudRateInternal
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
//Now, let's get the baud rate information
{
GET_SERIAL_PORT_STRUCT( desc->port, newio );
#ifdef _WIN32
GetCommState( desc->port, &newio );
switch( newio.BaudRate ){
#else
switch( cfgetispeed( &newio ) ){
GET_SPEED_SWITCH( 0, newio );
GET_SPEED_SWITCH( 50, newio );
GET_SPEED_SWITCH( 75, newio );
#endif /* _WIN32 */
GET_SPEED_SWITCH( 110, newio );
#ifndef _WIN32
GET_SPEED_SWITCH( 134, newio );
GET_SPEED_SWITCH( 150, newio );
GET_SPEED_SWITCH( 200, newio );
#endif /* _WIN32 */
GET_SPEED_SWITCH( 300, newio );
GET_SPEED_SWITCH( 600, newio );
GET_SPEED_SWITCH( 1200, newio );
#ifndef _WIN32
GET_SPEED_SWITCH( 1800, newio );
#endif /* _WIN32 */
GET_SPEED_SWITCH( 2400, newio );
GET_SPEED_SWITCH( 4800, newio );
GET_SPEED_SWITCH( 9600, newio );
GET_SPEED_SWITCH( 19200, newio );
GET_SPEED_SWITCH( 38400, newio );
GET_SPEED_SWITCH( 115200, newio );
default:
return 0;
} /* end switch */
}
 
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setStopBits
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits
(JNIEnv * env, jobject obj, jint bits){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
return set_stop_bits( desc, bits );
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getStopBitsInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getStopBitsInternal
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
{
GET_SERIAL_PORT_STRUCT( desc->port, newio );
#ifdef _WIN32
if( newio.StopBits == 1 ){
return 1;
}else if( newio.StopBits == 2 ){
return 2;
}else{
return -1;
}
#else
if( newio.c_cflag & CSTOPB ){
return 2;
}else{
return 1;
}
#endif
}
}
/*
* Class: com_rm5248_serial_SerialPort
* Method: setCharSize
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize
(JNIEnv * env, jobject obj, jint size){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
return set_data_bits( desc, size );
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getCharSizeInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getCharSizeInternal
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
//Now get the char size
{
GET_SERIAL_PORT_STRUCT( desc->port, newio );
#ifdef _WIN32
return newio.ByteSize;
#else
if( ( newio.c_cflag | CS8 ) == CS8 ){
return 8;
}else if( ( newio.c_cflag | CS7 ) == CS7 ){
return 7;
}else if( ( newio.c_cflag | CS6 ) == CS6 ){
return 6;
}else if( ( newio.c_cflag | CS5 ) == CS5 ){
return 5;
}else{
return 0;
}
#endif
}
 
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setParity
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity
(JNIEnv * env, jobject obj, jint parity){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
return set_parity( desc, parity );
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getParityInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getParityInternal
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
{
GET_SERIAL_PORT_STRUCT( desc->port, newio );
#ifdef _WIN32
if( newio.Parity == NOPARITY ){
return 0;
}else if( newio.Parity == ODDPARITY ){
return 1;
}else if( newio.Parity == EVENPARITY ){
return 2;
}else{
return -1;
}
#else
if( !( newio.c_cflag & PARENB ) ){
//No parity
return 0;
}else if( newio.c_cflag & PARODD ){
//Odd parity
return 1;
}else if( !( newio.c_cflag & PARODD ) ){
//Even parity
return 2;
}else{
return -1;
}
#endif
}
 
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setFlowControl
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setFlowControl
(JNIEnv * env, jobject obj, jint flow){
struct port_descriptor* desc;
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
return set_flow_control( desc, flow );
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getFlowControlInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getFlowControlInternal
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
{
GET_SERIAL_PORT_STRUCT( desc->port, newio );
#ifdef _WIN32
if( newio.fOutX == TRUE && newio.fInX == TRUE ){
return 2;
}else if( newio.fRtsControl == TRUE && newio.fOutxCtsFlow == TRUE ){
return 1;
}else{
return 0;
}
#else
if( newio.c_cflag & ~( IXON ) &&
newio.c_cflag & ~( IXOFF ) &&
newio.c_cflag & ~( IXANY ) ){
return 0;
}else if( newio.c_cflag & HW_FLOW ){
return 1;
}else if( newio.c_cflag & ( IXON ) &&
newio.c_cflag & ( IXOFF ) &&
newio.c_cflag & ( IXANY ) ){
return 2;
}
#endif /* _WIN32 */
}
 
return -1;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getSerialLineStateInternalNonblocking
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getSerialLineStateInternalNonblocking
(JNIEnv * env, jobject obj ){
struct port_descriptor* desc;
jint ret_val;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
ret_val = 0;
{
#ifdef _WIN32
DWORD get_val;
if( GetCommModemStatus( desc->port, &get_val ) == 0 ){
throw_io_exception( env, GetLastError() );
return -1;
}
if( get_val & MS_CTS_ON ){
// CTS
ret_val |= ( 0x01 << 1 );
}
if( get_val & MS_DSR_ON ){
// Data Set Ready
ret_val |= ( 0x01 << 2 );
}
if( winDTR ){
ret_val |= ( 0x01 << 3 );
}
if( winRTS ){
ret_val |= ( 0x01 << 4 );
}
if( get_val & MS_RING_ON ){
// Ring Indicator
ret_val |= ( 0x01 << 5 );
}
#else
int get_val;
if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
throw_io_exception( env, errno );
return -1;
}
 
if( get_val & TIOCM_CD ){
// Carrier detect
ret_val |= 0x01;
}
 
if( get_val & TIOCM_CTS ){
// CTS
ret_val |= ( 0x01 << 1 );
}
 
if( get_val & TIOCM_DSR ){
// Data Set Ready
ret_val |= ( 0x01 << 2 );
}
 
if( get_val & TIOCM_DTR ){
// Data Terminal Ready
ret_val |= ( 0x01 << 3 );
}
 
if( get_val & TIOCM_RTS ){
// Request To Send
ret_val |= ( 0x01 << 4 );
}
 
if( get_val & TIOCM_RI ){
// Ring Indicator
ret_val |= ( 0x01 << 5 );
}
#endif
}
 
return ret_val;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setSerialLineStateInternal
* Signature: (Lcom/rm5248/serial/SerialLineState;)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_setSerialLineStateInternal
(JNIEnv * env, jobject obj, jobject serial){
struct port_descriptor* desc;
jint ret_val;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
ret_val = 0;
#ifdef _WIN32
if( get_bool( env, serial, "dataTerminalReady" ) ){
if( !EscapeCommFunction( desc->port, SETDTR ) ){
throw_io_exception_message( env, "Could not set DTR" );
return -1;
}
winDTR = 1;
}else{
if( !EscapeCommFunction( desc->port, CLRDTR ) ){
throw_io_exception_message( env, "Could not set DTR" );
return -1;
}
winDTR = 0;
}
 
if( get_bool( env, serial, "requestToSend" ) ){
if( !EscapeCommFunction( desc->port, SETRTS ) ){
throw_io_exception_message( env, "Could not set RTS" );
return -1;
}
winRTS = 1;
}else{
if( !EscapeCommFunction( desc->port, CLRRTS ) ){
throw_io_exception_message( env, "Could not set RTS" );
return -1;
}
winRTS = 0;
}
#else
int toSet = 0;
 
if( ioctl( desc->port, TIOCMGET, &toSet ) < 0 ){
throw_io_exception_message( env, "Could not get port settings" );
return -1;
}
 
if( get_bool( env, serial, "dataTerminalReady" ) ){
toSet |= TIOCM_DTR;
}else{
toSet &= ~TIOCM_DTR;
}
 
if( get_bool( env, serial, "requestToSend" ) ){
toSet |= TIOCM_RTS;
}else{
toSet &= ~TIOCM_RTS;
}
 
if( ioctl( desc->port, TIOCMSET, &toSet ) < 0 ){
throw_io_exception_message( env, "Could not set port settings" );
}
#endif
 
return ret_val;
}
 
//
// ------------------------------------------------------------------------
// ------------------Input/Output methods below here-----------------------
// ------------------------------------------------------------------------
//
 
 
/*
* Class: com_rm5248_serial_SerialInputStream
* Method: readByte
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_readByte
(JNIEnv * env, jobject obj){
int stat;
int ret_val;
struct port_descriptor* desc;
int get_val = 0;
#ifdef _WIN32
DWORD ret = 0;
OVERLAPPED overlap = {0};
int current_available = 0;
#endif
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
ret_val = 0;
 
#ifdef _WIN32
{
DWORD comErrors = {0};
COMSTAT portStatus = {0};
if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){
//return value zero = fail
throw_io_exception( env, GetLastError() );
return -1;
}else{
current_available = portStatus.cbInQue;
}
}
if( !current_available ){
//If nothing is currently available, wait until we get an event of some kind.
//This could be the serial lines changing state, or it could be some data
//coming into the system.
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
SetCommMask( desc->port, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING );
WaitCommEvent( desc->port, &ret, &overlap );
WaitForSingleObject( overlap.hEvent, INFINITE );
}else{
//Data is available; set the RXCHAR mask so we try to read from the port
ret = EV_RXCHAR;
}
if( ret & EV_RXCHAR ){
if( !ReadFile( desc->port, &ret_val, 1, &stat, &overlap) ){
throw_io_exception( env, GetLastError() );
return -1;
}
//This is a valid byte, set our valid bit
ret_val |= ( 0x01 << 15 );
}
//Always get the com lines no matter what
if( GetCommModemStatus( desc->port, &get_val ) == 0 ){
throw_io_exception( env, GetLastError() );
return -1;
}
if( get_val & MS_CTS_ON ){
// CTS
ret_val |= ( 0x01 << 10 );
}
if( get_val & MS_DSR_ON ){
// Data Set Ready
ret_val |= ( 0x01 << 11 );
}
if( winDTR ){
ret_val |= ( 0x01 << 12 );
}
if( winRTS ){
ret_val |= ( 0x01 << 13 );
}
if( get_val & MS_RING_ON ){
// Ring Indicator
ret_val |= ( 0x01 << 14 );
}
#else
 
//Okay, this here is going to be a bit ugly.
//The problem here is that Linux/POSIX don't specify that TIOCMIWAIT
//has to exist. Also, the fact that if we use TIOCMIWAIT we don't
//timeout or anything. What would be very convenient in this case
//would be to have select() return when the state changed, but
//it's not possible. :(
//Ironically, this is one case in which the Windows serial API
//is better than the POSIX way.
fd_set fdset;
struct timeval timeout;
int originalState;
int selectStatus;
 
pthread_mutex_lock( &(desc->in_use) );
 
//first get the original state of the serial port lines
if( ioctl( desc->port, TIOCMGET, &originalState ) < 0 ){
throw_io_exception( env, errno );
pthread_mutex_unlock( &(desc->in_use) );
return -1;
}
while( 1 ){
FD_ZERO( &fdset );
FD_SET( desc->port, &fdset );
timeout.tv_sec = 0;
timeout.tv_usec = 10000; // 10,000 microseconds = 10ms
 
selectStatus = select( desc->port + 1, &fdset, NULL, NULL, &timeout );
if( selectStatus < 0 ){
int errval;
if( errno == EBADF ){
// EOF
errval= 0;
}else{
throw_io_exception( env, errno );
errval = -1;
}
pthread_mutex_unlock( &(desc->in_use) );
return errval;
}
 
if( selectStatus == 0 ){
//This was a timeout
if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
throw_io_exception( env, errno );
pthread_mutex_unlock( &(desc->in_use) );
return -1;
}
 
if( get_val == originalState ){
//The state of the lines have not changed,
//continue on until something changes
continue;
}
}
if( FD_ISSET( desc->port, &fdset ) ){
stat = read( desc->port, &ret_val, 1 );
if( stat < 0 ){
//throw new exception
throw_io_exception( env, errno );
pthread_mutex_unlock( &(desc->in_use) );
return -1;
}
//This is a valid byte, set our valid bit
ret_val |= ( 0x01 << 15 );
}
//We get to this point if we either 1. have data or
//2. our state has changed
break;
}
 
//Now that we have read in the character, let's get the serial port line state.
//If it has changed, we will fire an event in Java.
//Now, because we only read one byte at a time, we will use the lower 8 bytes to
//return the character that we read. The other bytes will be used to return
//information on our serial port state.
if( ioctl( desc->port, TIOCMGET, &get_val ) < 0 ){
throw_io_exception( env, errno );
pthread_mutex_unlock( &(desc->in_use) );
return -1;
}
 
if( get_val & TIOCM_CD ){
// Carrier detect
ret_val |= ( 0x01 << 9 );
}
 
if( get_val & TIOCM_CTS ){
// CTS
ret_val |= ( 0x01 << 10 );
}
 
if( get_val & TIOCM_DSR ){
// Data Set Ready
ret_val |= ( 0x01 << 11 );
}
 
if( get_val & TIOCM_DTR ){
// Data Terminal Ready
ret_val |= ( 0x01 << 12 );
}
if( get_val & TIOCM_RTS ){
// Request To Send
ret_val |= ( 0x01 << 13 );
}
if( get_val & TIOCM_RI ){
// Ring Indicator
ret_val |= ( 0x01 << 14 );
}
pthread_mutex_unlock( &(desc->in_use) );
#endif
 
return ret_val;
}
 
/*
* Class: com_rm5248_serial_SerialInputStream
* Method: getAvailable
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialInputStream_getAvailable
(JNIEnv * env, jobject obj){
jint ret_val;
struct port_descriptor* desc;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
 
#ifdef _WIN32
{
DWORD comErrors = {0};
COMSTAT portStatus = {0};
if( !ClearCommError( desc->port, &comErrors, &portStatus ) ){
//return value zero = fail
throw_io_exception( env, GetLastError() );
return -1;
}else{
ret_val = portStatus.cbInQue;
}
}
#else
if( ioctl( desc->port, FIONREAD, &ret_val ) < 0 ){
//throw new exception
throw_io_exception( env, errno );
return -1;
}
#endif
return ret_val;
}
 
/*
* Class: com_rm5248_serial_SimpleSerialInputStream
* Method: readByte
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_readByte
(JNIEnv * env, jobject obj){
struct port_descriptor* desc;
jint ret_val;
int stat;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return 0;
}
ret_val = 0;
 
#ifdef _WIN32
if( !ReadFile( desc->port, &ret_val, 1, 0, 0) ){
throw_io_exception( env, GetLastError() );
return -1;
}
#else
pthread_mutex_lock( &(desc->in_use) );
stat = read( desc->port, &ret_val, 1 );
if( stat < 0 ){
throw_io_exception( env, errno );
pthread_mutex_unlock( &(desc->in_use) );
return -1;
}
pthread_mutex_unlock( &(desc->in_use) );
#endif
return ret_val;
}
 
/*
* Class: com_rm5248_serial_SimpleSerialInputStream
* Method: getAvailable
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_getAvailable
(JNIEnv * env, jobject obj){
//use our already-existing method to get the available bytes, it already works
return Java_com_rm5248_serial_SerialInputStream_getAvailable( env, obj );
}
 
 
/*
* Class: com_rm5248_serial_SerialOutputStream
* Method: writeByte
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByte
(JNIEnv * env, jobject obj, jint byte){
struct port_descriptor* desc;
char byte_write;
#ifdef _WIN32
DWORD bytes_written;
OVERLAPPED overlap;
#else
int bytes_written;
#endif
 
byte_write = byte;
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return;
}
 
#ifdef _WIN32
memset( &overlap, 0, sizeof( overlap ) );
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
if( !WriteFile( desc->port, &byte_write, sizeof( byte_write ), &bytes_written, &overlap ) ){
if( GetLastError() == ERROR_IO_PENDING ){
//Probably not an error, we're just doing this in an async fasion
if( WaitForSingleObject( overlap.hEvent, INFINITE ) == WAIT_FAILED ){
throw_io_exception( env, GetLastError() );
return;
}
}else{
throw_io_exception( env, GetLastError() );
return;
}
}
#else
bytes_written = write( desc->port, &byte_write, sizeof( byte_write ) );
if( bytes_written < 0 ){
//throw new exception
throw_io_exception( env, errno );
return;
}
#endif
}
 
/*
* Class: com_rm5248_serial_SerialOutputStream
* Method: writeByteArray
* Signature: ([B)V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByteArray
(JNIEnv * env, jobject obj, jbyteArray arr){
jbyte* data;
jint len;
struct port_descriptor* desc;
#ifdef _WIN32
DWORD bytes_written;
OVERLAPPED overlap;
#else
int bytes_written;
#endif /* _WIN32 */
 
desc = get_port_descriptor( env, obj );
if( desc == NULL ){
return;
}
 
len = (*env)->GetArrayLength( env, arr );
data = (*env)->GetByteArrayElements(env, arr, 0);
 
#ifdef _WIN32
memset( &overlap, 0, sizeof( overlap ) );
overlap.hEvent = CreateEvent( 0, TRUE, 0, 0 );
if( !WriteFile( desc->port, data, len, &bytes_written, &overlap ) ){
if( GetLastError() == ERROR_IO_PENDING ){
//Probably not an error, we're just doing this in an async fasion
if( WaitForSingleObject( overlap.hEvent, INFINITE ) == WAIT_FAILED ){
throw_io_exception( env, GetLastError() );
return;
}
}else{
throw_io_exception( env, GetLastError() );
}
}
#else
bytes_written = write( desc->port, data, len );
if( bytes_written < 0 ){
throw_io_exception( env, errno );
}
#endif /* _WIN32 */
 
(*env)->ReleaseByteArrayElements(env, arr, data, 0);
}
 
 
//
// ------------------------------------------------------------------------
// ---------------------Static methods below here--------------------------
// ------------------------------------------------------------------------
//
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getMajorNativeVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMajorNativeVersion
(JNIEnv * env, jclass cls){
return 0;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getMinorNativeVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMinorNativeVersion
(JNIEnv * env, jclass cls){
return 5;
}
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getSerialPorts
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_com_rm5248_serial_SerialPort_getSerialPorts
(JNIEnv * env, jclass cls){
jclass stringClass;
jobjectArray array;
char** port_names;
int port_names_size;
int x;
port_names_size = 0;
port_names = malloc( sizeof( char* ) * 255 ); //max 255 serial ports
#ifdef _WIN32
{
//Brute force, baby!
char* port_to_open = malloc( 11 );
HANDLE* port;
for( x = 0; x <= 255; x++ ){
_snprintf_s( port_to_open, 11, 11, "\\\\.\\COM%d", x );
port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 );
if( port != INVALID_HANDLE_VALUE ||
( port == INVALID_HANDLE_VALUE &&
GetLastError() != ERROR_FILE_NOT_FOUND ) ){
//This is a valid port
//we could get INVALID_HANDLE_VALUE if the port is already open,
//so make sure we check to see if it is not that value
port_names[ port_names_size ] = malloc( 6 );
memcpy( port_names[ port_names_size ], port_to_open + 4, 6 );
port_names_size++;
}
CloseHandle( port );
}
free( port_to_open );
}
#else
{
struct dirent *entry;
DIR* dir;
int fd;
char* deviceName;
 
deviceName = malloc( 100 );
 
dir = opendir( "/dev/" );
if( dir == NULL ){
throw_io_exception_message( env, "We can't open /dev." );
free( port_names );
free( deviceName );
return NULL;
}
while ( entry = readdir( dir ), entry != NULL) {
if( snprintf( deviceName, 100, "/dev/%s", entry->d_name ) >= 99 ){
fprintf( stderr, "WARNING: Ignoring file %s, filename too long\n", entry->d_name );
continue;
}
fd = open( deviceName, O_RDONLY );
if( fd < 0 ){
switch( errno ){
case EACCES:
case ENOMEDIUM:
//For some reason, I get errno 22 on my laptop
//when opening /dev/video0, which prints out
//"No such device or address"
//Not adding it here, because that does seem bad
break;
default:
perror( "open" );
fprintf( stderr, "ERROR: This is a very bad thing that should never happen %s:%d errno:%d\n", __FILE__, __LINE__, errno );
}
close( fd );
continue;
}
if( isatty( fd ) && port_names_size < 255 ){
port_names[ port_names_size ] = malloc( strlen( entry->d_name ) + 6 );
memcpy( port_names[ port_names_size ], "/dev/", 5 );
memcpy( port_names[ port_names_size ] + 5, entry->d_name, strlen( entry->d_name ) + 1 );
port_names_size++;
}
close( fd );
}
closedir( dir );
free( deviceName );
}
#endif /* _WIN32 */
 
stringClass = (*env)->FindClass(env, "java/lang/String");
array = (*env)->NewObjectArray(env, port_names_size, stringClass, 0);
for( x = 0; x < port_names_size; x++ ){
(*env)->SetObjectArrayElement(env, array, x, (*env)->NewStringUTF( env, port_names[ x ] ) );
free( port_names[ x ] );
}
free( port_names );
return array;
}
/branches/JavaSerialNIO/NativeCode/com_rm5248_serial_SimpleSerialInputStream.h
0,0 → 1,31
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_rm5248_serial_SimpleSerialInputStream */
 
#ifndef _Included_com_rm5248_serial_SimpleSerialInputStream
#define _Included_com_rm5248_serial_SimpleSerialInputStream
#ifdef __cplusplus
extern "C" {
#endif
#undef com_rm5248_serial_SimpleSerialInputStream_MAX_SKIP_BUFFER_SIZE
#define com_rm5248_serial_SimpleSerialInputStream_MAX_SKIP_BUFFER_SIZE 2048L
/*
* Class: com_rm5248_serial_SimpleSerialInputStream
* Method: readByte
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_readByte
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SimpleSerialInputStream
* Method: getAvailable
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SimpleSerialInputStream_getAvailable
(JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif
/branches/JavaSerialNIO/NativeCode/Makefile
0,0 → 1,104
#
# Created by gmakemake x86 (Feb 24 2012) on Sat Aug 4 19:31:04 2012
#
 
#
# Definitions
#
 
.SUFFIXES:
.SUFFIXES: .a .o .c .C .cpp .s .S
.c.o:
$(COMPILE.c) $< -o $@
.C.o:
$(COMPILE.cc) $< -o $@
.cpp.o:
$(COMPILE.cc) $< -o $@
.S.s:
$(CPP) -o $*.s $<
.s.o:
$(COMPILE.cc) $< -o $@
.c.a:
$(COMPILE.c) -o $% $<
$(AR) $(ARFLAGS) $@ $%
.C.a:
$(COMPILE.cc) -o $% $<
$(AR) $(ARFLAGS) $@ $%
.cpp.a:
$(COMPILE.cc) -o $% $<
$(AR) $(ARFLAGS) $@ $%
 
CC = gcc
CXX = g++
 
RM = rm -f
AR = ar
LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS)
LINK.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) -c
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c
 
########## Default flags (redefine these with a header.mak file if desired)
CPPFLAGS = -DPIC -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/linux
CXXFLAGS =
CFLAGS = -fPIC -Wall $(ARCH)
CLIBFLAGS = -lm
CCLIBFLAGS =
########## End of default flags
 
 
CPP_FILES =
C_FILES = SerialPortImpl.c
PS_FILES =
S_FILES =
H_FILES = com_rm5248_serial_SerialPort.h com_rm5248_serial_SerialPort_SerialInputStream.h com_rm5248_serial_SerialPort_SerialOutputStream.h
SOURCEFILES = $(H_FILES) $(CPP_FILES) $(C_FILES) $(S_FILES)
.PRECIOUS: $(SOURCEFILES)
OBJFILES = SerialPortImpl.o
 
JNI_INCLUDE_DIR = /usr/lib/jvm/java-7-openjdk-amd64/include
JNI_INCLUDE_DIR_WIN=C:\Program Files (x86)\Java\jdk1.6.0_18\include
 
#
# Main targets
#
linux: SerialPortImpl.o
gcc -o libjavaserial.so $(ARCH) -shared -Wl,-soname,libjavaserial.so -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/linux -lc $(OBJFILES)
 
linux-32:
$(MAKE) ARCH="-m32"
linux-64:
$(MAKE) ARCH="-m64"
 
windows:
cl -I"$(JNI_INCLUDE_DIR_WIN)" -I"$(JNI_INCLUDE_DIR_WIN)\win32" -I"." -MT -LD SerialPortImpl.c -Fejavaserial.dll
#
# Dependencies
#
 
SerialPortImpl.o: SerialPortImpl.c com_rm5248_serial_SerialPort.h \
com_rm5248_serial_SerialInputStream.h \
com_rm5248_serial_SerialOutputStream.h \
com_rm5248_serial_SimpleSerialInputStream.h
 
#
# Installation Targets
#
 
install:
/usr/bin/install /usr/bin
 
#
# Housekeeping
#
 
Archive: archive.tgz
 
archive.tgz: $(SOURCEFILES) Makefile
tar cf - $(SOURCEFILES) Makefile | gzip > archive.tgz
 
clean:
-/bin/rm $(OBJFILES) core 2> /dev/null
 
realclean: clean
-/bin/rm -rf
/branches/JavaSerialNIO/NativeCode/com_rm5248_serial_SerialPort.h
0,0 → 1,157
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_rm5248_serial_SerialPort */
 
#ifndef _Included_com_rm5248_serial_SerialPort
#define _Included_com_rm5248_serial_SerialPort
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_rm5248_serial_SerialPort
* Method: openPort
* Signature: (Ljava/lang/String;IIIII)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2IIIII
(JNIEnv *, jobject, jstring, jint, jint, jint, jint, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: openPort
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_openPort__Ljava_lang_String_2
(JNIEnv *, jobject, jstring);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: doClose
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialPort_doClose
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setBaudRate
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setBaudRate
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getBaudRateInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getBaudRateInternal
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setStopBits
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getStopBitsInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getStopBitsInternal
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setCharSize
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getCharSizeInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getCharSizeInternal
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setParity
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getParityInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getParityInternal
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setFlowControl
* Signature: (I)Z
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setFlowControl
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getFlowControlInternal
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getFlowControlInternal
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getSerialLineStateInternalNonblocking
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getSerialLineStateInternalNonblocking
(JNIEnv *, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: setSerialLineStateInternal
* Signature: (Lcom/rm5248/serial/SerialLineState;)I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_setSerialLineStateInternal
(JNIEnv *, jobject, jobject);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getMajorNativeVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMajorNativeVersion
(JNIEnv *, jclass);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getMinorNativeVersion
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_rm5248_serial_SerialPort_getMinorNativeVersion
(JNIEnv *, jclass);
 
/*
* Class: com_rm5248_serial_SerialPort
* Method: getSerialPorts
* Signature: ()[Ljava/lang/String;
*/
JNIEXPORT jobjectArray JNICALL Java_com_rm5248_serial_SerialPort_getSerialPorts
(JNIEnv *, jclass);
 
#ifdef __cplusplus
}
#endif
#endif
/branches/JavaSerialNIO/NativeCode/com_rm5248_serial_SerialOutputStream.h
0,0 → 1,29
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_rm5248_serial_SerialOutputStream */
 
#ifndef _Included_com_rm5248_serial_SerialOutputStream
#define _Included_com_rm5248_serial_SerialOutputStream
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_rm5248_serial_SerialOutputStream
* Method: writeByte
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByte
(JNIEnv *, jobject, jint);
 
/*
* Class: com_rm5248_serial_SerialOutputStream
* Method: writeByteArray
* Signature: ([B)V
*/
JNIEXPORT void JNICALL Java_com_rm5248_serial_SerialOutputStream_writeByteArray
(JNIEnv *, jobject, jbyteArray);
 
#ifdef __cplusplus
}
#endif
#endif
/branches/JavaSerialNIO/LICENSE
0,0 → 1,7
Copyright (c) 2013-2015 rm5248
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/branches/JavaSerialNIO/.project
0,0 → 1,23
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>JavaSerial</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>
/branches/JavaSerialNIO/pom.xml
0,0 → 1,36
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rm5248</groupId>
<artifactId>JavaSerial</artifactId>
<version>0.5-SNAPSHOT</version>
<description>A cross-platform way of accessing serial ports through Java. Supports Windows and Linux. Does not use the Java SerialAPI. Implementations have both traditional IO and NIO implementations.</description>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source/>
<target/>
</configuration>
</plugin>
</plugins>
</build>
<url>http://programming.rm5248.com/</url>
<name>Java Serial</name>
<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<url>http://svn.rm5248.com/prog_utils/trunk/JavaSerial/</url>
<connection>svn</connection>
</scm>
<issueManagement>
<url>http://programming.rm5248.com/</url>
</issueManagement>
</project>
/branches/JavaSerialNIO/README
0,0 → 1,8
Java Serial
=========================================
 
This software is open-source software.
 
The home of Java Serial is at http://svn.rm5248.com/RMProgrammingUtilities/?page_id=19
 
Use of this code is subject to license terms as laid out in LICENSE