aboutsummaryrefslogtreecommitdiff
path: root/native/src/akka_serial_jni.c
diff options
context:
space:
mode:
Diffstat (limited to 'native/src/akka_serial_jni.c')
-rw-r--r--native/src/akka_serial_jni.c150
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);
+}