From 554bda33322b2f92f73f6d03343168bb014cf720 Mon Sep 17 00:00:00 2001 From: Thad House Date: Tue, 18 Feb 2020 20:44:40 -0800 Subject: [PATCH] HAL: Expose NetComm SendConsoleLine (#2337) This can be use to synchronize writes between threads, assuming writes all go through this and not stdout. --- hal/src/main/java/edu/wpi/first/hal/HAL.java | 4 ++- .../sim/mockdata/DriverStationDataJNI.java | 3 ++- .../main/native/athena/FRCDriverStation.cpp | 26 ++++++++++++++----- hal/src/main/native/cpp/jni/HAL.cpp | 17 +++++++++++- .../main/native/include/hal/DriverStation.h | 8 +++++- .../main/native/include/mockdata/MockHooks.h | 5 +++- hal/src/main/native/sim/DriverStation.cpp | 17 ++++++++++++ .../native/sim/jni/DriverStationDataJNI.cpp | 20 ++++++++++++-- 8 files changed, 86 insertions(+), 14 deletions(-) diff --git a/hal/src/main/java/edu/wpi/first/hal/HAL.java b/hal/src/main/java/edu/wpi/first/hal/HAL.java index 8f09a0a863..c132a58e45 100644 --- a/hal/src/main/java/edu/wpi/first/hal/HAL.java +++ b/hal/src/main/java/edu/wpi/first/hal/HAL.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -130,6 +130,8 @@ public final class HAL extends JNIWrapper { String details, String location, String callStack, boolean printMsg); + public static native int sendConsoleLine(String line); + public static native int getPortWithModule(byte module, byte channel); public static native int getPort(byte channel); diff --git a/hal/src/main/java/edu/wpi/first/hal/sim/mockdata/DriverStationDataJNI.java b/hal/src/main/java/edu/wpi/first/hal/sim/mockdata/DriverStationDataJNI.java index ec197350d8..93d7c30dfd 100644 --- a/hal/src/main/java/edu/wpi/first/hal/sim/mockdata/DriverStationDataJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/sim/mockdata/DriverStationDataJNI.java @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -50,6 +50,7 @@ public class DriverStationDataJNI extends JNIWrapper { public static native void notifyNewData(); public static native void setSendError(boolean shouldSend); + public static native void setSendConsoleLine(boolean shouldSend); public static native void resetData(); } diff --git a/hal/src/main/native/athena/FRCDriverStation.cpp b/hal/src/main/native/athena/FRCDriverStation.cpp index 5b29815b28..a822cbaa87 100644 --- a/hal/src/main/native/athena/FRCDriverStation.cpp +++ b/hal/src/main/native/athena/FRCDriverStation.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -176,27 +176,27 @@ int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, if (baseLength + detailsRef.size() + locationRef.size() + callStackRef.size() <= - 65536) { + 65535) { // Pass through retval = FRC_NetworkCommunication_sendError(isError, errorCode, isLVCode, details, location, callStack); - } else if (baseLength + detailsRef.size() > 65536) { + } else if (baseLength + detailsRef.size() > 65535) { // Details too long, cut both location and stack - auto newLen = 65536 - baseLength; + auto newLen = 65535 - baseLength; std::string newDetails{details, newLen}; char empty = '\0'; retval = FRC_NetworkCommunication_sendError( isError, errorCode, isLVCode, newDetails.c_str(), &empty, &empty); - } else if (baseLength + detailsRef.size() + locationRef.size() > 65536) { + } else if (baseLength + detailsRef.size() + locationRef.size() > 65535) { // Location too long, cut stack - auto newLen = 65536 - baseLength - detailsRef.size(); + auto newLen = 65535 - baseLength - detailsRef.size(); std::string newLocation{location, newLen}; char empty = '\0'; retval = FRC_NetworkCommunication_sendError( isError, errorCode, isLVCode, details, newLocation.c_str(), &empty); } else { // Stack too long - auto newLen = 65536 - baseLength - detailsRef.size() - locationRef.size(); + auto newLen = 65535 - baseLength - detailsRef.size() - locationRef.size(); std::string newCallStack{callStack, newLen}; retval = FRC_NetworkCommunication_sendError(isError, errorCode, isLVCode, details, location, @@ -229,6 +229,18 @@ int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, return retval; } +int32_t HAL_SendConsoleLine(const char* line) { + wpi::StringRef lineRef{line}; + if (lineRef.size() <= 65535) { + // Send directly + return FRC_NetworkCommunication_sendConsoleLine(line); + } else { + // Need to truncate + std::string newLine{line, 65535}; + return FRC_NetworkCommunication_sendConsoleLine(newLine.c_str()); + } +} + int32_t HAL_GetControlWord(HAL_ControlWord* controlWord) { return HAL_GetControlWordInternal(controlWord); } diff --git a/hal/src/main/native/cpp/jni/HAL.cpp b/hal/src/main/native/cpp/jni/HAL.cpp index 393b0b4d17..f60dce4379 100644 --- a/hal/src/main/native/cpp/jni/HAL.cpp +++ b/hal/src/main/native/cpp/jni/HAL.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2016-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2016-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -448,6 +448,21 @@ Java_edu_wpi_first_hal_HAL_sendError return returnValue; } +/* + * Class: edu_wpi_first_hal_HAL + * Method: sendConsoleLine + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_hal_HAL_sendConsoleLine + (JNIEnv* env, jclass, jstring line) +{ + JStringRef lineStr{env, line}; + + jint returnValue = HAL_SendConsoleLine(lineStr.c_str()); + return returnValue; +} + /* * Class: edu_wpi_first_hal_HAL * Method: getPortWithModule diff --git a/hal/src/main/native/include/hal/DriverStation.h b/hal/src/main/native/include/hal/DriverStation.h index 471c18b971..091e662449 100644 --- a/hal/src/main/native/include/hal/DriverStation.h +++ b/hal/src/main/native/include/hal/DriverStation.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2013-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2013-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -37,6 +37,12 @@ extern "C" { int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, const char* details, const char* location, const char* callStack, HAL_Bool printMsg); +/** + * Sends a line to the driver station console. + * + * @param line the line to send (null terminated) + */ +int32_t HAL_SendConsoleLine(const char* line); /** * Gets the current control word of the driver station. diff --git a/hal/src/main/native/include/mockdata/MockHooks.h b/hal/src/main/native/include/mockdata/MockHooks.h index 318ff21135..31751f8e40 100644 --- a/hal/src/main/native/include/mockdata/MockHooks.h +++ b/hal/src/main/native/include/mockdata/MockHooks.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2017-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -24,4 +24,7 @@ typedef int32_t (*HALSIM_SendErrorHandler)( const char* location, const char* callStack, HAL_Bool printMsg); void HALSIM_SetSendError(HALSIM_SendErrorHandler handler); +typedef int32_t (*HALSIM_SendConsoleLineHandler)(const char* line); +void HALSIM_SetSendConsoleLine(HALSIM_SendConsoleLineHandler handler); + } // extern "C" diff --git a/hal/src/main/native/sim/DriverStation.cpp b/hal/src/main/native/sim/DriverStation.cpp index 14e0ffdde0..9e97c56cea 100644 --- a/hal/src/main/native/sim/DriverStation.cpp +++ b/hal/src/main/native/sim/DriverStation.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "HALInitializer.h" #include "mockdata/DriverStationDataInternal.h" @@ -29,6 +30,8 @@ static wpi::mutex newDSDataAvailableMutex; static int newDSDataAvailableCounter{0}; static std::atomic_bool isFinalized{false}; static std::atomic sendErrorHandler{nullptr}; +static std::atomic sendConsoleLineHandler{ + nullptr}; namespace hal { namespace init { @@ -47,6 +50,10 @@ void HALSIM_SetSendError(HALSIM_SendErrorHandler handler) { sendErrorHandler.store(handler); } +void HALSIM_SetSendConsoleLine(HALSIM_SendConsoleLineHandler handler) { + sendConsoleLineHandler.store(handler); +} + int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, const char* details, const char* location, const char* callStack, HAL_Bool printMsg) { @@ -105,6 +112,16 @@ int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, return retval; } +int32_t HAL_SendConsoleLine(const char* line) { + auto handler = sendConsoleLineHandler.load(); + if (handler) { + return handler(line); + } + wpi::outs() << line << "\n"; + wpi::outs().flush(); + return 0; +} + int32_t HAL_GetControlWord(HAL_ControlWord* controlWord) { controlWord->enabled = SimDriverStationData->enabled; controlWord->autonomous = SimDriverStationData->autonomous; diff --git a/hal/src/main/native/sim/jni/DriverStationDataJNI.cpp b/hal/src/main/native/sim/jni/DriverStationDataJNI.cpp index 82433b3f07..6a1432dbd3 100644 --- a/hal/src/main/native/sim/jni/DriverStationDataJNI.cpp +++ b/hal/src/main/native/sim/jni/DriverStationDataJNI.cpp @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------------*/ -/* Copyright (c) 2018-2019 FIRST. All Rights Reserved. */ +/* Copyright (c) 2018-2020 FIRST. All Rights Reserved. */ /* Open Source Software - may be modified and shared by FRC teams. The code */ /* must be accompanied by the FIRST BSD license file in the root directory of */ /* the project. */ @@ -462,7 +462,23 @@ Java_edu_wpi_first_hal_sim_mockdata_DriverStationDataJNI_setSendError HALSIM_SetSendError([](HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, const char* details, const char* location, const char* callStack, - HAL_Bool printMsg) { return 1; }); + HAL_Bool printMsg) { return 0; }); + } +} + +/* + * Class: edu_wpi_first_hal_sim_mockdata_DriverStationDataJNI + * Method: setSendConsoleLine + * Signature: (Z)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_hal_sim_mockdata_DriverStationDataJNI_setSendConsoleLine + (JNIEnv*, jclass, jboolean shouldSend) +{ + if (shouldSend) { + HALSIM_SetSendConsoleLine(nullptr); + } else { + HALSIM_SetSendConsoleLine([](const char* line) { return 0; }); } }