diff options
Diffstat (limited to 'native/src/akka_serial_jni.c')
-rw-r--r-- | native/src/akka_serial_jni.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/native/src/akka_serial_jni.c b/native/src/akka_serial_jni.c new file mode 100644 index 0000000..126a7bf --- /dev/null +++ b/native/src/akka_serial_jni.c @@ -0,0 +1,150 @@ +#include <stdint.h> + +#include "akka_serial.h" + +#include "akka_serial_sync_UnsafeSerial.h" +#include "akka_serial_sync_UnsafeSerial__.h" + +// suppress unused parameter warnings +#define UNUSED_ARG(x) (void)(x) + +static inline void throwException(JNIEnv* env, const char* const exception, const char * const message) +{ + (*env)->ThrowNew(env, (*env)->FindClass(env, exception), message); +} + +/** Check return code and throw exception in case it is non-zero. */ +static void check(JNIEnv* env, int ret) +{ + switch (ret) { + case -E_IO: throwException(env, "java/io/IOException", ""); break; + case -E_BUSY: throwException(env, "akka/serial/PortInUseException", ""); break; + case -E_ACCESS_DENIED: throwException(env, "akka/serial/AccessDeniedException", ""); break; + case -E_INVALID_SETTINGS: throwException(env, "akka/serial/InvalidSettingsException", ""); break; + case -E_INTERRUPT: throwException(env, "akka/serial/PortInterruptedException", ""); break; + case -E_NO_PORT: throwException(env, "akka/serial/NoSuchPortException", ""); break; + default: return; + } +} + +/** Get pointer to serial config associated to an UnsafeSerial instance. */ +static struct serial_config* get_config(JNIEnv* env, jobject unsafe_serial) +{ + jclass clazz = (*env)->FindClass(env, "akka/serial/sync/UnsafeSerial"); + jfieldID field = (*env)->GetFieldID(env, clazz, "serialAddr", "J"); + jlong addr = (*env)->GetLongField(env, unsafe_serial, field); + return (struct serial_config*) (intptr_t) addr; +} + +/* + * Class: akka_serial_sync_UnsafeSerial__ + * Method: open + * Signature: (Ljava/lang/String;IIZI)J + */ +JNIEXPORT jlong JNICALL Java_akka_serial_sync_UnsafeSerial_00024_open +(JNIEnv *env, jobject instance, jstring port_name, jint baud, jint char_size, jboolean two_stop_bits, jint parity) +{ + UNUSED_ARG(instance); + + 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); + + if (r < 0) { + check(env, r); + return -E_IO; + } + + long jpointer = (long) config; + return (jlong) jpointer; +} + +/* + * Class: akka_serial_sync_UnsafeSerial + * Method: read + * Signature: (Ljava/nio/ByteBuffer;)I + */ +JNIEXPORT jint JNICALL Java_akka_serial_sync_UnsafeSerial_read +(JNIEnv *env, jobject instance, jobject buffer) +{ + char* local_buffer = (char*) (*env)->GetDirectBufferAddress(env, buffer); + if (local_buffer == NULL) { + throwException(env, "java/lang/IllegalArgumentException", "buffer is not direct"); + return -E_IO; + } + size_t size = (size_t) (*env)->GetDirectBufferCapacity(env, buffer); + struct serial_config* config = get_config(env, instance); + + int r = serial_read(config, local_buffer, size); + if (r < 0) { + check(env, r); + } + return r; + +} + +/* + * Class: akka_serial_sync_UnsafeSerial + * Method: cancelRead + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_akka_serial_sync_UnsafeSerial_cancelRead +(JNIEnv *env, jobject instance) +{ + int r = serial_cancel_read(get_config(env, instance)); + if (r < 0) { + check(env, r); + } +} + +/* + * Class: akka_serial_sync_UnsafeSerial + * Method: write + * Signature: (Ljava/nio/ByteBuffer;I)I + */ +JNIEXPORT jint JNICALL Java_akka_serial_sync_UnsafeSerial_write +(JNIEnv *env, jobject instance, jobject buffer, jint size) +{ + + char* local_buffer = (char *) (*env)->GetDirectBufferAddress(env, buffer); + if (local_buffer == NULL) { + throwException(env, "java/lang/IllegalArgumentException", "buffer is not direct"); + return -E_IO; + } + + int r = serial_write(get_config(env, instance), local_buffer, (size_t) size); + if (r < 0) { + check(env, r); + return -E_IO; + } + return r; +} + +/* + * Class: akka_serial_sync_UnsafeSerial + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_akka_serial_sync_UnsafeSerial_close +(JNIEnv *env, jobject instance) +{ + int r = serial_close(get_config(env, instance)); + if (r < 0) { + check(env, r); + } +} + +/* + * Class: akka_serial_sync_UnsafeSerial__ + * Method: debug + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_akka_serial_sync_UnsafeSerial_00024_debug +(JNIEnv *env, jobject instance, jboolean value) +{ + UNUSED_ARG(env); + UNUSED_ARG(instance); + + serial_debug((bool) value); +} |