Files
allwpilib/wpilibj/wpilibJavaJNI/lib/SerialPortJNI.cpp
Peter Johnson 7023013c4b Simplify JNI interfaces.
These changes both simplify the Java code and improve performance across the
JNI boundary.

This also fixes the AnalogCrossConnectTest by adding delays to
setInterruptHigh() and setInterruptLow() to ensure the change in voltage has
time to propagate and extends the timeouts in AbstractInterruptTest.

Detailed changes:

Hoisted status checks to C.  This avoids the need to create direct byte
buffers (expensive) and significantly simplifies the Java code.  The C code
now directly generates the exception or reports the error to the DS.

The JVM pointer is now a global across the JNI, initialized by the OnLoad
function, avoiding the need for some of the class-specific initializers to
get this pointer for callbacks.

Opaque pointers (such as ports) are now passed as long values rather than
with a ByteBuffer wrapper.

Added extern "C" to source files.  This allows earlier detection of JNI
definition mismatches to the Java source headers.

Changed JNI signatures to more closely match HAL signatures (in particular,
boolean is now universally used instead of byte for HAL bool, which cleans
up mapping back and forth to 1/0 from true/false).

Change-Id: I4ea0032cabb0871cd74106a3a70d947258c29d2d
2015-11-06 09:04:22 -08:00

312 lines
9.2 KiB
C++

#include <jni.h>
#include <assert.h>
#include "Log.hpp"
#include "edu_wpi_first_wpilibj_hal_SerialPortJNI.h"
#include "HAL/SerialPort.hpp"
#include "HALUtil.h"
// set the logging level
TLogLevel serialJNILogLevel = logWARNING;
#define SERIALJNI_LOG(level) \
if (level > serialJNILogLevel) ; \
else Log().Get(level)
extern "C" {
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialInitializePort
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialInitializePort
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Calling Serial Initialize";
SERIALJNI_LOG(logDEBUG) << "Port = " << (jint) port;
int32_t status = 0;
serialInitializePort(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetBaudRate
* Signature: (BI)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetBaudRate
(JNIEnv * env, jclass, jbyte port, jint rate)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Baud Rate";
SERIALJNI_LOG(logDEBUG) << "Baud: " << rate;
int32_t status = 0;
serialSetBaudRate(port, rate, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetDataBits
* Signature: (BB)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetDataBits
(JNIEnv * env, jclass, jbyte port, jbyte bits)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Data Bits";
SERIALJNI_LOG(logDEBUG) << "Data Bits: " << bits;
int32_t status = 0;
serialSetDataBits(port, bits, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetParity
* Signature: (BB)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetParity
(JNIEnv * env, jclass, jbyte port, jbyte parity)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Parity";
SERIALJNI_LOG(logDEBUG) << "Parity: " << parity;
int32_t status = 0;
serialSetParity(port, parity, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetStopBits
* Signature: (BB)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetStopBits
(JNIEnv * env, jclass, jbyte port, jbyte bits)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Stop Bits";
SERIALJNI_LOG(logDEBUG) << "Stop Bits: " << bits;
int32_t status = 0;
serialSetStopBits(port, bits, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetWriteMode
* Signature: (BB)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetWriteMode
(JNIEnv * env, jclass, jbyte port, jbyte mode)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Write Mode";
SERIALJNI_LOG(logDEBUG) << "Write mode: " << mode;
int32_t status = 0;
serialSetWriteMode(port, mode, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetFlowControl
* Signature: (BB)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetFlowControl
(JNIEnv * env, jclass, jbyte port, jbyte flow)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Flow Control";
SERIALJNI_LOG(logDEBUG) << "Flow Control: " << flow;
int32_t status = 0;
serialSetFlowControl(port, flow, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetTimeout
* Signature: (BF)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetTimeout
(JNIEnv * env, jclass, jbyte port, jfloat timeout)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Timeout";
SERIALJNI_LOG(logDEBUG) << "Timeout: " << timeout;
int32_t status = 0;
serialSetTimeout(port, timeout, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialEnableTermination
* Signature: (BC)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialEnableTermination
(JNIEnv * env, jclass, jbyte port, jchar terminator)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Enable Termination";
SERIALJNI_LOG(logDEBUG) << "Terminator: " << terminator;
int32_t status = 0;
serialEnableTermination(port, terminator, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialDisableTermination
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialDisableTermination
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Disable termination";
int32_t status = 0;
serialDisableTermination(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetReadBufferSize
* Signature: (BI)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetReadBufferSize
(JNIEnv * env, jclass, jbyte port, jint size)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Read Buffer Size";
SERIALJNI_LOG(logDEBUG) << "Size: " << size;
int32_t status = 0;
serialSetReadBufferSize(port, size, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialSetWriteBufferSize
* Signature: (BI)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetWriteBufferSize
(JNIEnv * env, jclass, jbyte port, jint size)
{
SERIALJNI_LOG(logDEBUG) << "Setting Serial Write Buffer Size";
SERIALJNI_LOG(logDEBUG) << "Size: " << size;
int32_t status = 0;
serialSetWriteBufferSize(port, size, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialGetBytesRecieved
* Signature: (B)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialGetBytesRecieved
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Serial Get Bytes Received";
int32_t status = 0;
jint retVal = serialGetBytesReceived(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialRead
* Signature: (BLjava/nio/ByteBuffer;I)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialRead
(JNIEnv * env, jclass, jbyte port, jobject dataReceived, jint size)
{
SERIALJNI_LOG(logDEBUG) << "Serial Read";
jbyte * dataReceivedPtr = NULL;
dataReceivedPtr = (jbyte*)env->GetDirectBufferAddress(dataReceived);
int32_t status = 0;
jint retVal = serialRead(port, (char*)dataReceivedPtr, size, &status);
SERIALJNI_LOG(logDEBUG) << "ReturnValue = " << retVal;
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialWrite
* Signature: (BLjava/nio/ByteBuffer;I)I
*/
JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialWrite
(JNIEnv * env, jclass, jbyte port, jobject dataToSend, jint size)
{
SERIALJNI_LOG(logDEBUG) << "Serial Write";
jbyte * dataToSendPtr = NULL;
if(dataToSend != 0){
dataToSendPtr = (jbyte*)env->GetDirectBufferAddress(dataToSend);
}
int32_t status = 0;
jint retVal = serialWrite(port, (const char*)dataToSendPtr, size, &status);
SERIALJNI_LOG(logDEBUG) << "ReturnValue = " << retVal;
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
return retVal;
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialFlush
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialFlush
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Serial Flush";
int32_t status = 0;
serialFlush(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialClear
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialClear
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Serial Clear";
int32_t status = 0;
serialClear(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_wpilibj_hal_SerialPortJNI
* Method: serialClose
* Signature: (B)V
*/
JNIEXPORT void JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialClose
(JNIEnv * env, jclass, jbyte port)
{
SERIALJNI_LOG(logDEBUG) << "Serial Close";
int32_t status = 0;
serialClose(port, &status);
SERIALJNI_LOG(logDEBUG) << "Status = " << status;
CheckStatus(env, status);
}
} // extern "C"