#include "flow.h"
#include "com_github_jodersky_flow_internal_NativeSerial.h"
static inline void throwException(JNIEnv* env, const char* const exception, const char * const message) {
(*env)->ThrowNew(env, (*env)->FindClass(env, exception), message);
}
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);
if (r < 0) {
check(env, r);
return 0;
}
long jpointer = (long) config;
return jpointer;
}
/*
* 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) {
char* local_buffer = (char*) (*env)->GetDirectBufferAddress(env, buffer);
if (local_buffer == NULL) {
throwException(env, "java/lang/IllegalArgumentException", "ByteBuffer not direct");
return -1;
}
jlong size = (*env)->GetDirectBufferCapacity(env, buffer);
int r = serial_read((struct serial_config*) config, local_buffer, (size_t) size);
if (r < 0) {
check(env, r);
return -1;
}
return r;
}
/*
* 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 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;
}
/*
* 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) {
char* local_buffer = (char *) (*env)->GetDirectBufferAddress(env, buffer);
if (local_buffer == NULL) {
throwException(env, "java/lang/IllegalArgumentException", "ByteBuffer not direct");
return -1;
}
int r = serial_write((struct serial_config*) config, local_buffer, (size_t) size);
if (r < 0) {
check(env, r);
return -1;
}
return r;
}
/*
* 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 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;
}
/*
* 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);
}