diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java b/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java index e0734dd369..177833bf82 100644 --- a/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANJNI.java @@ -31,5 +31,6 @@ public class CANJNI extends JNIWrapper { public static native void closeCANStreamSession(int sessionHandle); public static native int readCANStreamSession( - int sessionHandle, CANStreamMessage[] messages, int messagesToRead); + int sessionHandle, CANStreamMessage[] messages, int messagesToRead) + throws CANStreamOverflowException; } diff --git a/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java new file mode 100644 index 0000000000..41d2bb56a2 --- /dev/null +++ b/hal/src/main/java/edu/wpi/first/hal/can/CANStreamOverflowException.java @@ -0,0 +1,35 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +package edu.wpi.first.hal.can; + +import edu.wpi.first.hal.CANStreamMessage; +import java.io.IOException; + +public class CANStreamOverflowException extends IOException { + private final CANStreamMessage[] m_messages; + private final int m_messagesRead; + + /** + * Constructs a new CANStreamOverflowException. + * + * @param messages The messages + * @param messagesRead The length of messages read + */ + @SuppressWarnings("PMD.ArrayIsStoredDirectly") + public CANStreamOverflowException(CANStreamMessage[] messages, int messagesRead) { + super("A CAN Stream has overflowed. Data will be missed"); + this.m_messages = messages; + this.m_messagesRead = messagesRead; + } + + @SuppressWarnings("PMD.MethodReturnsInternalArray") + public CANStreamMessage[] getMessages() { + return m_messages; + } + + public int getMessagesRead() { + return m_messagesRead; + } +} diff --git a/hal/src/main/native/cpp/jni/CANJNI.cpp b/hal/src/main/native/cpp/jni/CANJNI.cpp index 53e344abdb..2339b5e05f 100644 --- a/hal/src/main/native/cpp/jni/CANJNI.cpp +++ b/hal/src/main/native/cpp/jni/CANJNI.cpp @@ -151,7 +151,8 @@ Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession return 0; } - if (!CheckStatus(env, status)) { + if (status != HAL_ERR_CANSessionMux_SessionOverrun && + !CheckStatus(env, status)) { return 0; } @@ -181,6 +182,12 @@ Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession reinterpret_cast(msg->data)); } + if (status == HAL_ERR_CANSessionMux_SessionOverrun) { + ThrowCANStreamOverflowException(env, messages, + static_cast(messagesRead)); + return 0; + } + return static_cast(messagesRead); } diff --git a/hal/src/main/native/cpp/jni/HALUtil.cpp b/hal/src/main/native/cpp/jni/HALUtil.cpp index 3c7f04ce48..b84ccadaea 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.cpp +++ b/hal/src/main/native/cpp/jni/HALUtil.cpp @@ -56,6 +56,7 @@ static JClass canStreamMessageCls; static JClass halValueCls; static JClass baseStoreCls; static JClass revPHVersionCls; +static JClass canStreamOverflowExCls; static const JClassInit classes[] = { {"edu/wpi/first/hal/PowerDistributionVersion", @@ -68,7 +69,9 @@ static const JClassInit classes[] = { {"edu/wpi/first/hal/CANStreamMessage", &canStreamMessageCls}, {"edu/wpi/first/hal/HALValue", &halValueCls}, {"edu/wpi/first/hal/DMAJNISample$BaseStore", &baseStoreCls}, - {"edu/wpi/first/hal/REVPHVersion", &revPHVersionCls}}; + {"edu/wpi/first/hal/REVPHVersion", &revPHVersionCls}, + {"edu/wpi/first/hal/can/CANStreamOverflowException", + &canStreamOverflowExCls}}; static const JExceptionInit exceptions[] = { {"java/lang/IllegalArgumentException", &illegalArgExCls}, @@ -209,6 +212,16 @@ void ReportCANError(JNIEnv* env, int32_t status, int message_id) { } } +void ThrowCANStreamOverflowException(JNIEnv* env, jobjectArray messages, + jint length) { + static jmethodID constructor = + env->GetMethodID(canStreamOverflowExCls, "", + "([Ledu/wpi/first/hal/CANStreamMessage;I)V"); + jobject exception = + env->NewObject(canStreamOverflowExCls, constructor, messages, length); + env->Throw(static_cast(exception)); +} + void ThrowIllegalArgumentException(JNIEnv* env, std::string_view msg) { illegalArgExCls.Throw(env, msg); } diff --git a/hal/src/main/native/cpp/jni/HALUtil.h b/hal/src/main/native/cpp/jni/HALUtil.h index b3fdd31e87..d86c0e2b92 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.h +++ b/hal/src/main/native/cpp/jni/HALUtil.h @@ -51,6 +51,8 @@ inline bool CheckCANStatus(JNIEnv* env, int32_t status, int32_t message_id) { return status == 0; } +void ThrowCANStreamOverflowException(JNIEnv* env, jobjectArray messages, + jint length); void ThrowIllegalArgumentException(JNIEnv* env, std::string_view msg); void ThrowBoundaryException(JNIEnv* env, double value, double lower, double upper);