diff --git a/hal/include/HAL/Errors.h b/hal/include/HAL/Errors.h index 5794bbaadd..8b73156718 100644 --- a/hal/include/HAL/Errors.h +++ b/hal/include/HAL/Errors.h @@ -83,6 +83,10 @@ #define HAL_HANDLE_ERROR_MESSAGE \ "HAL: A handle parameter was passed incorrectly" +#define HAL_SERIAL_PORT_NOT_FOUND -1123 +#define HAL_SERIAL_PORT_NOT_FOUND_MESSAGE \ + "HAL: The specified serial port device was not found"; + #define VI_ERROR_SYSTEM_ERROR_MESSAGE "HAL - VISA: System Error"; #define VI_ERROR_INV_OBJECT_MESSAGE "HAL - VISA: Invalid Object" #define VI_ERROR_RSRC_LOCKED_MESSAGE "HAL - VISA: Resource Locked" diff --git a/hal/include/HAL/SerialPort.h b/hal/include/HAL/SerialPort.h index 33039925e1..5ae64a41f0 100644 --- a/hal/include/HAL/SerialPort.h +++ b/hal/include/HAL/SerialPort.h @@ -9,31 +9,42 @@ #include +enum HAL_SerialPort : int32_t { + HAL_SerialPort_Onboard = 0, + HAL_SerialPort_MXP = 1, + HAL_SerialPort_USB1 = 2, + HAL_SerialPort_USB2 = 3 +}; + #ifdef __cplusplus extern "C" { #endif -void HAL_InitializeSerialPort(int32_t port, int32_t* status); -void HAL_SetSerialBaudRate(int32_t port, int32_t baud, int32_t* status); -void HAL_SetSerialDataBits(int32_t port, int32_t bits, int32_t* status); -void HAL_SetSerialParity(int32_t port, int32_t parity, int32_t* status); -void HAL_SetSerialStopBits(int32_t port, int32_t stopBits, int32_t* status); -void HAL_SetSerialWriteMode(int32_t port, int32_t mode, int32_t* status); -void HAL_SetSerialFlowControl(int32_t port, int32_t flow, int32_t* status); -void HAL_SetSerialTimeout(int32_t port, double timeout, int32_t* status); -void HAL_EnableSerialTermination(int32_t port, char terminator, +void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status); +void HAL_SetSerialBaudRate(HAL_SerialPort port, int32_t baud, int32_t* status); +void HAL_SetSerialDataBits(HAL_SerialPort port, int32_t bits, int32_t* status); +void HAL_SetSerialParity(HAL_SerialPort port, int32_t parity, int32_t* status); +void HAL_SetSerialStopBits(HAL_SerialPort port, int32_t stopBits, + int32_t* status); +void HAL_SetSerialWriteMode(HAL_SerialPort port, int32_t mode, int32_t* status); +void HAL_SetSerialFlowControl(HAL_SerialPort port, int32_t flow, + int32_t* status); +void HAL_SetSerialTimeout(HAL_SerialPort port, double timeout, int32_t* status); +void HAL_EnableSerialTermination(HAL_SerialPort port, char terminator, int32_t* status); -void HAL_DisableSerialTermination(int32_t port, int32_t* status); -void HAL_SetSerialReadBufferSize(int32_t port, int32_t size, int32_t* status); -void HAL_SetSerialWriteBufferSize(int32_t port, int32_t size, int32_t* status); -int32_t HAL_GetSerialBytesReceived(int32_t port, int32_t* status); -int32_t HAL_ReadSerial(int32_t port, char* buffer, int32_t count, +void HAL_DisableSerialTermination(HAL_SerialPort port, int32_t* status); +void HAL_SetSerialReadBufferSize(HAL_SerialPort port, int32_t size, + int32_t* status); +void HAL_SetSerialWriteBufferSize(HAL_SerialPort port, int32_t size, + int32_t* status); +int32_t HAL_GetSerialBytesReceived(HAL_SerialPort port, int32_t* status); +int32_t HAL_ReadSerial(HAL_SerialPort port, char* buffer, int32_t count, int32_t* status); -int32_t HAL_WriteSerial(int32_t port, const char* buffer, int32_t count, +int32_t HAL_WriteSerial(HAL_SerialPort port, const char* buffer, int32_t count, int32_t* status); -void HAL_FlushSerial(int32_t port, int32_t* status); -void HAL_ClearSerial(int32_t port, int32_t* status); -void HAL_CloseSerial(int32_t port, int32_t* status); +void HAL_FlushSerial(HAL_SerialPort port, int32_t* status); +void HAL_ClearSerial(HAL_SerialPort port, int32_t* status); +void HAL_CloseSerial(HAL_SerialPort port, int32_t* status); #ifdef __cplusplus } #endif diff --git a/hal/lib/athena/HAL.cpp b/hal/lib/athena/HAL.cpp index 83b7b0fd2e..92a6015400 100644 --- a/hal/lib/athena/HAL.cpp +++ b/hal/lib/athena/HAL.cpp @@ -161,6 +161,8 @@ const char* HAL_GetErrorMessage(int32_t code) { return VI_ERROR_INV_PARAMETER_MESSAGE; case HAL_PWM_SCALE_ERROR: return HAL_PWM_SCALE_ERROR_MESSAGE; + case HAL_SERIAL_PORT_NOT_FOUND: + return HAL_SERIAL_PORT_NOT_FOUND_MESSAGE; default: return "Unknown error status"; } diff --git a/hal/lib/athena/SerialHelper.cpp b/hal/lib/athena/SerialHelper.cpp new file mode 100644 index 0000000000..79c6a8c16d --- /dev/null +++ b/hal/lib/athena/SerialHelper.cpp @@ -0,0 +1,263 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2016. 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. */ +/*----------------------------------------------------------------------------*/ + +#include "SerialHelper.h" + +#include +#include +#include +#include + +#include "HAL/Errors.h" +#include "llvm/StringRef.h" +#include "visa/visa.h" + +constexpr const char* OnboardResource = "ASRL1::INSTR"; +constexpr const char* MxpResource = "ASRL2::INSTR"; + +namespace hal { +std::string SerialHelper::m_usbNames[2]{"", ""}; + +priority_mutex SerialHelper::m_nameMutex; + +SerialHelper::SerialHelper(int32_t resourceHandle) + : m_resourceHandle(resourceHandle) {} + +std::string SerialHelper::GetSerialPortName(HAL_SerialPort port, + int32_t* status) { + if (port == HAL_SerialPort::HAL_SerialPort_Onboard) { + return OnboardResource; + } else if (port == HAL_SerialPort::HAL_SerialPort_MXP) { + return MxpResource; + } + + QueryHubPaths(status); + + // If paths are empty or status error, return error + if (*status != 0 || m_visaResource.empty() || m_osResource.empty() || + m_sortedHubPath.empty()) { + *status = HAL_SERIAL_PORT_NOT_FOUND; + return ""; + } + + // Hold lock whenever we're using the names array + std::lock_guard lock(m_nameMutex); + + std::string portString = m_usbNames[port - 2]; + + llvm::SmallVector indices; + + // If port has not been assigned, find the one to assign + if (portString.empty()) { + for (size_t i = 0; i < 2; i++) { + // Remove all used ports + auto idx = std::find(m_sortedHubPath.begin(), m_sortedHubPath.end(), + m_usbNames[i]); + if (idx != m_sortedHubPath.end()) { + // found + m_sortedHubPath.erase(idx); + } + if (m_usbNames[i] == "") { + indices.push_back(i); + } + } + + int32_t idx = -1; + for (size_t i = 0; i < indices.size(); i++) { + if (indices[i] == port - 2) { + idx = i; + break; + } + } + + if (idx == -1) { + *status = HAL_SERIAL_PORT_NOT_FOUND; + return ""; + } + + if (idx >= static_cast(m_sortedHubPath.size())) { + *status = HAL_SERIAL_PORT_NOT_FOUND; + return ""; + } + + portString = m_sortedHubPath[idx].str(); + m_usbNames[port - 2] = portString; + } + + int visaIndex = -1; + + for (size_t i = 0; i < m_sortedHubPath.size(); i++) { + if (m_sortedHubPath[i].equals(portString)) { + visaIndex = i; + break; + } + } + + if (visaIndex == -1) { + *status = HAL_SERIAL_PORT_NOT_FOUND; + return ""; + // Error + } else { + return m_visaResource[visaIndex].str(); + } +} + +void SerialHelper::SortHubPathVector() { + m_sortedHubPath.clear(); + m_sortedHubPath = m_unsortedHubPath; + std::sort(m_sortedHubPath.begin(), m_sortedHubPath.end(), + [](llvm::SmallVectorImpl& lhs, + llvm::SmallVectorImpl& rhs) -> int { + llvm::StringRef lhsRef(lhs.begin(), lhs.size()); + llvm::StringRef rhsRef(rhs.begin(), rhs.size()); + return lhsRef.compare(rhsRef); + }); +} + +void SerialHelper::CoiteratedSort( + llvm::SmallVectorImpl>& vec) { + llvm::SmallVector, 4> sortedVec; + for (auto& str : m_sortedHubPath) { + for (size_t i = 0; i < m_unsortedHubPath.size(); i++) { + if (llvm::StringRef{m_unsortedHubPath[i].begin(), + m_unsortedHubPath[i].size()} + .equals(llvm::StringRef{str.begin(), str.size()})) { + sortedVec.push_back(vec[i]); + break; + } + } + } + vec = sortedVec; +} + +void SerialHelper::QueryHubPaths(int32_t* status) { + // VISA resource matching string + const char* str = "?*"; + // Items needed for VISA + ViUInt32 retCnt = 0; + ViFindList viList = 0; + ViChar desc[VI_FIND_BUFLEN]; + *status = viFindRsrc(m_resourceHandle, const_cast(str), &viList, + &retCnt, desc); + + if (*status < 0) { + // Handle the bad status elsewhere + // Note let positive statii (warnings) continue + return; + } + // Status might be positive, so reset it to 0 + *status = 0; + + // Storage buffers for Visa calls and system exec calls + char osName[256]; + char execBuffer[128]; + + // Regex to filter out the device name + // Will be index 1 on success + std::regex devMatch("[^\\s]+\\s+\\(\\/dev\\/([^\\s]+)\\)"); + + // Loop through all returned VISA objects. + // Increment the internal VISA ptr every loop + for (size_t i = 0; i < retCnt; i++, viFindNext(viList, desc)) { + // Ignore any matches to the 2 onboard ports + if (std::strcmp(OnboardResource, desc) == 0 || + std::strcmp(MxpResource, desc) == 0) { + continue; + } + + // Open the resource, grab its interface name, and close it. + ViSession vSession; + *status = viOpen(m_resourceHandle, desc, VI_NULL, VI_NULL, &vSession); + if (*status < 0) return; + *status = 0; + + *status = viGetAttribute(vSession, VI_ATTR_INTF_INST_NAME, &osName); + // Ignore an error here, as we want to close the session on an error + // Use a seperate close variable so we can check + ViStatus closeStatus = viClose(vSession); + if (*status < 0) return; + if (closeStatus < 0) return; + *status = 0; + + std::smatch regexMatcher; + auto regexVal = + std::regex_match(std::string(osName), regexMatcher, devMatch); + + if (regexVal > 0 && regexMatcher.size() > 1) { + // Store our match string, as output was ocassionally being corrupted + // before being accessed + auto matchString = regexMatcher[1].str(); + + // Run find using pipe to get a list of system accessors + llvm::SmallString<128> val( + "sh -c \"find /sys/devices/soc0 | grep amba | grep usb | grep "); + val += matchString; + val += "\""; + + // Pipe code found on StackOverflow + // http://stackoverflow.com/questions/478898/how-to-execute-a-command-and-get-output-of-command-within-c-using-posix + + // Using std::string because this is guarenteed to be large + std::string output = ""; + + std::shared_ptr pipe(popen(val.c_str(), "r"), pclose); + // Just check the next item on a pipe failure + if (!pipe) continue; + while (!feof(pipe.get())) { + if (std::fgets(execBuffer, 128, pipe.get()) != 0) output += execBuffer; + } + + if (!output.empty()) { + llvm::SmallVector pathSplitVec; + // Split output by line, grab first line, and split it into + // individual directories + llvm::StringRef{output}.split('\n').first.split(pathSplitVec, '/', -1, + false); + + // Find each individual item index + + const char* usb1 = "usb1"; + const char* tty = "tty"; + + int findusb = -1; + int findtty = -1; + int findregex = -1; + for (size_t i = 0; i < pathSplitVec.size(); i++) { + if (findusb == -1 && pathSplitVec[i].equals(usb1)) { + findusb = i; + } + if (findtty == -1 && pathSplitVec[i].equals(tty)) { + findtty = i; + } + if (findregex == -1 && pathSplitVec[i].equals(matchString)) { + findregex = i; + } + } + + // Get the index for our device + int hubIndex = findtty; + if (findtty == -1) hubIndex = findregex; + + int devStart = findusb + 1; + + if (hubIndex < devStart) continue; + + // Add our devices to our list + m_unsortedHubPath.push_back( + llvm::StringRef{pathSplitVec[hubIndex - 2]}); + m_visaResource.push_back(llvm::StringRef{desc}); + m_osResource.push_back(llvm::StringRef{matchString}); + } + } + } + + SortHubPathVector(); + + CoiteratedSort(m_visaResource); + CoiteratedSort(m_osResource); +} +} // namespace hal diff --git a/hal/lib/athena/SerialHelper.h b/hal/lib/athena/SerialHelper.h new file mode 100644 index 0000000000..17bb2407ef --- /dev/null +++ b/hal/lib/athena/SerialHelper.h @@ -0,0 +1,44 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2016. 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. */ +/*----------------------------------------------------------------------------*/ + +#pragma once + +#include + +#include + +#include "HAL/SerialPort.h" +#include "HAL/cpp/priority_mutex.h" +#include "llvm/SmallString.h" +#include "llvm/SmallVector.h" + +namespace hal { +class SerialHelper { + public: + explicit SerialHelper(int32_t resourceHandle); + + std::string GetSerialPortName(HAL_SerialPort port, int32_t* status); + + private: + void SortHubPathVector(); + void CoiteratedSort(llvm::SmallVectorImpl>& vec); + void QueryHubPaths(int32_t* status); + + // Vectors to hold data before sorting. + // Note we will most likely have at max 2 instances, and the longest string + // is around 12, so these should never touch the heap; + llvm::SmallVector, 4> m_visaResource; + llvm::SmallVector, 4> m_osResource; + llvm::SmallVector, 4> m_unsortedHubPath; + llvm::SmallVector, 4> m_sortedHubPath; + + int32_t m_resourceHandle; + + static priority_mutex m_nameMutex; + static std::string m_usbNames[2]; +}; +} // namespace hal diff --git a/hal/lib/athena/SerialPort.cpp b/hal/lib/athena/SerialPort.cpp index 21c1b19d0f..47b3f993af 100644 --- a/hal/lib/athena/SerialPort.cpp +++ b/hal/lib/athena/SerialPort.cpp @@ -7,109 +7,118 @@ #include "HAL/SerialPort.h" +#include + +#include "SerialHelper.h" #include "visa/visa.h" -static int32_t m_resourceManagerHandle; -static int32_t m_portHandle[2]; +static int32_t resourceManagerHandle; +static HAL_SerialPort portHandles[4]; extern "C" { -void HAL_InitializeSerialPort(int32_t port, int32_t* status) { - char const* portName; +void HAL_InitializeSerialPort(HAL_SerialPort port, int32_t* status) { + std::string portName; - if (m_resourceManagerHandle == 0) - viOpenDefaultRM(reinterpret_cast(&m_resourceManagerHandle)); + if (resourceManagerHandle == 0) + viOpenDefaultRM(reinterpret_cast(&resourceManagerHandle)); - if (port == 0) - portName = "ASRL1::INSTR"; - else if (port == 1) - portName = "ASRL2::INSTR"; - else - portName = "ASRL3::INSTR"; + hal::SerialHelper serialHelper(resourceManagerHandle); - *status = - viOpen(m_resourceManagerHandle, const_cast(portName), VI_NULL, - VI_NULL, reinterpret_cast(&m_portHandle[port])); + portName = serialHelper.GetSerialPortName(port, status); + + if (*status < 0) { + return; + } + + *status = viOpen(resourceManagerHandle, const_cast(portName.c_str()), + VI_NULL, VI_NULL, + reinterpret_cast(&portHandles[port])); if (*status > 0) *status = 0; } -void HAL_SetSerialBaudRate(int32_t port, int32_t baud, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_BAUD, baud); +void HAL_SetSerialBaudRate(HAL_SerialPort port, int32_t baud, int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_BAUD, baud); if (*status > 0) *status = 0; } -void HAL_SetSerialDataBits(int32_t port, int32_t bits, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_DATA_BITS, bits); +void HAL_SetSerialDataBits(HAL_SerialPort port, int32_t bits, int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_DATA_BITS, bits); if (*status > 0) *status = 0; } -void HAL_SetSerialParity(int32_t port, int32_t parity, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_PARITY, parity); +void HAL_SetSerialParity(HAL_SerialPort port, int32_t parity, int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_PARITY, parity); if (*status > 0) *status = 0; } -void HAL_SetSerialStopBits(int32_t port, int32_t stopBits, int32_t* status) { - *status = - viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_STOP_BITS, stopBits); +void HAL_SetSerialStopBits(HAL_SerialPort port, int32_t stopBits, + int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_STOP_BITS, stopBits); if (*status > 0) *status = 0; } -void HAL_SetSerialWriteMode(int32_t port, int32_t mode, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_WR_BUF_OPER_MODE, mode); +void HAL_SetSerialWriteMode(HAL_SerialPort port, int32_t mode, + int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_WR_BUF_OPER_MODE, mode); if (*status > 0) *status = 0; } -void HAL_SetSerialFlowControl(int32_t port, int32_t flow, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_FLOW_CNTRL, flow); +void HAL_SetSerialFlowControl(HAL_SerialPort port, int32_t flow, + int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_FLOW_CNTRL, flow); if (*status > 0) *status = 0; } -void HAL_SetSerialTimeout(int32_t port, double timeout, int32_t* status) { - *status = viSetAttribute(m_portHandle[port], VI_ATTR_TMO_VALUE, +void HAL_SetSerialTimeout(HAL_SerialPort port, double timeout, + int32_t* status) { + *status = viSetAttribute(portHandles[port], VI_ATTR_TMO_VALUE, static_cast(timeout * 1e3)); if (*status > 0) *status = 0; } -void HAL_EnableSerialTermination(int32_t port, char terminator, +void HAL_EnableSerialTermination(HAL_SerialPort port, char terminator, int32_t* status) { - viSetAttribute(m_portHandle[port], VI_ATTR_TERMCHAR_EN, VI_TRUE); - viSetAttribute(m_portHandle[port], VI_ATTR_TERMCHAR, terminator); - *status = viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_END_IN, + viSetAttribute(portHandles[port], VI_ATTR_TERMCHAR_EN, VI_TRUE); + viSetAttribute(portHandles[port], VI_ATTR_TERMCHAR, terminator); + *status = viSetAttribute(portHandles[port], VI_ATTR_ASRL_END_IN, VI_ASRL_END_TERMCHAR); if (*status > 0) *status = 0; } -void HAL_DisableSerialTermination(int32_t port, int32_t* status) { - viSetAttribute(m_portHandle[port], VI_ATTR_TERMCHAR_EN, VI_FALSE); +void HAL_DisableSerialTermination(HAL_SerialPort port, int32_t* status) { + viSetAttribute(portHandles[port], VI_ATTR_TERMCHAR_EN, VI_FALSE); *status = - viSetAttribute(m_portHandle[port], VI_ATTR_ASRL_END_IN, VI_ASRL_END_NONE); + viSetAttribute(portHandles[port], VI_ATTR_ASRL_END_IN, VI_ASRL_END_NONE); if (*status > 0) *status = 0; } -void HAL_SetSerialReadBufferSize(int32_t port, int32_t size, int32_t* status) { - *status = viSetBuf(m_portHandle[port], VI_READ_BUF, size); +void HAL_SetSerialReadBufferSize(HAL_SerialPort port, int32_t size, + int32_t* status) { + *status = viSetBuf(portHandles[port], VI_READ_BUF, size); if (*status > 0) *status = 0; } -void HAL_SetSerialWriteBufferSize(int32_t port, int32_t size, int32_t* status) { - *status = viSetBuf(m_portHandle[port], VI_WRITE_BUF, size); +void HAL_SetSerialWriteBufferSize(HAL_SerialPort port, int32_t size, + int32_t* status) { + *status = viSetBuf(portHandles[port], VI_WRITE_BUF, size); if (*status > 0) *status = 0; } -int32_t HAL_GetSerialBytesReceived(int32_t port, int32_t* status) { +int32_t HAL_GetSerialBytesReceived(HAL_SerialPort port, int32_t* status) { int32_t bytes = 0; - *status = viGetAttribute(m_portHandle[port], VI_ATTR_ASRL_AVAIL_NUM, &bytes); + *status = viGetAttribute(portHandles[port], VI_ATTR_ASRL_AVAIL_NUM, &bytes); if (*status > 0) *status = 0; return bytes; } -int32_t HAL_ReadSerial(int32_t port, char* buffer, int32_t count, +int32_t HAL_ReadSerial(HAL_SerialPort port, char* buffer, int32_t count, int32_t* status) { uint32_t retCount = 0; *status = - viRead(m_portHandle[port], (ViPBuf)buffer, count, (ViPUInt32)&retCount); + viRead(portHandles[port], (ViPBuf)buffer, count, (ViPUInt32)&retCount); if (*status == VI_ERROR_IO || *status == VI_ERROR_ASRL_OVERRUN || *status == VI_ERROR_ASRL_FRAMING || *status == VI_ERROR_ASRL_PARITY) { @@ -121,29 +130,29 @@ int32_t HAL_ReadSerial(int32_t port, char* buffer, int32_t count, return static_cast(retCount); } -int32_t HAL_WriteSerial(int32_t port, const char* buffer, int32_t count, +int32_t HAL_WriteSerial(HAL_SerialPort port, const char* buffer, int32_t count, int32_t* status) { uint32_t retCount = 0; *status = - viWrite(m_portHandle[port], (ViPBuf)buffer, count, (ViPUInt32)&retCount); + viWrite(portHandles[port], (ViPBuf)buffer, count, (ViPUInt32)&retCount); if (*status > 0) *status = 0; return static_cast(retCount); } -void HAL_FlushSerial(int32_t port, int32_t* status) { - *status = viFlush(m_portHandle[port], VI_WRITE_BUF); +void HAL_FlushSerial(HAL_SerialPort port, int32_t* status) { + *status = viFlush(portHandles[port], VI_WRITE_BUF); if (*status > 0) *status = 0; } -void HAL_ClearSerial(int32_t port, int32_t* status) { - *status = viClear(m_portHandle[port]); +void HAL_ClearSerial(HAL_SerialPort port, int32_t* status) { + *status = viClear(portHandles[port]); if (*status > 0) *status = 0; } -void HAL_CloseSerial(int32_t port, int32_t* status) { - *status = viClose(m_portHandle[port]); +void HAL_CloseSerial(HAL_SerialPort port, int32_t* status) { + *status = viClose(portHandles[port]); if (*status > 0) *status = 0; } diff --git a/wpilibc/athena/include/SerialPort.h b/wpilibc/athena/include/SerialPort.h index c9ddf969d0..f2e140d455 100644 --- a/wpilibc/athena/include/SerialPort.h +++ b/wpilibc/athena/include/SerialPort.h @@ -46,7 +46,7 @@ class SerialPort : public ErrorBase { kFlowControl_DtrDsr = 4 }; enum WriteBufferMode { kFlushOnAccess = 1, kFlushWhenFull = 2 }; - enum Port { kOnboard = 0, kMXP = 1, kUSB = 2 }; + enum Port { kOnboard = 0, kMXP = 1, kUSB = 2, kUSB1 = 2, kUSB2 = 3 }; SerialPort(int baudRate, Port port = kOnboard, int dataBits = 8, Parity parity = kParity_None, StopBits stopBits = kStopBits_One); diff --git a/wpilibc/athena/src/SerialPort.cpp b/wpilibc/athena/src/SerialPort.cpp index 4c892d0ebd..2b2937eb8a 100644 --- a/wpilibc/athena/src/SerialPort.cpp +++ b/wpilibc/athena/src/SerialPort.cpp @@ -32,15 +32,17 @@ SerialPort::SerialPort(int baudRate, Port port, int dataBits, m_port = port; - HAL_InitializeSerialPort(port, &status); + HAL_InitializeSerialPort(static_cast(port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); - HAL_SetSerialBaudRate(port, baudRate, &status); + // Don't continue if initialization failed + if (status < 0) return; + HAL_SetSerialBaudRate(static_cast(port), baudRate, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); - HAL_SetSerialDataBits(port, dataBits, &status); + HAL_SetSerialDataBits(static_cast(port), dataBits, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); - HAL_SetSerialParity(port, parity, &status); + HAL_SetSerialParity(static_cast(port), parity, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); - HAL_SetSerialStopBits(port, stopBits, &status); + HAL_SetSerialStopBits(static_cast(port), stopBits, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); // Set the default timeout to 5 seconds. @@ -63,7 +65,7 @@ SerialPort::SerialPort(int baudRate, Port port, int dataBits, */ SerialPort::~SerialPort() { int32_t status = 0; - HAL_CloseSerial(m_port, &status); + HAL_CloseSerial(static_cast(m_port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -74,7 +76,8 @@ SerialPort::~SerialPort() { */ void SerialPort::SetFlowControl(SerialPort::FlowControl flowControl) { int32_t status = 0; - HAL_SetSerialFlowControl(m_port, flowControl, &status); + HAL_SetSerialFlowControl(static_cast(m_port), flowControl, + &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -89,7 +92,8 @@ void SerialPort::SetFlowControl(SerialPort::FlowControl flowControl) { */ void SerialPort::EnableTermination(char terminator) { int32_t status = 0; - HAL_EnableSerialTermination(m_port, terminator, &status); + HAL_EnableSerialTermination(static_cast(m_port), terminator, + &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -98,7 +102,7 @@ void SerialPort::EnableTermination(char terminator) { */ void SerialPort::DisableTermination() { int32_t status = 0; - HAL_DisableSerialTermination(m_port, &status); + HAL_DisableSerialTermination(static_cast(m_port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -109,7 +113,8 @@ void SerialPort::DisableTermination() { */ int SerialPort::GetBytesReceived() { int32_t status = 0; - int retVal = HAL_GetSerialBytesReceived(m_port, &status); + int retVal = + HAL_GetSerialBytesReceived(static_cast(m_port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); return retVal; } @@ -123,7 +128,8 @@ int SerialPort::GetBytesReceived() { */ int SerialPort::Read(char* buffer, int count) { int32_t status = 0; - int retVal = HAL_ReadSerial(m_port, buffer, count, &status); + int retVal = HAL_ReadSerial(static_cast(m_port), buffer, + count, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); return retVal; } @@ -137,7 +143,8 @@ int SerialPort::Read(char* buffer, int count) { */ int SerialPort::Write(const std::string& buffer, int count) { int32_t status = 0; - int retVal = HAL_WriteSerial(m_port, buffer.c_str(), count, &status); + int retVal = HAL_WriteSerial(static_cast(m_port), + buffer.c_str(), count, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); return retVal; } @@ -152,7 +159,7 @@ int SerialPort::Write(const std::string& buffer, int count) { */ void SerialPort::SetTimeout(double timeout) { int32_t status = 0; - HAL_SetSerialTimeout(m_port, timeout, &status); + HAL_SetSerialTimeout(static_cast(m_port), timeout, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -170,7 +177,8 @@ void SerialPort::SetTimeout(double timeout) { */ void SerialPort::SetReadBufferSize(int size) { int32_t status = 0; - HAL_SetSerialReadBufferSize(m_port, size, &status); + HAL_SetSerialReadBufferSize(static_cast(m_port), size, + &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -184,7 +192,8 @@ void SerialPort::SetReadBufferSize(int size) { */ void SerialPort::SetWriteBufferSize(int size) { int32_t status = 0; - HAL_SetSerialWriteBufferSize(m_port, size, &status); + HAL_SetSerialWriteBufferSize(static_cast(m_port), size, + &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -201,7 +210,7 @@ void SerialPort::SetWriteBufferSize(int size) { */ void SerialPort::SetWriteBufferMode(SerialPort::WriteBufferMode mode) { int32_t status = 0; - HAL_SetSerialWriteMode(m_port, mode, &status); + HAL_SetSerialWriteMode(static_cast(m_port), mode, &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -213,7 +222,7 @@ void SerialPort::SetWriteBufferMode(SerialPort::WriteBufferMode mode) { */ void SerialPort::Flush() { int32_t status = 0; - HAL_FlushSerial(m_port, &status); + HAL_FlushSerial(static_cast(m_port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } @@ -224,6 +233,6 @@ void SerialPort::Flush() { */ void SerialPort::Reset() { int32_t status = 0; - HAL_ClearSerial(m_port, &status); + HAL_ClearSerial(static_cast(m_port), &status); wpi_setErrorWithContext(status, HAL_GetErrorMessage(status)); } diff --git a/wpilibj/src/athena/cpp/lib/SerialPortJNI.cpp b/wpilibj/src/athena/cpp/lib/SerialPortJNI.cpp index d857b3fec1..093868b9bc 100644 --- a/wpilibj/src/athena/cpp/lib/SerialPortJNI.cpp +++ b/wpilibj/src/athena/cpp/lib/SerialPortJNI.cpp @@ -38,7 +38,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialInitializePort( SERIALJNI_LOG(logDEBUG) << "Calling Serial Initialize"; SERIALJNI_LOG(logDEBUG) << "Port = " << (jint)port; int32_t status = 0; - HAL_InitializeSerialPort(port, &status); + HAL_InitializeSerialPort(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatusForceThrow(env, status); } @@ -54,7 +54,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetBaudRate( SERIALJNI_LOG(logDEBUG) << "Setting Serial Baud Rate"; SERIALJNI_LOG(logDEBUG) << "Baud: " << rate; int32_t status = 0; - HAL_SetSerialBaudRate(port, rate, &status); + HAL_SetSerialBaudRate(static_cast(port), rate, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -70,7 +70,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetDataBits( SERIALJNI_LOG(logDEBUG) << "Setting Serial Data Bits"; SERIALJNI_LOG(logDEBUG) << "Data Bits: " << bits; int32_t status = 0; - HAL_SetSerialDataBits(port, bits, &status); + HAL_SetSerialDataBits(static_cast(port), bits, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -86,7 +86,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetParity( SERIALJNI_LOG(logDEBUG) << "Setting Serial Parity"; SERIALJNI_LOG(logDEBUG) << "Parity: " << parity; int32_t status = 0; - HAL_SetSerialParity(port, parity, &status); + HAL_SetSerialParity(static_cast(port), parity, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -102,7 +102,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetStopBits( SERIALJNI_LOG(logDEBUG) << "Setting Serial Stop Bits"; SERIALJNI_LOG(logDEBUG) << "Stop Bits: " << bits; int32_t status = 0; - HAL_SetSerialStopBits(port, bits, &status); + HAL_SetSerialStopBits(static_cast(port), bits, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -118,7 +118,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetWriteMode( SERIALJNI_LOG(logDEBUG) << "Setting Serial Write Mode"; SERIALJNI_LOG(logDEBUG) << "Write mode: " << mode; int32_t status = 0; - HAL_SetSerialWriteMode(port, mode, &status); + HAL_SetSerialWriteMode(static_cast(port), mode, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -134,7 +134,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetFlowControl( SERIALJNI_LOG(logDEBUG) << "Setting Serial Flow Control"; SERIALJNI_LOG(logDEBUG) << "Flow Control: " << flow; int32_t status = 0; - HAL_SetSerialFlowControl(port, flow, &status); + HAL_SetSerialFlowControl(static_cast(port), flow, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -150,7 +150,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetTimeout( SERIALJNI_LOG(logDEBUG) << "Setting Serial Timeout"; SERIALJNI_LOG(logDEBUG) << "Timeout: " << timeout; int32_t status = 0; - HAL_SetSerialTimeout(port, timeout, &status); + HAL_SetSerialTimeout(static_cast(port), timeout, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -166,7 +166,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialEnableTermination( SERIALJNI_LOG(logDEBUG) << "Setting Serial Enable Termination"; SERIALJNI_LOG(logDEBUG) << "Terminator: " << terminator; int32_t status = 0; - HAL_EnableSerialTermination(port, terminator, &status); + HAL_EnableSerialTermination(static_cast(port), terminator, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -181,7 +181,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialDisableTermination( JNIEnv* env, jclass, jbyte port) { SERIALJNI_LOG(logDEBUG) << "Setting Serial Disable termination"; int32_t status = 0; - HAL_DisableSerialTermination(port, &status); + HAL_DisableSerialTermination(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -197,7 +197,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetReadBufferSize( SERIALJNI_LOG(logDEBUG) << "Setting Serial Read Buffer Size"; SERIALJNI_LOG(logDEBUG) << "Size: " << size; int32_t status = 0; - HAL_SetSerialReadBufferSize(port, size, &status); + HAL_SetSerialReadBufferSize(static_cast(port), size, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -213,7 +213,7 @@ Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialSetWriteBufferSize( SERIALJNI_LOG(logDEBUG) << "Setting Serial Write Buffer Size"; SERIALJNI_LOG(logDEBUG) << "Size: " << size; int32_t status = 0; - HAL_SetSerialWriteBufferSize(port, size, &status); + HAL_SetSerialWriteBufferSize(static_cast(port), size, &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -228,7 +228,7 @@ 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 = HAL_GetSerialBytesReceived(port, &status); + jint retVal = HAL_GetSerialBytesReceived(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); return retVal; @@ -245,7 +245,8 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialRead( jbyte* dataReceivedPtr = nullptr; dataReceivedPtr = (jbyte*)env->GetDirectBufferAddress(dataReceived); int32_t status = 0; - jint retVal = HAL_ReadSerial(port, reinterpret_cast(dataReceivedPtr), size, &status); + jint retVal = HAL_ReadSerial(static_cast(port), reinterpret_cast(dataReceivedPtr), + size, &status); SERIALJNI_LOG(logDEBUG) << "ReturnValue = " << retVal; SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); @@ -265,7 +266,8 @@ JNIEXPORT jint JNICALL Java_edu_wpi_first_wpilibj_hal_SerialPortJNI_serialWrite( dataToSendPtr = (jbyte*)env->GetDirectBufferAddress(dataToSend); } int32_t status = 0; - jint retVal = HAL_WriteSerial(port, reinterpret_cast(dataToSendPtr), size, &status); + jint retVal = HAL_WriteSerial(static_cast(port), reinterpret_cast(dataToSendPtr), + size, &status); SERIALJNI_LOG(logDEBUG) << "ReturnValue = " << retVal; SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); @@ -281,7 +283,7 @@ 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; - HAL_FlushSerial(port, &status); + HAL_FlushSerial(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -295,7 +297,7 @@ 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; - HAL_ClearSerial(port, &status); + HAL_ClearSerial(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } @@ -309,7 +311,7 @@ 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; - HAL_CloseSerial(port, &status); + HAL_CloseSerial(static_cast(port), &status); SERIALJNI_LOG(logDEBUG) << "Status = " << status; CheckStatus(env, status); } diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SerialPort.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SerialPort.java index dd3ce9de51..a7885690a1 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SerialPort.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/SerialPort.java @@ -30,7 +30,7 @@ public class SerialPort { private byte m_port; public enum Port { - kOnboard(0), kMXP(1), kUSB(2); + kOnboard(0), kMXP(1), kUSB(2), kUSB1(2), kUSB2(3); @SuppressWarnings("MemberName") public int value;