aboutsummaryrefslogblamecommitdiff
path: root/flow-native/src/flow_jni.c
blob: 8ec2aed50552fac260fabe834d2b2138ccd6f4cd (plain) (tree)








































































































































































                                                                                                                   
#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);
}