[hal, wpilib] Rewrite CAN APIs (#7798)

This commit is contained in:
Thad House
2025-02-25 19:07:01 -08:00
committed by GitHub
parent b39744b562
commit baa20fa239
107 changed files with 1447 additions and 1379 deletions

View File

@@ -19,29 +19,20 @@ using namespace wpi::java;
extern "C" {
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: getCANPacketBaseTime
* Signature: ()J
*/
JNIEXPORT jlong JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_getCANPacketBaseTime
(JNIEnv*, jclass)
{
return HAL_GetCANPacketBaseTime();
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: initializeCAN
* Signature: (III)I
* Signature: (IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_initializeCAN
(JNIEnv* env, jclass, jint manufacturer, jint deviceId, jint deviceType)
(JNIEnv* env, jclass, jint busId, jint manufacturer, jint deviceId,
jint deviceType)
{
int32_t status = 0;
auto handle =
HAL_InitializeCAN(static_cast<HAL_CANManufacturer>(manufacturer),
HAL_InitializeCAN(static_cast<int32_t>(busId),
static_cast<HAL_CANManufacturer>(manufacturer),
static_cast<int32_t>(deviceId),
static_cast<HAL_CANDeviceType>(deviceType), &status);
@@ -63,105 +54,189 @@ Java_edu_wpi_first_hal_CANAPIJNI_cleanCAN
}
}
static bool PackCANMessage(JNIEnv* env, jbyteArray data, jint dataLength,
jint flags, HAL_CANMessage* message) {
if (data == nullptr) {
ThrowNullPointerException(env, "data array cannot be null");
return false;
}
auto arrLen = env->GetArrayLength(data);
if (arrLen < dataLength) {
ThrowIllegalArgumentException(env, "array length less than data length");
return false;
}
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
return false;
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
ThrowIllegalArgumentException(env,
"Non FD frame has max length of 8 bytes");
return false;
}
std::memset(message, 0, sizeof(*message));
message->dataSize = dataLength;
message->flags = flags;
JSpan<const jbyte> arr{env, data, static_cast<size_t>(dataLength)};
std::memcpy(message->data, arr.data(), dataLength);
return true;
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANPacket
* Signature: (I[BI)V
* Signature: (II[BII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacket
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
JSpan<const jbyte> arr{env, data};
HAL_CANMessage message;
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return;
}
int32_t status = 0;
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
arr.size(), apiId, &status);
HAL_WriteCANPacket(static_cast<HAL_CANHandle>(handle), apiId, &message,
&status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANPacketRepeating
* Signature: (I[BII)V
* Signature: (II[BIII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeating
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId,
jint timeoutMs)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags, jint repeatMs)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
JSpan<const jbyte> arr{env, data};
HAL_CANMessage message;
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return;
}
int32_t status = 0;
HAL_WriteCANPacketRepeating(halHandle,
reinterpret_cast<const uint8_t*>(arr.data()),
arr.size(), apiId, timeoutMs, &status);
HAL_WriteCANPacketRepeating(static_cast<HAL_CANHandle>(handle), apiId,
&message, repeatMs, &status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANRTRFrame
* Signature: (III)V
* Signature: (II[BII)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANRTRFrame
(JNIEnv* env, jclass, jint handle, jint length, jint apiId)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
HAL_CANMessage message;
if (data == nullptr) {
// We will allow RTR frames to have a null data array
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
return;
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
ThrowIllegalArgumentException(env,
"Non FD frame has max length of 8 bytes");
return;
}
std::memset(&message, 0, sizeof(message));
message.flags = flags;
message.dataSize = dataLength;
} else if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return;
}
int32_t status = 0;
HAL_WriteCANRTRFrame(halHandle, static_cast<int32_t>(length), apiId, &status);
HAL_WriteCANRTRFrame(static_cast<HAL_CANHandle>(handle), apiId, &message,
&status);
CheckStatus(env, status);
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANPacketNoThrow
* Signature: (I[BI)I
* Signature: (II[BII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketNoThrow
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
JSpan<const jbyte> arr{env, data};
HAL_CANMessage message;
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return PARAMETER_OUT_OF_RANGE;
}
int32_t status = 0;
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
arr.size(), apiId, &status);
HAL_WriteCANPacket(static_cast<HAL_CANHandle>(handle), apiId, &message,
&status);
return status;
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANPacketRepeatingNoThrow
* Signature: (I[BII)I
* Signature: (II[BIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeatingNoThrow
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId,
jint timeoutMs)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags, jint repeatMs)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
JSpan<const jbyte> arr{env, data};
HAL_CANMessage message;
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return PARAMETER_OUT_OF_RANGE;
}
int32_t status = 0;
HAL_WriteCANPacketRepeating(halHandle,
reinterpret_cast<const uint8_t*>(arr.data()),
arr.size(), apiId, timeoutMs, &status);
HAL_WriteCANPacketRepeating(static_cast<HAL_CANHandle>(handle), apiId,
&message, repeatMs, &status);
return status;
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: writeCANRTRFrameNoThrow
* Signature: (III)I
* Signature: (II[BII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_writeCANRTRFrameNoThrow
(JNIEnv* env, jclass, jint handle, jint length, jint apiId)
(JNIEnv* env, jclass, jint handle, jint apiId, jbyteArray data,
jint dataLength, jint flags)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
HAL_CANMessage message;
if (data == nullptr) {
// We will allow RTR frames to have a null data array
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
return PARAMETER_OUT_OF_RANGE;
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
ThrowIllegalArgumentException(env,
"Non FD frame has max length of 8 bytes");
return PARAMETER_OUT_OF_RANGE;
}
std::memset(&message, 0, sizeof(message));
message.flags = flags;
message.dataSize = dataLength;
} else if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return PARAMETER_OUT_OF_RANGE;
}
int32_t status = 0;
HAL_WriteCANRTRFrame(halHandle, static_cast<int32_t>(length), apiId, &status);
HAL_WriteCANRTRFrame(static_cast<HAL_CANHandle>(handle), apiId, &message,
&status);
return status;
}
@@ -190,29 +265,28 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketNew
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
uint8_t dataTemp[8];
int32_t dataLength = 0;
uint64_t timestamp = 0;
HAL_CANReceiveMessage message;
std::memset(&message, 0, sizeof(message));
int32_t status = 0;
HAL_ReadCANPacketNew(halHandle, apiId, dataTemp, &dataLength, &timestamp,
&status);
HAL_ReadCANPacketNew(halHandle, apiId, &message, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (!CheckStatus(env, status)) {
return false;
}
if (dataLength > 8) {
dataLength = 8;
}
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
jbyteArray toSetArray =
SetCANReceiveMessageObject(env, data, message.message.dataSize,
message.message.flags, message.timeStamp);
auto javaLen = env->GetArrayLength(toSetArray);
if (javaLen < dataLength) {
dataLength = javaLen;
if (javaLen < message.message.dataSize) {
ThrowIllegalArgumentException(env,
"Message buffer not long enough for message");
return false;
}
env->SetByteArrayRegion(toSetArray, 0, dataLength,
reinterpret_cast<jbyte*>(dataTemp));
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
reinterpret_cast<jbyte*>(message.message.data));
return true;
}
@@ -226,48 +300,45 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketLatest
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
uint8_t dataTemp[8];
int32_t dataLength = 0;
uint64_t timestamp = 0;
HAL_CANReceiveMessage message;
std::memset(&message, 0, sizeof(message));
int32_t status = 0;
HAL_ReadCANPacketLatest(halHandle, apiId, dataTemp, &dataLength, &timestamp,
&status);
HAL_ReadCANPacketLatest(halHandle, apiId, &message, &status);
if (status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
}
if (!CheckStatus(env, status)) {
return false;
}
if (dataLength > 8) {
dataLength = 8;
}
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
jbyteArray toSetArray =
SetCANReceiveMessageObject(env, data, message.message.dataSize,
message.message.flags, message.timeStamp);
auto javaLen = env->GetArrayLength(toSetArray);
if (javaLen < dataLength) {
dataLength = javaLen;
if (javaLen < message.message.dataSize) {
ThrowIllegalArgumentException(env,
"Message buffer not long enough for message");
return false;
}
env->SetByteArrayRegion(toSetArray, 0, dataLength,
reinterpret_cast<jbyte*>(dataTemp));
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
reinterpret_cast<jbyte*>(message.message.data));
return true;
}
/*
* Class: edu_wpi_first_hal_CANAPIJNI
* Method: readCANPacketTimeout
* Signature: (IIILjava/lang/Object;)Z
* Signature: (IILjava/lang/Object;I)Z
*/
JNIEXPORT jboolean JNICALL
Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketTimeout
(JNIEnv* env, jclass, jint handle, jint apiId, jint timeoutMs, jobject data)
(JNIEnv* env, jclass, jint handle, jint apiId, jobject data, jint timeoutMs)
{
auto halHandle = static_cast<HAL_CANHandle>(handle);
uint8_t dataTemp[8];
int32_t dataLength = 0;
uint64_t timestamp = 0;
HAL_CANReceiveMessage message;
std::memset(&message, 0, sizeof(message));
int32_t status = 0;
HAL_ReadCANPacketTimeout(halHandle, apiId, dataTemp, &dataLength, &timestamp,
timeoutMs, &status);
HAL_ReadCANPacketTimeout(halHandle, apiId, &message, timeoutMs, &status);
if (status == HAL_CAN_TIMEOUT ||
status == HAL_ERR_CANSessionMux_MessageNotFound) {
return false;
@@ -275,17 +346,18 @@ Java_edu_wpi_first_hal_CANAPIJNI_readCANPacketTimeout
if (!CheckStatus(env, status)) {
return false;
}
if (dataLength > 8) {
dataLength = 8;
}
jbyteArray toSetArray = SetCANDataObject(env, data, dataLength, timestamp);
jbyteArray toSetArray =
SetCANReceiveMessageObject(env, data, message.message.dataSize,
message.message.flags, message.timeStamp);
auto javaLen = env->GetArrayLength(toSetArray);
if (javaLen < dataLength) {
dataLength = javaLen;
if (javaLen < message.message.dataSize) {
ThrowIllegalArgumentException(env,
"Message buffer not long enough for message");
return false;
}
env->SetByteArrayRegion(toSetArray, 0, dataLength,
reinterpret_cast<jbyte*>(dataTemp));
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
reinterpret_cast<jbyte*>(message.message.data));
return true;
}
} // extern "C"

View File

@@ -11,68 +11,98 @@
#include "HALUtil.h"
#include "edu_wpi_first_hal_can_CANJNI.h"
#include "hal/CAN.h"
#include "hal/Errors.h"
using namespace hal;
using namespace wpi::java;
extern "C" {
/*
* Class: edu_wpi_first_hal_can_CANJNI
* Method: FRCNetCommCANSessionMuxSendMessage
* Signature: (I[BI)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxSendMessage
(JNIEnv* env, jclass, jint messageID, jbyteArray data, jint periodMs)
{
JSpan<const jbyte> dataArray{env, data};
static bool PackCANMessage(JNIEnv* env, jbyteArray data, jint dataLength,
jint flags, HAL_CANMessage* message) {
if (data == nullptr) {
ThrowNullPointerException(env, "data array cannot be null");
return false;
}
const uint8_t* dataBuffer =
reinterpret_cast<const uint8_t*>(dataArray.data());
uint8_t dataSize = dataArray.size();
auto arrLen = env->GetArrayLength(data);
if (arrLen < dataLength) {
ThrowIllegalArgumentException(env, "array length less than data length");
return false;
}
int32_t status = 0;
HAL_CAN_SendMessage(messageID, dataBuffer, dataSize, periodMs, &status);
CheckCANStatus(env, status, messageID);
if ((flags & HAL_CAN_FD_DATALENGTH) && dataLength > 64) {
ThrowIllegalArgumentException(env, "FD frame has max length of 64 bytes");
return false;
} else if (!(flags & HAL_CAN_FD_DATALENGTH) && dataLength > 8) {
ThrowIllegalArgumentException(env,
"Non FD frame has max length of 8 bytes");
return false;
}
std::memset(message, 0, sizeof(*message));
message->dataSize = dataLength;
message->flags = flags;
JSpan<const jbyte> arr{env, data, static_cast<size_t>(dataLength)};
std::memcpy(message->data, arr.data(), dataLength);
return true;
}
/*
* Class: edu_wpi_first_hal_can_CANJNI
* Method: FRCNetCommCANSessionMuxReceiveMessage
* Signature: (Ljava/lang/Object;ILjava/lang/Object;)[B
* Method: sendMessage
* Signature: (II[BIII)I
*/
JNIEXPORT jbyteArray JNICALL
Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxReceiveMessage
(JNIEnv* env, jclass, jobject messageID, jint messageIDMask,
jobject timeStamp)
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_can_CANJNI_sendMessage
(JNIEnv* env, jclass, jint busId, jint messageId, jbyteArray data,
jint dataLength, jint flags, jint periodMs)
{
uint32_t* messageIDPtr =
reinterpret_cast<uint32_t*>(env->GetDirectBufferAddress(messageID));
uint32_t* timeStampPtr =
reinterpret_cast<uint32_t*>(env->GetDirectBufferAddress(timeStamp));
uint8_t dataSize = 0;
uint8_t buffer[8];
HAL_CANMessage message;
if (!PackCANMessage(env, data, dataLength, flags, &message)) {
return PARAMETER_OUT_OF_RANGE;
}
int32_t status = 0;
HAL_CAN_ReceiveMessage(messageIDPtr, messageIDMask, buffer, &dataSize,
timeStampPtr, &status);
HAL_CAN_SendMessage(busId, messageId, &message, periodMs, &status);
return status;
}
if (!CheckCANStatus(env, status, *messageIDPtr)) {
return nullptr;
/*
* Class: edu_wpi_first_hal_can_CANJNI
* Method: receiveMessage
* Signature: (IILjava/lang/Object;)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_can_CANJNI_receiveMessage
(JNIEnv* env, jclass, jint busId, jint messageId, jobject data)
{
HAL_CANReceiveMessage message;
std::memset(&message, 0, sizeof(message));
int32_t status = 0;
HAL_CAN_ReceiveMessage(busId, messageId, &message, &status);
jbyteArray toSetArray =
SetCANReceiveMessageObject(env, data, message.message.dataSize,
message.message.flags, message.timeStamp);
auto javaLen = env->GetArrayLength(toSetArray);
if (javaLen < message.message.dataSize) {
ThrowIllegalArgumentException(env,
"Message buffer not long enough for message");
return status;
}
return MakeJByteArray(env, {buffer, static_cast<size_t>(dataSize)});
env->SetByteArrayRegion(toSetArray, 0, message.message.dataSize,
reinterpret_cast<jbyte*>(message.message.data));
return status;
}
/*
* Class: edu_wpi_first_hal_can_CANJNI
* Method: getCANStatus
* Signature: (Ljava/lang/Object;)V
* Signature: (ILjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
(JNIEnv* env, jclass, jobject canStatus)
(JNIEnv* env, jclass, jint busId, jobject canStatus)
{
float percentBusUtilization = 0;
uint32_t busOffCount = 0;
@@ -80,8 +110,9 @@ Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
uint32_t receiveErrorCount = 0;
uint32_t transmitErrorCount = 0;
int32_t status = 0;
HAL_CAN_GetCANStatus(&percentBusUtilization, &busOffCount, &txFullCount,
&receiveErrorCount, &transmitErrorCount, &status);
HAL_CAN_GetCANStatus(busId, &percentBusUtilization, &busOffCount,
&txFullCount, &receiveErrorCount, &transmitErrorCount,
&status);
if (!CheckStatus(env, status)) {
return;
@@ -94,17 +125,18 @@ Java_edu_wpi_first_hal_can_CANJNI_getCANStatus
/*
* Class: edu_wpi_first_hal_can_CANJNI
* Method: openCANStreamSession
* Signature: (III)I
* Signature: (IIII)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_can_CANJNI_openCANStreamSession
(JNIEnv* env, jclass, jint messageID, jint messageIDMask, jint maxMessages)
(JNIEnv* env, jclass, jint busId, jint messageId, jint messageIDMask,
jint maxMessages)
{
uint32_t handle = 0;
int32_t status = 0;
HAL_CAN_OpenStreamSession(&handle, static_cast<uint32_t>(messageID),
static_cast<uint32_t>(messageIDMask),
static_cast<uint32_t>(maxMessages), &status);
HAL_CANStreamHandle handle =
HAL_CAN_OpenStreamSession(busId, static_cast<uint32_t>(messageId),
static_cast<uint32_t>(messageIDMask),
static_cast<uint32_t>(maxMessages), &status);
if (!CheckStatus(env, status)) {
return static_cast<jint>(0);
@@ -182,14 +214,17 @@ Java_edu_wpi_first_hal_can_CANJNI_readCANStreamSession
}
}
JLocal<jbyteArray> toSetArray{
env, SetCANStreamObject(env, elem, msg->dataSize, msg->messageID,
msg->timeStamp)};
env, SetCANStreamObject(env, elem, msg->message.message.dataSize,
msg->messageId, msg->message.timeStamp)};
auto javaLen = env->GetArrayLength(toSetArray);
if (javaLen < msg->dataSize) {
msg->dataSize = javaLen;
if (javaLen < msg->message.message.dataSize) {
ThrowIllegalArgumentException(
env, "Message buffer not long enough for message");
return PARAMETER_OUT_OF_RANGE;
}
env->SetByteArrayRegion(toSetArray, 0, msg->dataSize,
reinterpret_cast<jbyte*>(msg->data));
env->SetByteArrayRegion(
toSetArray, 0, msg->message.message.dataSize,
reinterpret_cast<jbyte*>(msg->message.message.data));
}
if (status == HAL_ERR_CANSessionMux_SessionOverrun) {

View File

@@ -19,15 +19,15 @@ extern "C" {
/*
* Class: edu_wpi_first_hal_CTREPCMJNI
* Method: initialize
* Signature: (I)I
* Signature: (II)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_CTREPCMJNI_initialize
(JNIEnv* env, jclass, jint module)
(JNIEnv* env, jclass, jint busId, jint module)
{
int32_t status = 0;
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
auto handle = HAL_InitializeCTREPCM(module, stack.c_str(), &status);
auto handle = HAL_InitializeCTREPCM(busId, module, stack.c_str(), &status);
CheckStatusForceThrow(env, status);
return handle;
}

View File

@@ -41,17 +41,13 @@ static JException illegalArgExCls;
static JException boundaryExCls;
static JException allocationExCls;
static JException halHandleExCls;
static JException canInvalidBufferExCls;
static JException canMessageNotFoundExCls;
static JException canMessageNotAllowedExCls;
static JException canNotInitializedExCls;
static JException uncleanStatusExCls;
static JException nullPointerEx;
static JClass powerDistributionVersionCls;
static JClass pwmConfigDataResultCls;
static JClass canStatusCls;
static JClass matchInfoDataCls;
static JClass canDataCls;
static JClass canReceiveMessageCls;
static JClass canStreamMessageCls;
static JClass halValueCls;
static JClass revPHVersionCls;
@@ -63,8 +59,8 @@ static const JClassInit classes[] = {
{"edu/wpi/first/hal/PWMConfigDataResult", &pwmConfigDataResultCls},
{"edu/wpi/first/hal/can/CANStatus", &canStatusCls},
{"edu/wpi/first/hal/MatchInfoData", &matchInfoDataCls},
{"edu/wpi/first/hal/CANData", &canDataCls},
{"edu/wpi/first/hal/CANStreamMessage", &canStreamMessageCls},
{"edu/wpi/first/hal/can/CANReceiveMessage", &canReceiveMessageCls},
{"edu/wpi/first/hal/can/CANStreamMessage", &canStreamMessageCls},
{"edu/wpi/first/hal/HALValue", &halValueCls},
{"edu/wpi/first/hal/REVPHVersion", &revPHVersionCls},
{"edu/wpi/first/hal/can/CANStreamOverflowException",
@@ -75,13 +71,6 @@ static const JExceptionInit exceptions[] = {
{"edu/wpi/first/hal/util/BoundaryException", &boundaryExCls},
{"edu/wpi/first/hal/util/AllocationException", &allocationExCls},
{"edu/wpi/first/hal/util/HalHandleException", &halHandleExCls},
{"edu/wpi/first/hal/can/CANInvalidBufferException", &canInvalidBufferExCls},
{"edu/wpi/first/hal/can/CANMessageNotFoundException",
&canMessageNotFoundExCls},
{"edu/wpi/first/hal/can/CANMessageNotAllowedException",
&canMessageNotAllowedExCls},
{"edu/wpi/first/hal/can/CANNotInitializedException",
&canNotInitializedExCls},
{"edu/wpi/first/hal/util/UncleanStatusException", &uncleanStatusExCls},
{"java/lang/NullPointerException", &nullPointerEx}};
@@ -152,64 +141,6 @@ void ThrowError(JNIEnv* env, int32_t status, int32_t minRange, int32_t maxRange,
env, fmt::format(" Code: {}. {}", status, lastError).c_str(), status);
}
void ReportCANError(JNIEnv* env, int32_t status, int message_id) {
if (status >= 0) {
return;
}
switch (status) {
case kRioStatusSuccess:
// Everything is ok... don't throw.
break;
case HAL_ERR_CANSessionMux_InvalidBuffer:
case kRIOStatusBufferInvalidSize: {
static jmethodID invalidBufConstruct = nullptr;
if (!invalidBufConstruct) {
invalidBufConstruct =
env->GetMethodID(canInvalidBufferExCls, "<init>", "()V");
}
jobject exception =
env->NewObject(canInvalidBufferExCls, invalidBufConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
case HAL_ERR_CANSessionMux_MessageNotFound:
case kRIOStatusOperationTimedOut: {
static jmethodID messageNotFoundConstruct = nullptr;
if (!messageNotFoundConstruct) {
messageNotFoundConstruct =
env->GetMethodID(canMessageNotFoundExCls, "<init>", "()V");
}
jobject exception =
env->NewObject(canMessageNotFoundExCls, messageNotFoundConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
case HAL_ERR_CANSessionMux_NotAllowed:
case kRIOStatusFeatureNotSupported: {
canMessageNotAllowedExCls.Throw(
env, fmt::format("MessageID = {}", message_id).c_str());
break;
}
case HAL_ERR_CANSessionMux_NotInitialized:
case kRIOStatusResourceNotInitialized: {
static jmethodID notInitConstruct = nullptr;
if (!notInitConstruct) {
notInitConstruct =
env->GetMethodID(canNotInitializedExCls, "<init>", "()V");
}
jobject exception =
env->NewObject(canNotInitializedExCls, notInitConstruct);
env->Throw(static_cast<jthrowable>(exception));
break;
}
default: {
uncleanStatusExCls.Throw(
env, fmt::format("Fatal status code detected: {}", status).c_str());
break;
}
}
}
void ThrowNullPointerException(JNIEnv* env, std::string_view msg) {
nullPointerEx.Throw(env, msg);
}
@@ -302,24 +233,27 @@ void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
static_cast<jint>(matchInfo.matchType));
}
jbyteArray SetCANDataObject(JNIEnv* env, jobject canData, int32_t length,
uint64_t timestamp) {
static jmethodID func = env->GetMethodID(canDataCls, "setData", "(IJ)[B");
jbyteArray SetCANReceiveMessageObject(JNIEnv* env, jobject canData,
int32_t length, int32_t flags,
uint64_t timestamp) {
static jmethodID func =
env->GetMethodID(canReceiveMessageCls, "setReceiveData", "(IIJ)[B");
jbyteArray retVal = static_cast<jbyteArray>(env->CallObjectMethod(
canData, func, static_cast<jint>(length), static_cast<jlong>(timestamp)));
canData, func, static_cast<jint>(length), static_cast<jint>(flags),
static_cast<jlong>(timestamp)));
return retVal;
}
jbyteArray SetCANStreamObject(JNIEnv* env, jobject canStreamData,
int32_t length, uint32_t messageID,
int32_t length, uint32_t messageId,
uint64_t timestamp) {
static jmethodID func =
env->GetMethodID(canStreamMessageCls, "setStreamData", "(IIJ)[B");
jbyteArray retVal = static_cast<jbyteArray>(env->CallObjectMethod(
canStreamData, func, static_cast<jint>(length),
static_cast<jint>(messageID), static_cast<jlong>(timestamp)));
static_cast<jint>(messageId), static_cast<jlong>(timestamp)));
return retVal;
}

View File

@@ -42,15 +42,6 @@ inline bool CheckStatusForceThrow(JNIEnv* env, int32_t status) {
return status == 0;
}
void ReportCANError(JNIEnv* env, int32_t status, int32_t message_id);
inline bool CheckCANStatus(JNIEnv* env, int32_t status, int32_t message_id) {
if (status != 0) {
ReportCANError(env, status, message_id);
}
return status == 0;
}
void ThrowNullPointerException(JNIEnv* env, std::string_view msg);
void ThrowCANStreamOverflowException(JNIEnv* env, jobjectArray messages,
jint length);
@@ -75,11 +66,12 @@ void SetCanStatusObject(JNIEnv* env, jobject canStatus,
void SetMatchInfoObject(JNIEnv* env, jobject matchStatus,
const HAL_MatchInfo& matchInfo);
jbyteArray SetCANDataObject(JNIEnv* env, jobject canData, int32_t length,
uint64_t timestamp);
jbyteArray SetCANReceiveMessageObject(JNIEnv* env, jobject canData,
int32_t length, int32_t flags,
uint64_t timestamp);
jbyteArray SetCANStreamObject(JNIEnv* env, jobject canStreamData,
int32_t length, uint32_t messageID,
int32_t length, uint32_t messageId,
uint64_t timestamp);
jobject CreateHALValue(JNIEnv* env, const HAL_Value& value);

View File

@@ -13,6 +13,19 @@
using namespace hal;
extern "C" {
/*
* Class: edu_wpi_first_hal_PortsJNI
* Method: getNumCanBuses
* Signature: ()I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_PortsJNI_getNumCanBuses
(JNIEnv*, jclass)
{
jint value = HAL_GetNumCanBuses();
return value;
}
/*
* Class: edu_wpi_first_hal_PortsJNI
* Method: getNumAnalogInputs

View File

@@ -27,17 +27,17 @@ extern "C" {
/*
* Class: edu_wpi_first_hal_PowerDistributionJNI
* Method: initialize
* Signature: (II)I
* Signature: (III)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_PowerDistributionJNI_initialize
(JNIEnv* env, jclass, jint module, jint type)
(JNIEnv* env, jclass, jint busId, jint module, jint type)
{
int32_t status = 0;
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
auto handle = HAL_InitializePowerDistribution(
module, static_cast<HAL_PowerDistributionType>(type), stack.c_str(),
&status);
busId, module, static_cast<HAL_PowerDistributionType>(type),
stack.c_str(), &status);
CheckStatusForceThrow(env, status);
return static_cast<jint>(handle);
}

View File

@@ -32,15 +32,15 @@ extern "C" {
/*
* Class: edu_wpi_first_hal_REVPHJNI
* Method: initialize
* Signature: (I)I
* Signature: (II)I
*/
JNIEXPORT jint JNICALL
Java_edu_wpi_first_hal_REVPHJNI_initialize
(JNIEnv* env, jclass, jint module)
(JNIEnv* env, jclass, jint busId, jint module)
{
int32_t status = 0;
auto stack = wpi::java::GetJavaStackTrace(env, "edu.wpi.first");
auto handle = HAL_InitializeREVPH(module, stack.c_str(), &status);
auto handle = HAL_InitializeREVPH(busId, module, stack.c_str(), &status);
CheckStatusForceThrow(env, status);
return handle;
}