From b6f27be4eda4ec0e50aaca8eb3a117db60b4067e Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Thu, 27 Mar 2014 20:19:28 +0100 Subject: re-implement native side (TODO: direct buffers) --- ...om_github_jodersky_flow_internal_NativeSerial.h | 54 +++---- flow/src/main/native/include/flow.h | 4 +- flow/src/main/native/posix/Makefile | 4 +- flow/src/main/native/posix/flow.c | 6 +- flow/src/main/native/posix/flow_jni.c | 164 +++++++++++++++------ .../jodersky/flow/internal/SerialConnection.scala | 11 +- 6 files changed, 161 insertions(+), 82 deletions(-) (limited to 'flow') diff --git a/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h b/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h index 1c71688..04364fb 100644 --- a/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h +++ b/flow/src/main/native/include/com_github_jodersky_flow_internal_NativeSerial.h @@ -7,18 +7,6 @@ #ifdef __cplusplus extern "C" { #endif -#undef com_github_jodersky_flow_internal_NativeSerial_E_IO -#define com_github_jodersky_flow_internal_NativeSerial_E_IO -1L -#undef com_github_jodersky_flow_internal_NativeSerial_E_ACCESS_DENIED -#define com_github_jodersky_flow_internal_NativeSerial_E_ACCESS_DENIED -2L -#undef com_github_jodersky_flow_internal_NativeSerial_E_BUSY -#define com_github_jodersky_flow_internal_NativeSerial_E_BUSY -3L -#undef com_github_jodersky_flow_internal_NativeSerial_E_INVALID_SETTINGS -#define com_github_jodersky_flow_internal_NativeSerial_E_INVALID_SETTINGS -4L -#undef com_github_jodersky_flow_internal_NativeSerial_E_INTERRUPT -#define com_github_jodersky_flow_internal_NativeSerial_E_INTERRUPT -5L -#undef com_github_jodersky_flow_internal_NativeSerial_E_NO_PORT -#define com_github_jodersky_flow_internal_NativeSerial_E_NO_PORT -6L #undef com_github_jodersky_flow_internal_NativeSerial_PARITY_NONE #define com_github_jodersky_flow_internal_NativeSerial_PARITY_NONE 0L #undef com_github_jodersky_flow_internal_NativeSerial_PARITY_ODD @@ -28,10 +16,18 @@ extern "C" { /* * Class: com_github_jodersky_flow_internal_NativeSerial * Method: open - * Signature: (Ljava/lang/String;IIZI[J)I + * Signature: (Ljava/lang/String;IIZI)J */ -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_open - (JNIEnv *, jclass, jstring, jint, jint, jboolean, jint, jlongArray); +JNIEXPORT jlong JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_open + (JNIEnv *, jclass, jstring, jint, jint, jboolean, jint); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: readDirect + * Signature: (JLjava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_readDirect + (JNIEnv *, jclass, jlong, jobject); /* * Class: com_github_jodersky_flow_internal_NativeSerial @@ -43,26 +39,34 @@ JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_read /* * Class: com_github_jodersky_flow_internal_NativeSerial - * Method: write - * Signature: (J[B)I + * Method: cancelRead + * Signature: (J)V */ -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_write - (JNIEnv *, jclass, jlong, jbyteArray); +JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_cancelRead + (JNIEnv *, jclass, jlong); /* * Class: com_github_jodersky_flow_internal_NativeSerial - * Method: interrupt - * Signature: (J)I + * Method: writeDirect + * Signature: (JLjava/nio/ByteBuffer;I)I */ -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_interrupt - (JNIEnv *, jclass, jlong); +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_writeDirect + (JNIEnv *, jclass, jlong, jobject, jint); + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: write + * Signature: (J[BI)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_write + (JNIEnv *, jclass, jlong, jbyteArray, jint); /* * Class: com_github_jodersky_flow_internal_NativeSerial * Method: close - * Signature: (J)I + * Signature: (J)V */ -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_close +JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_close (JNIEnv *, jclass, jlong); /* diff --git a/flow/src/main/native/include/flow.h b/flow/src/main/native/include/flow.h index d6a173e..ff80259 100644 --- a/flow/src/main/native/include/flow.h +++ b/flow/src/main/native/include/flow.h @@ -62,7 +62,7 @@ int serial_close(struct serial_config* const serial); * @return n>0 the number of bytes read into buffer * @return E_INTERRUPT if the call to this function was interrupted * @return E_IO on IO error */ -int serial_read(struct serial_config* const serial, unsigned char* const buffer, size_t size); +int serial_read(struct serial_config* const serial, char* const buffer, size_t size); /**Cancels a blocked read call. This function is thread safe, i.e. it may be called from a thread even * while another thread is blocked in a read call. @@ -77,7 +77,7 @@ int serial_cancel_read(struct serial_config* const serial); * @param size number of bytes to write from data * @return n>0 the number of bytes written * @return E_IO on IO error */ -int serial_write(struct serial_config* const serial, unsigned char* const data, size_t size); +int serial_write(struct serial_config* const serial, char* const data, size_t size); /**Sets debugging option. If debugging is enabled, detailed error message are printed from method calls. */ void serial_debug(bool value); diff --git a/flow/src/main/native/posix/Makefile b/flow/src/main/native/posix/Makefile index 81e0fad..22338e5 100644 --- a/flow/src/main/native/posix/Makefile +++ b/flow/src/main/native/posix/Makefile @@ -5,7 +5,7 @@ TARGET?=libflow.so MAJOR_VERSION=2 CC=$(CROSS_COMPILE)gcc -CFLAGS= -O2 -fPIC +CFLAGS= -O2 -fPIC -Wall LD=$(CROSS_COMPILE)ld LDFLAGS=-shared -Wl,-soname,$(TARGET).$(MAJOR_VERSION) INCLUDES?=../include/ /usr/lib/jvm/java-7-oracle/include/ /usr/lib/jvm/java-7-oracle/include/linux/ @@ -15,7 +15,7 @@ OBJECTS=flow.o flow_jni.o all: $(TARGET) $(TARGET): $(OBJECTS) - $(CC) $(LDFLAGS) -o $@ $< + $(CC) $(LDFLAGS) -o $@ $^ %.o: %.c $(CC) $(CFLAGS) $(addprefix -I, $(INCLUDES)) -o $@ -c $< diff --git a/flow/src/main/native/posix/flow.c b/flow/src/main/native/posix/flow.c index 18aa9c2..c408670 100644 --- a/flow/src/main/native/posix/flow.c +++ b/flow/src/main/native/posix/flow.c @@ -4,8 +4,10 @@ #include #include #include +#include #include "flow.h" + #define DATA_CANCEL 0xffffffff static bool debug = false; @@ -186,7 +188,7 @@ int serial_close(struct serial_config* const serial) { return 0; } -int serial_read(struct serial_config* const serial, unsigned char* const buffer, size_t size) { +int serial_read(struct serial_config* const serial, char* const buffer, size_t size) { int port = serial->port_fd; int pipe = serial->pipe_read_fd; @@ -234,7 +236,7 @@ int serial_cancel_read(struct serial_config* const serial) { return 0; } -int serial_write(struct serial_config* const serial, unsigned char* const data, size_t size) { +int serial_write(struct serial_config* const serial, char* const data, size_t size) { int r = write(serial->port_fd, data, size); if (r < 0) { DEBUG(perror("error writing to port");); diff --git a/flow/src/main/native/posix/flow_jni.c b/flow/src/main/native/posix/flow_jni.c index 3af2873..9e0ec5e 100644 --- a/flow/src/main/native/posix/flow_jni.c +++ b/flow/src/main/native/posix/flow_jni.c @@ -1,70 +1,144 @@ #include "flow.h" #include "com_github_jodersky_flow_internal_NativeSerial.h" -inline struct serial_config* j2s(jlong pointer) { - return (struct serial_config*) pointer; + +static inline void throwException(JNIEnv* env, const char* const exception, const char * const message) { + (*env)->ThrowNew(env, (*env)->FindClass(env, exception), message); } -inline jlong s2j(struct serial_config* pointer) { - return (jlong) pointer; +static inline void check(JNIEnv* env, int id) { + switch (id) { + case E_IO: throwException(env, "java/io/IOException", ""); break; + case E_BUSY: throwException(env, "com/github/jodersky/flow/PortInUseException", ""); break; + case E_ACCESS_DENIED: throwException(env, "com/github/jodersky/flow/AccessDeniedException", ""); break; + case E_INVALID_SETTINGS: throwException(env, "com/github/jodersky/flow/InvalidSettingsException", ""); break; + case E_INTERRUPT: throwException(env, "com/github/jodersky/flow/PortInterruptedException", ""); break; + case E_NO_PORT: throwException(env, "com/github/jodersky/flow/NoSuchPortException", ""); break; + default: return; + } } + + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: open + * Signature: (Ljava/lang/String;IIZI)J + */ +JNIEXPORT jlong JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_open + (JNIEnv *env, jclass clazz, jstring port_name, jint baud, jint char_size, jboolean two_stop_bits, jint parity) { + + const char *dev = (*env)->GetStringUTFChars(env, port_name, 0); + struct serial_config* config; + int r = serial_open(dev, baud, char_size, two_stop_bits, parity, &config); + (*env)->ReleaseStringUTFChars(env, port_name, dev); -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_open -(JNIEnv *env, jclass clazz, jstring port_name, jint baud, jint char_size, jboolean two_stop_bits, jint parity, jlongArray jserialp) -{ - const char *dev = (*env)->GetStringUTFChars(env, port_name, 0); - struct serial_config* serial; - int r = serial_open(dev, baud, char_size, two_stop_bits, parity, &serial); - (*env)->ReleaseStringUTFChars(env, port_name, dev); - long serialp = s2j(serial); - (*env)->SetLongArrayRegion(env, jserialp, 0, 1, &serialp); + if (r < 0) { + check(env, r); + return 0; + } - return r; + long jpointer = (long) config; + return jpointer; + } -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_close -(JNIEnv * env, jclass clazz, jlong serial) -{ - serial_close(j2s(serial)); +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: readDirect + * Signature: (JLjava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_readDirect + (JNIEnv *env, jclass clazz, jlong config, jobject buffer) { + return 0; } +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: read + * Signature: (J[B)I + */ JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_read -(JNIEnv * env, jclass clazz, jlong serial, jbyteArray jbuffer) -{ + (JNIEnv *env, jclass clazz, jlong config, jbyteArray buffer) { + + jsize size = (*env)->GetArrayLength(env, buffer); + char local_buffer[size]; + int r = serial_read((struct serial_config*) config, local_buffer, size); + if (r < 0) { + check(env, r); + return -1; + } + + (*env)->SetByteArrayRegion(env, buffer, 0, r, (signed char *) local_buffer); + return r; - jsize size = (*env)->GetArrayLength(env, jbuffer); - - unsigned char buffer[size]; - int n = serial_read(j2s(serial), buffer, size); - if (n < 0) { - return n; } -(*env)->SetByteArrayRegion(env, jbuffer, 0, n, (signed char *) buffer); -return n; +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: cancelRead + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_cancelRead + (JNIEnv *env, jclass clazz, jlong config) { + + int r = serial_cancel_read((struct serial_config*) config); + if (r < 0) { + check(env, r); + } + } +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: writeDirect + * Signature: (JLjava/nio/ByteBuffer;I)I + */ +JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_writeDirect + (JNIEnv *env, jclass clazz, jlong config, jobject buffer, jint size) { + + return 0; + +} + +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: write + * Signature: (J[BI)I + */ JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_write -(JNIEnv * env, jclass clazz, jlong serial, jbyteArray jbuffer) -{ - unsigned char * buffer = (*env)->GetByteArrayElements(env, jbuffer, NULL); - int size = (*env)->GetArrayLength(env, jbuffer); - int r = serial_write(j2s(serial), buffer, size); - - (*env)->ReleaseByteArrayElements(env, jbuffer, buffer, JNI_ABORT); - - return r; + (JNIEnv *env, jclass clazz, jlong config, jbyteArray buffer, jint size) { + + char* local_buffer = (char*) (*env)->GetByteArrayElements(env, buffer, NULL); + int r = serial_write((struct serial_config*) config, local_buffer, size); + (*env)->ReleaseByteArrayElements(env, buffer, (signed char*) local_buffer, JNI_ABORT); + if (r < 0) { + check(env, r); + return -1; + } + return r; + } -JNIEXPORT jint JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_interrupt -(JNIEnv * env, jclass clazz, jlong serial) -{ - return serial_interrupt(j2s(serial)); +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: close + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_close + (JNIEnv *env, jclass clazz, jlong config) { + int r = serial_close((struct serial_config*) config); + if (r < 0) { + check(env, r); + } } +/* + * Class: com_github_jodersky_flow_internal_NativeSerial + * Method: debug + * Signature: (Z)V + */ JNIEXPORT void JNICALL Java_com_github_jodersky_flow_internal_NativeSerial_debug -(JNIEnv *env, jclass clazz, jboolean value) -{ - serial_debug((bool) value); -} + (JNIEnv *env, jclass clazz, jboolean value) { + serial_debug((bool) value); +} \ No newline at end of file diff --git a/flow/src/main/scala/com/github/jodersky/flow/internal/SerialConnection.scala b/flow/src/main/scala/com/github/jodersky/flow/internal/SerialConnection.scala index 446160d..3bdc7ec 100644 --- a/flow/src/main/scala/com/github/jodersky/flow/internal/SerialConnection.scala +++ b/flow/src/main/scala/com/github/jodersky/flow/internal/SerialConnection.scala @@ -3,8 +3,7 @@ package com.github.jodersky.flow.internal import java.nio.ByteBuffer import java.util.concurrent.atomic.AtomicBoolean -import com.github.jodersky.flow.PortClosedException -import com.github.jodersky.flow.SerialSettings +import com.github.jodersky.flow._ /** * Represents a serial connection in a more secure and object-oriented style than `NativeSerial`. In contrast @@ -43,10 +42,10 @@ class SerialConnection private ( closed.set(true) NativeSerial.cancelRead(pointer) readLock.synchronized { - while (reading) wait() + while (reading) this.wait() } writeLock.synchronized { - while (writing) wait() + while (writing) this.wait() } NativeSerial.close(pointer) } @@ -77,7 +76,7 @@ class SerialConnection private ( b => NativeSerial.read(pointer, b.array()))(buffer) } finally { reading = false - if (closed.get) notify() + if (closed.get) readLock.notify() } } else { throw new PortClosedException(s"port ${port} is closed") @@ -108,7 +107,7 @@ class SerialConnection private ( b => NativeSerial.write(pointer, b.array(), b.remaining()))(buffer) } finally { writing = false - if (closed.get) notify() + if (closed.get) writeLock.notify() } } else { throw new PortClosedException(s"port ${port} is closed") -- cgit v1.2.3