Subversion Repositories Programming Utils

Compare Revisions

Ignore whitespace Rev 13 → Rev 12

/JavaSerial/NativeCode/SerialPortImpl.c
1,16 → 1,5
#ifdef _WIN32
#include <windows.h>
#define SPEED_SWITCH(SPD,io) case SPD: io.BaudRate = CBR_##SPD; break;
#define GET_SERIAL_PORT_STRUCT( port, io_name ) DCB io_name = {0};\
io_name.DCBlength = sizeof( io_name ); \
if (!GetCommState( port, &io_name ) ) { \
return -1;\
}
#define SET_SERIAL_PORT_STRUCT( port, io_name ) if( !SetCommState( port, &io_name ) ){\
return 0;\
}
#ifdef __WIN32
 
#else
#include <termio.h>
#include <termios.h>
18,18 → 7,7
#include <fcntl.h>
#define SPEED_SWITCH(SPD,io) case SPD: cfsetospeed( &io, B##SPD ); break;
#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 0;\
}
#endif
 
#include <stdlib.h>
#include <errno.h>
#include <string.h>
45,7 → 23,7
// Struct Definitions
//
struct port_descriptor{
#ifdef _WIN32
#ifdef __WIN32
HANDLE port;
#else
int port;
61,7 → 39,7
//
// Helper Methods
//
static jint get_handle
static inline jint get_handle
(JNIEnv * env, jobject obj){
jfieldID fid;
jint array_pos;
77,30 → 55,25
return array_pos;
}
 
static int set_baud_rate( struct port_descriptor* desc, int baud_rate ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
static inline int set_baud_rate( struct port_descriptor* desc, int baud_rate ){
#ifdef __WIN32
#else
struct termios newio;
 
tcgetattr( 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);
109,76 → 82,15
SPEED_SWITCH(115200,newio);
}
 
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
static 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.
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
static 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;
if( tcsetattr( desc->port, TCSANOW, &newio ) < 0 ){
return 0;
}
#else
newio.
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
#endif /* __WIN32 */
 
return 1;
}
 
static 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.
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
static int set_flow_control( struct port_descriptor* desc, int flow_control ){
GET_SERIAL_PORT_STRUCT( desc->port, newio );
 
#ifdef _WIN32
#else
newio.
#endif
SET_SERIAL_PORT_STRUCT( desc->port, newio );
 
return 1;
}
 
//
// JNI Methods
//
236,31 → 148,7
new_port = malloc( sizeof( struct port_descriptor ) );
 
//Now, let's get to the actual opening of our port
#ifdef _WIN32
new_port->port = CreateFile( port_to_open, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
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;
}
}
#ifdef __WIN32
#else
new_port->port = open( port_to_open, O_RDWR );
if( new_port->port < 0 && errno == ENOENT ){
271,7 → 159,7
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
return;
}else if( new_port->port < 0 ){
jclass exception_class;
(*env)->ExceptionDescribe( env );
279,45 → 167,19
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NoSuchPortException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
free( new_port );
return -1;
return;
}
#endif /* __WIN32 */
 
port_list[ list_pos ] = new_port;
 
//Set the baud rate
found = set_baud_rate( new_port, baudRate ); //re-using found variable, don't care what it is at this point
if( found < 0 ){
//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;
}else if( found == 0 ){
//This is a serial port, but some error happened. What happened? We don't know.
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "com/rm5248/serial/NotASerialPortException");
(*env)->ThrowNew(env, exception_class, "An internal error occurred. This should not happen. Please report this bug." );
free( new_port );
return -1;
}
set_baud_rate( new_port, baudRate );
//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;
}
 
340,7 → 202,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return 0;
return;
}
 
desc = port_list[ array_pos ];
352,7 → 214,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return 0;
return;
}
 
return set_baud_rate( desc, baud_rate );
387,17 → 249,8
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setStopBits
(JNIEnv * env, jobject obj, jint bits){
jint array_pos;
struct port_descriptor* desc;
 
array_pos = get_handle( env, obj );
 
desc = port_list[ array_pos ];
if( desc == NULL ){
return 0;
}
return set_stop_bits( desc, bits );
return 1;
}
 
/*
407,17 → 260,8
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setCharSize
(JNIEnv * env, jobject obj, jint size){
jint array_pos;
struct port_descriptor* desc;
 
array_pos = get_handle( env, obj );
 
desc = port_list[ array_pos ];
if( desc == NULL ){
return 0;
}
return set_data_bits( desc, size );
return 1;
}
 
/*
427,17 → 271,8
*/
JNIEXPORT jboolean JNICALL Java_com_rm5248_serial_SerialPort_setParity
(JNIEnv * env, jobject obj, jint parity){
jint array_pos;
struct port_descriptor* desc;
 
array_pos = get_handle( env, obj );
 
desc = port_list[ array_pos ];
if( desc == NULL ){
return 0;
}
return set_parity( desc, parity );
return 1;
}
 
//
466,7 → 301,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
 
desc = port_list[ array_pos ];
478,10 → 313,10
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
 
#ifdef _WIN32
#ifdef __WIN32
#else
stat = read( desc->port, &ret_val, sizeof( ret_val ) );
if( stat < 0 ){
491,7 → 326,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
#endif
return ret_val;
516,7 → 351,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
 
desc = port_list[ array_pos ];
528,10 → 363,10
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
 
#ifdef _WIN32
#ifdef __WIN32
#else
if( ioctl( desc->port, FIONREAD, &ret_val ) < 0 ){
//throw new exception
540,7 → 375,7
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return -1;
return;
}
#endif
return ret_val;
556,11 → 391,6
struct port_descriptor* desc;
jint array_pos;
char byte_write;
#ifdef _WIN32
DWORD bytes_written;
#else
int bytes_written;
#endif
 
byte_write = byte;
 
587,19 → 417,9
return;
}
 
#ifdef _WIN32
if( !WriteFile( desc->port, &byte_write, sizeof( byte_write ), &bytes_written, NULL) ){
//throw new exception
jclass exception_class;
(*env)->ExceptionDescribe( env );
(*env)->ExceptionClear( env );
exception_class = (*env)->FindClass(env, "java/io/IOException");
(*env)->ThrowNew(env, exception_class, strerror( errno ) );
return;
}
#ifdef __WIN32
#else
bytes_written = write( desc->port, &byte_write, sizeof( byte_write ) );
if( bytes_written < 0 ){
if( write( desc->port, &byte_write, sizeof( byte_write ) ) < 0 ){
//throw new exception
jclass exception_class;
(*env)->ExceptionDescribe( env );
/JavaSerial/NativeCode/Makefile
57,7 → 57,6
OBJFILES = SerialPortImpl.o
 
JNI_INCLUDE_DIR = /usr/lib/jvm/java-6-sun/include
JNI_INCLUDE_DIR_WIN=C:\Program Files (x86)\Java\jdk1.6.0_18\include
 
#
# Main targets
64,9 → 63,6
#
linux: SerialPortImpl.o
gcc -o libjavaserial.so -shared -Wl,-soname,libjavaserial.so -I$(JNI_INCLUDE_DIR) -I$(JNI_INCLUDE_DIR)/linux -static -lc $(OBJFILES)
 
windows:
cl -I"$(JNI_INCLUDE_DIR_WIN)" -I"$(JNI_INCLUDE_DIR_WIN)\win32" -I"." -MT -LD SerialPortImpl.c -Fejavaserial.dll
#
# Dependencies
#
/JavaSerial/src/com/rm5248/serial/SerialPort.java
13,22 → 13,16
* 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,