diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..316140f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Dependabot updates for GitHub Actions + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a361f2f..50cb9e2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,96 +1,203 @@ name: Build on: - push: - branches: - - 'main' - pull_request: - branches: - - '*' + [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: false defaults: run: shell: bash jobs: + # Use native runners to build for Windows, Linux x86-64, and macOS; use WPI provided Docker images to build for Linux ARM32 and ARM64 platforms build: - timeout-minutes: 15 strategy: fail-fast: false matrix: include: - os: windows-latest - container: '' - name: windows64 - name: "build-${{ matrix.name }}" + name: Win64 + build-options: "" + platform-type: windowsx86-64 + - os: ubuntu-latest + name: Linux64 + platform-type: linuxx86-64 + build-options: "" + - os: macos-latest + name: macOS + platform-type: osxuniversal + build-options: "" + - container: wpilib/aarch64-cross-ubuntu:bullseye-22.04 + os: ubuntu-latest + name: LinuxARM64 + build-options: "-Ponlylinuxarm64" + platform-type: linuxarm64 + arch: arm64 + - container: wpilib/raspbian-cross-ubuntu:bullseye-22.04 + os: ubuntu-latest + name: LinuxARM32 + build-options: "-Ponlylinuxarm32" + platform-type: linuxarm32 + arch: arm32 + name: "Build - ${{ matrix.name }}" runs-on: ${{ matrix.os }} container: ${{ matrix.container }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ github.sha }} - name: Setup Java - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 11 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Build run: | ./gradlew outputVersions publish ${{ matrix.build-options }} -PreleaseMode - - name: Download WPILib HAL artifacts and headers, gather all needed headers + - name: Download WPILib HAL artifacts and headers for ${{ matrix.platform-type }} run : | halVersion=$(cat wpiHalVersion.txt) + + sharedHalPlatformUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/hal/hal-cpp/"$halVersion"/hal-cpp-"$halVersion"-${{ matrix.platform-type }}.zip + sharedUtilPlatformUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/wpiutil/wpiutil-cpp/"$halVersion"/wpiutil-cpp-"$halVersion"-${{ matrix.platform-type }}.zip + curl -L -o sharedHalPlatform.zip "$sharedHalPlatformUrl" + curl -L -o sharedUtilPlatform.zip "$sharedUtilPlatformUrl" - # Download WPILib artifacts from Artifactory - halWindowsUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/hal/hal-cpp/"$halVersion"/hal-cpp-"$halVersion"-windowsx86-64.zip + staticHalPlatformUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/hal/hal-cpp/"$halVersion"/hal-cpp-"$halVersion"-${{ matrix.platform-type }}static.zip + staticUtilPlatformUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/wpiutil/wpiutil-cpp/"$halVersion"/wpiutil-cpp-"$halVersion"-${{ matrix.platform-type }}static.zip + curl -L -o staticHalPlatform.zip "$staticHalPlatformUrl" + curl -L -o staticUtilPlatform.zip "$staticUtilPlatformUrl" + + - name: Unzip WPILib HAL artifacts and headers + run: | + unzip sharedHalPlatform.zip -d sharedHalPlatform + unzip sharedUtilPlatform.zip -d sharedUtilPlatform + unzip staticHalPlatform.zip -d staticHalPlatform + unzip staticUtilPlatform.zip -d staticUtilPlatform + mkdir -p CANBridge-artifacts/static + mkdir -p CANBridge-artifacts/shared + + # Put release files together in one directory based on platform + - name: Create Artifact + run: | + mkdir -p CANBridge-artifacts + if [[ "${{ matrix.platform-type }}" == "windowsx86-64" ]]; then + cp build/libs/cANBridge/shared/windowsx86-64/release/CANBridge.dll CANBridge-artifacts/shared/ + cp build/libs/cANBridge/shared/windowsx86-64/release/CANBridge.lib CANBridge-artifacts/shared/ + cp sharedHalPlatform/windows/x86-64/shared/wpiHal.dll CANBridge-artifacts/shared/ + cp sharedHalPlatform/windows/x86-64/shared/wpiHal.lib CANBridge-artifacts/shared/ + cp sharedUtilPlatform/windows/x86-64/shared/wpiutil.dll CANBridge-artifacts/shared/ + cp sharedUtilPlatform/windows/x86-64/shared/wpiutil.lib CANBridge-artifacts/shared/ + + cp build/libs/cANBridge/static/windowsx86-64/release/CANBridge.lib CANBridge-artifacts/static/ + cp staticHalPlatform/windows/x86-64/static/wpiHal.lib CANBridge-artifacts/static/ + cp staticUtilPlatform/windows/x86-64/static/wpiutil.lib CANBridge-artifacts/static/ + elif [[ "${{ matrix.platform-type }}" == "linuxx86-64" ]]; then + cp build/libs/cANBridge/shared/linuxx86-64/release/libCANBridge.so CANBridge-artifacts/shared/ + cp sharedHalPlatform/linux/x86-64/shared/libwpiHal.so CANBridge-artifacts/shared/ + cp sharedUtilPlatform/linux/x86-64/shared/libwpiutil.so CANBridge-artifacts/shared/ + + cp build/libs/cANBridge/static/linuxx86-64/release/libCANBridge.a CANBridge-artifacts/static/ + cp staticHalPlatform/linux/x86-64/static/libwpiHal.a CANBridge-artifacts/static/ + cp staticUtilPlatform/linux/x86-64/static/libwpiutil.a CANBridge-artifacts/static/ + elif [[ "${{ matrix.platform-type }}" == "osxuniversal" ]]; then + cp build/libs/cANBridge/shared/osxuniversal/release/libCANBridge.dylib CANBridge-artifacts/shared/ + cp sharedHalPlatform/osx/universal/shared/libwpiHal.dylib CANBridge-artifacts/shared/ + cp sharedUtilPlatform/osx/universal/shared/libwpiutil.dylib CANBridge-artifacts/shared + + cp build/libs/cANBridge/static/osxuniversal/release/libCANBridge.a CANBridge-artifacts/static/ + cp staticHalPlatform/osx/universal/static/libwpiHal.a CANBridge-artifacts/static/ + cp staticUtilPlatform/osx/universal/static/libwpiutil.a CANBridge-artifacts/static/ + elif [[ "${{ matrix.platform-type }}" == "linuxarm32" || "${{ matrix.platform-type }}" == "linuxarm64" ]]; then + cp build/libs/cANBridge/shared/release/libCANBridge.so CANBridge-artifacts/shared/libCANBridge.so + cp sharedHalPlatform/linux/${{ matrix.arch }}/shared/libwpiHal.so CANBridge-artifacts/shared/libwpiHal.so + cp sharedUtilPlatform/linux/${{ matrix.arch }}/shared/libwpiutil.so CANBridge-artifacts/shared/libwpiutil.so + + cp build/libs/cANBridge/static/release/libCANBridge.a CANBridge-artifacts/static/libCANBridge.a + cp staticHalPlatform/linux/${{ matrix.arch }}/static/libwpiHal.a CANBridge-artifacts/static/libwpiHal.a + cp staticUtilPlatform/linux/${{ matrix.arch }}/static/libwpiutil.a CANBridge-artifacts/static/libwpiutil.a + fi + + # Upload build artifact + - name: Upload build artifact + uses: actions/upload-artifact@v4 + with: + name: CANBridge-${{ matrix.platform-type }}-${{ github.sha}} + path: CANBridge-artifacts/ + + # Upload combined headers for WPILib from HAL and WPIUtil + wpi-headers: + runs-on: ubuntu-latest + name: "WPILib Headers" + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} + - name: Download WPILib HAL artifacts and headers + run : | + halVersion=$(cat wpiHalVersion.txt) + halHeadersUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/hal/hal-cpp/"$halVersion"/hal-cpp-"$halVersion"-headers.zip - utilWindowsUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/wpiutil/wpiutil-cpp/"$halVersion"/wpiutil-cpp-"$halVersion"-windowsx86-64.zip utilHeadersUrl=https://frcmaven.wpi.edu/artifactory/release/edu/wpi/first/wpiutil/wpiutil-cpp/"$halVersion"/wpiutil-cpp-"$halVersion"-headers.zip - curl -L -o halWindows.zip "$halWindowsUrl" + curl -L -o halHeaders.zip "$halHeadersUrl" - curl -L -o utilWindows.zip "$utilWindowsUrl" curl -L -o utilHeaders.zip "$utilHeadersUrl" - unzip halWindows.zip -d halWindows + + - name: Unzip WPILib HAL artifacts and headers + run: | unzip halHeaders.zip -d halHeaders - unzip utilWindows.zip -d utilWindows unzip utilHeaders.zip -d utilHeaders - # Gather all of the the needed headers + - name: Gather all needed headers + run: | mkdir headers-for-artifact cp -r halHeaders/hal headers-for-artifact cp -r utilHeaders/wpi headers-for-artifact cp -r src/main/native/include/* headers-for-artifact - # Zip the needed headers and put them in the appropriate location for artifact upload - mkdir -p CANBridge-artifacts - 7z a CANBridge-artifacts/headers.zip ./headers-for-artifact/* - - # Put release files together in one directory - - name: Create Artifact - run: | - mkdir -p CANBridge-artifacts - cp build/libs/cANBridge/static/windowsx86-64/release/CANBridge.lib CANBridge-artifacts/CANBridge-static.lib - cp build/libs/cANBridge/shared/windowsx86-64/release/CANBridge.dll CANBridge-artifacts/CANBridge.dll - cp build/libs/cANBridge/shared/windowsx86-64/release/CANBridge.lib CANBridge-artifacts/CANBridge.lib - cp halWindows/windows/x86-64/shared/wpiHal.dll CANBridge-artifacts/wpiHal.dll - cp halWindows/windows/x86-64/shared/wpiHal.lib CANBridge-artifacts/wpiHal.lib - cp utilWindows/windows/x86-64/shared/wpiutil.dll CANBridge-artifacts/wpiutil.dll - cp utilWindows/windows/x86-64/shared/wpiutil.lib CANBridge-artifacts/wpiutil.lib - # Upload build artifact - name: Upload build artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: CANBridge-${{ github.sha }} - path: CANBridge-artifacts/ + path: headers-for-artifact + name: headers + + # Upload version file, used for versioning + version: + runs-on: ubuntu-latest + name: "Version" + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.sha }} + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 11 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build + run: | + ./gradlew outputVersions -PreleaseMode - # Upload version.txt - - name: Upload version artifact - uses: actions/upload-artifact@v3 + - name: Upload build artifact + uses: actions/upload-artifact@v4 with: name: version path: build/allOutputs/version.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0c00949..2c11dfc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,33 +3,39 @@ name: Create release on: push: tags: - - 'v*' + - 'v**' + +permissions: + contents: write + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: false defaults: run: shell: bash jobs: - check-versions: + # Checks previous build workflow and gets the version from publish.gradle + check-build: + name: Check build and publish versions runs-on: ubuntu-latest outputs: TAG_NAME: ${{ env.TAG_NAME }} VERSION: ${{ steps.get_version.outputs.version }} steps: - - name: Wait for build to finish - uses: lewagon/wait-on-check-action@v1.3.1 + - name: Wait for build workflow to finish + uses: lewagon/wait-on-check-action@v1.3.4 with: ref: ${{ github.ref }} - check-name: 'build-windows64' + check-regexp: 'Build|WPILib Headers|Version' repo-token: ${{ secrets.GITHUB_TOKEN }} wait-interval: 10 - - name: Get tag name - run: | - echo "TAG_NAME=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV # Download artifacts from build workflow - name: Download workflow artifacts - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v6 with: workflow: build.yml commit: ${{ github.sha }} @@ -37,38 +43,46 @@ jobs: # Get publish.gradle version - name: Get publish.gradle version - id: get_version + id: get-version run: | echo "version=$(cat version/version.txt)" >> $GITHUB_OUTPUT echo "expectedTagName=v$(cat version/version.txt)" >> $GITHUB_OUTPUT - # Check publish.gradle version - - name: publish.gradle version check FAILED - if: ${{ steps.get_version.outputs.expectedTagName != env.TAG_NAME }} + # Check if the publish.gradle version matches the tag name + - name: Check version run: | - echo Tag name: ${{ env.TAG_NAME }} - echo publish.gradle version: ${{ steps.get_version.outputs.version }} - exit 1 + if [[ "${{ steps.get-version.outputs.expectedTagName }}" != "${{ env.TAG_NAME }}" ]]; then + echo "Version mismatch: ${{ steps.get-version.outputs.expectedTagName }} != ${{ env.TAG_NAME }}" + exit 1 + fi + # Creates a release draft with the artifacts from the build workflow prepare-release: + name: Prepare release runs-on: ubuntu-latest - needs: check-versions + needs: check-build steps: # Download API, docs, and version.txt - name: Download workflow artifacts - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v6 with: workflow: build.yml commit: ${{ github.sha }} path: '.' + skip_unpack: true + + # This step is to check what files are downloaded and how they are structured, as well as binary sizes for releases + - name: List files + run: | + ls -Rlh # Create new release draft - name: Create release - id: create_release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - VERSION=${{ needs.check-versions.outputs.version }} - TAG=v$VERSION - ls --recursive -l - gh release create $TAG CANBridge-${{ github.sha }}/* --repo $GITHUB_REPOSITORY --draft --title "Version $VERSION" + uses: softprops/action-gh-release@v2 + with: + draft: true + generate_release_notes: true + tag_name: v${{ steps.get-version.outputs.version }} + name: Version ${{ steps.get-version.outputs.version }} + files: | + **/** \ No newline at end of file diff --git a/config.gradle b/config.gradle index 7a59e9d..1c8fcb6 100644 --- a/config.gradle +++ b/config.gradle @@ -8,7 +8,7 @@ nativeUtils { // When updating WPILib, be sure to also update wpiHalVersion.txt wpiVersion = "2023.+" niLibVersion = "2023.3.0" - googleTestVersion = "1.11.0-3" + googleTestVersion = "1.11.0-4" } } } diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/native/cpp/CANBridge.cpp b/src/main/native/cpp/CANBridge.cpp index 68a9f26..029cec7 100644 --- a/src/main/native/cpp/CANBridge.cpp +++ b/src/main/native/cpp/CANBridge.cpp @@ -43,8 +43,6 @@ #include "rev/Drivers/CandleWinUSB/CandleWinUSBDriver.h" #endif -#include "rev/Drivers/SerialPort/SerialDriver.h" - #include #include @@ -61,7 +59,6 @@ static const std::vector CANDriverList = { #ifdef _WIN32 new rev::usb::CandleWinUSBDriver(), #endif - new rev::usb::SerialDriver() }; static std::vector, rev::usb::CANBridge_CANFilter>> CANDeviceList = {}; diff --git a/src/main/native/cpp/Drivers/Serial/SerialDevice.cpp b/src/main/native/cpp/Drivers/Serial/SerialDevice.cpp deleted file mode 100644 index a72d19d..0000000 --- a/src/main/native/cpp/Drivers/Serial/SerialDevice.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef _WIN32 - -#include "rev/Drivers/SerialPort/SerialDevice.h" - -#include //TODO: Remove -#include -#include - -#include -#include - -#include "serial/serial.h" - -namespace rev { -namespace usb { - -SerialDevice::SerialDevice(std::string port) : - m_thread(port) -{ - m_descriptor = port; - m_name = "SPARK MAX"; - m_thread.Start(); -} - -SerialDevice::~SerialDevice() -{ - m_thread.Stop(); -} - -std::string SerialDevice::GetName() const -{ - return m_name; -} - - -std::string SerialDevice::GetDescriptor() const -{ - return m_descriptor; -} - -int SerialDevice::GetId() const -{ - return 0; -} - -int SerialDevice::GetNumberOfErrors() -{ - return m_thread.GetNumberOfErrors(); -} - -CANStatus SerialDevice::SendCANMessage(const CANMessage& msg, int periodMs) -{ - m_thread.EnqueueMessage(msg, periodMs); - return m_thread.GetLastThreadError(); -} - -CANStatus SerialDevice::ReceiveCANMessage(std::shared_ptr& msg, uint32_t messageID, uint32_t messageMask) -{ - CANStatus status = CANStatus::kTimeout; - - // parse through the keys, find the messges the match, and return it - // The first in the message id, then the messages - std::map> messages; - m_thread.ReceiveMessage(messages); - std::shared_ptr mostRecent; - for (auto& m : messages) { - if ( - CANBridge_ProcessMask({m.second->GetMessageId(), 0}, m.first) - && CANBridge_ProcessMask({messageID, messageMask}, m.first) - && (!mostRecent || m.second->GetTimestampUs() > mostRecent->GetTimestampUs()) - ) { - mostRecent = m.second; - status = CANStatus::kOk; - } - } - - if (status == CANStatus::kOk) { - msg = mostRecent; - status = m_thread.GetLastThreadError(); - } else { - status = CANStatus::kError; - } - - - return status; -} - -CANStatus SerialDevice::OpenStreamSession(uint32_t* sessionHandle, CANBridge_CANFilter filter, uint32_t maxSize) -{ - // Register the stream with the correct buffer size - CANStatus stat = CANStatus::kOk; - m_thread.OpenStream(sessionHandle, filter, maxSize, &stat); - return m_thread.GetLastThreadError(); -} -CANStatus SerialDevice::CloseStreamSession(uint32_t sessionHandle) -{ - m_thread.CloseStream(sessionHandle); - return m_thread.GetLastThreadError(); -} -CANStatus SerialDevice::ReadStreamSession(uint32_t sessionHandle, struct HAL_CANStreamMessage* msgs, uint32_t messagesToRead, uint32_t* messagesRead) -{ - m_thread.ReadStream(sessionHandle, msgs, messagesToRead, messagesRead); - return m_thread.GetLastThreadError(); -} - -CANStatus SerialDevice::GetCANDetailStatus(float* percentBusUtilization, uint32_t* busOff, uint32_t* txFull, uint32_t* receiveErr, uint32_t* transmitErr) -{ - rev::usb::CANStatusDetails details; - m_thread.GetCANStatus(&details); - *busOff = details.busOffCount; - *txFull = details.txFullCount; - *receiveErr = details.receiveErrCount; - *transmitErr = details.transmitErrCount; - *percentBusUtilization = 0.0; // todo how to get this properly - - return m_thread.GetLastThreadError(); -} - -CANStatus SerialDevice::GetCANDetailStatus(float* percentBusUtilization, uint32_t* busOff, uint32_t* txFull, uint32_t* receiveErr, uint32_t* transmitErr, uint32_t* lastErrorTime) { - return GetCANDetailStatus(percentBusUtilization, busOff, txFull, receiveErr, transmitErr); -} - -bool SerialDevice::IsConnected() -{ - return true; -} - -bool SerialDevice::CopyReceivedMessagesMap(std::map>& receivedMessagesMap) -{ - return m_thread.ReceiveMessage(receivedMessagesMap); -} - - -} // namespace usb -} // namespace rev - -#else -typedef int __ISOWarning__CLEAR_; -#endif // _WIN32 diff --git a/src/main/native/cpp/Drivers/Serial/SerialDriver.cpp b/src/main/native/cpp/Drivers/Serial/SerialDriver.cpp deleted file mode 100644 index 1be761f..0000000 --- a/src/main/native/cpp/Drivers/Serial/SerialDriver.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifdef _WIN32 - -#include "rev/Drivers/SerialPort/SerialDriver.h" -#include "rev/Drivers/SerialPort/SerialDevice.h" -#include "rev/CANBridgeUtils.h" - -#include "serial/serial.h" - -#include -#include -#include -#include - -namespace rev { -namespace usb { - -static const std::string SparkMax_HardwareId = "USB\\VID_0483&PID_5740&REV_0200"; - -std::vector SerialDriver::GetDevices() -{ - // Search driver layer for devices - std::vector retval; - - std::vector found = serial::list_ports(); - for (auto& dev : found) { - if (parse_serial_com_port(dev.port) != -1 && dev.hardware_id.compare(SparkMax_HardwareId) == 0) { - std::string name("SPARK MAX"); - retval.push_back({dev.port, name, this->GetName()}); - } - } - - return retval; -} - -std::unique_ptr SerialDriver::CreateDeviceFromDescriptor(const char* descriptor) -{ - // Search driver layer for devices - std::vector found = serial::list_ports(); - for (auto& dev : found) { - if (dev.port == std::string(descriptor)) { - try { - return std::make_unique(dev.port); - } catch(...) { - // do nothing if it failed - } - } - } - - return std::unique_ptr(); -} - - - -} // namespace usb -} // namespace rev - -#else -typedef int __ISOWarning__CLEAR_; -#endif // _WIN32 diff --git a/src/main/native/cpp/Drivers/Serial/SerialMessage.cpp b/src/main/native/cpp/Drivers/Serial/SerialMessage.cpp deleted file mode 100644 index 983aec7..0000000 --- a/src/main/native/cpp/Drivers/Serial/SerialMessage.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "rev/Drivers/SerialPort/SerialMessage.h" - -// Constant defines of valid message IDS for the serial communication -const int CMD_API_CLEAR_FAULTS = 0x06E; -const int CMD_API_DRV_STAT = 0x06A; -const int CMD_API_BURN_FLASH = 0x072; -const int CMD_API_SET_FOLLOWER = 0x073; -const int CMD_API_FACTORY_DEFAULT = 0x074; -const int CMD_API_FACTORY_RESET = 0x075; - -const int CMD_API_FIRMWARE = 0x098; - -const int CMD_API_SWDL_BOOTLOADER = 0x1FF; -const int CMD_API_SWDL_DATA = 0x09C; -const int CMD_API_SWDL_CHKSUM = 0x09D; -const int CMD_API_SWDL_RETRANSMIT = 0x09E; - -const int ID_SIZE = 13; - -const int ValidIds[ID_SIZE] = { - CMD_API_CLEAR_FAULTS, - CMD_API_DRV_STAT, - CMD_API_BURN_FLASH, - CMD_API_SET_FOLLOWER, - CMD_API_FACTORY_DEFAULT, - CMD_API_FACTORY_RESET, - - CMD_API_FIRMWARE, - - CMD_API_SWDL_BOOTLOADER, - CMD_API_SWDL_DATA, - CMD_API_SWDL_CHKSUM, - CMD_API_SWDL_RETRANSMIT, - - // Reset into DFU Mode command - 0x010, - - CMD_API_PARAM_ACCESS -}; - -bool IsValidSerialMessageId(uint16_t apiId) { - - for (int i = 0; i <= ID_SIZE; i++) { - if (ValidIds[i] == apiId) { - return true; - } - } - - return false; -} - -bool IsConfigParameter(uint16_t apiId) { - if (apiId >= CMD_API_PARAM_ACCESS) { - return true; - } - - return false; -} - -bool IsLegacyGetParam(uint32_t msgId) { - return ((msgId & GET_CONFIG_PARAM) == GET_CONFIG_PARAM) || ((msgId & SET_CONFIG_PARAM) == SET_CONFIG_PARAM); -} - diff --git a/src/main/native/cpp/serial/list_ports_linux.cc b/src/main/native/cpp/serial/list_ports_linux.cc deleted file mode 100644 index 349e36f..0000000 --- a/src/main/native/cpp/serial/list_ports_linux.cc +++ /dev/null @@ -1,335 +0,0 @@ -#if defined(__linux__) - -/* - * Copyright (c) 2014 Craig Lilley - * This software is made available under the terms of the MIT licence. - * A copy of the licence can be obtained from: - * http://opensource.org/licenses/MIT - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "serial.h" - -using serial::PortInfo; -using std::istringstream; -using std::ifstream; -using std::getline; -using std::vector; -using std::string; -using std::cout; -using std::endl; - -static vector glob(const vector& patterns); -static string basename(const string& path); -static string dirname(const string& path); -static bool path_exists(const string& path); -static string realpath(const string& path); -static string usb_sysfs_friendly_name(const string& sys_usb_path); -static vector get_sysfs_info(const string& device_path); -static string read_line(const string& file); -static string usb_sysfs_hw_string(const string& sysfs_path); -static string format(const char* format, ...); - -vector -glob(const vector& patterns) -{ - vector paths_found; - - if(patterns.size() == 0) - return paths_found; - - glob_t glob_results; - - glob(patterns[0].c_str(), 0, NULL, &glob_results); - - vector::const_iterator iter = patterns.begin(); - - while(++iter != patterns.end()) - { - glob(iter->c_str(), GLOB_APPEND, NULL, &glob_results); - } - - for(uint path_index = 0; path_index < glob_results.gl_pathc; path_index++) - { - paths_found.push_back(glob_results.gl_pathv[path_index]); - } - - globfree(&glob_results); - - return paths_found; -} - -string -basename(const string& path) -{ - size_t pos = path.rfind("/"); - - if(pos == std::string::npos) - return path; - - return string(path, pos+1, string::npos); -} - -string -dirname(const string& path) -{ - size_t pos = path.rfind("/"); - - if(pos == std::string::npos) - return path; - else if(pos == 0) - return "/"; - - return string(path, 0, pos); -} - -bool -path_exists(const string& path) -{ - struct stat sb; - - if( stat(path.c_str(), &sb ) == 0 ) - return true; - - return false; -} - -string -realpath(const string& path) -{ - char* real_path = realpath(path.c_str(), NULL); - - string result; - - if(real_path != NULL) - { - result = real_path; - - free(real_path); - } - - return result; -} - -string -usb_sysfs_friendly_name(const string& sys_usb_path) -{ - unsigned int device_number = 0; - - istringstream( read_line(sys_usb_path + "/devnum") ) >> device_number; - - string manufacturer = read_line( sys_usb_path + "/manufacturer" ); - - string product = read_line( sys_usb_path + "/product" ); - - string serial = read_line( sys_usb_path + "/serial" ); - - if( manufacturer.empty() && product.empty() && serial.empty() ) - return ""; - - return format("%s %s %s", manufacturer.c_str(), product.c_str(), serial.c_str() ); -} - -vector -get_sysfs_info(const string& device_path) -{ - string device_name = basename( device_path ); - - string friendly_name; - - string hardware_id; - - string sys_device_path = format( "/sys/class/tty/%s/device", device_name.c_str() ); - - if( device_name.compare(0,6,"ttyUSB") == 0 ) - { - sys_device_path = dirname( dirname( realpath( sys_device_path ) ) ); - - if( path_exists( sys_device_path ) ) - { - friendly_name = usb_sysfs_friendly_name( sys_device_path ); - - hardware_id = usb_sysfs_hw_string( sys_device_path ); - } - } - else if( device_name.compare(0,6,"ttyACM") == 0 ) - { - sys_device_path = dirname( realpath( sys_device_path ) ); - - if( path_exists( sys_device_path ) ) - { - friendly_name = usb_sysfs_friendly_name( sys_device_path ); - - hardware_id = usb_sysfs_hw_string( sys_device_path ); - } - } - else - { - // Try to read ID string of PCI device - - string sys_id_path = sys_device_path + "/id"; - - if( path_exists( sys_id_path ) ) - hardware_id = read_line( sys_id_path ); - } - - if( friendly_name.empty() ) - friendly_name = device_name; - - if( hardware_id.empty() ) - hardware_id = "n/a"; - - vector result; - result.push_back(friendly_name); - result.push_back(hardware_id); - - return result; -} - -string -read_line(const string& file) -{ - ifstream ifs(file.c_str(), ifstream::in); - - string line; - - if(ifs) - { - getline(ifs, line); - } - - return line; -} - -string -format(const char* format, ...) -{ - va_list ap; - - size_t buffer_size_bytes = 256; - - string result; - - char* buffer = (char*)malloc(buffer_size_bytes); - - if( buffer == NULL ) - return result; - - bool done = false; - - unsigned int loop_count = 0; - - while(!done) - { - va_start(ap, format); - - int return_value = vsnprintf(buffer, buffer_size_bytes, format, ap); - - if( return_value < 0 ) - { - done = true; - } - else if( return_value >= static_cast(buffer_size_bytes) ) - { - // Realloc and try again. - - buffer_size_bytes = return_value + 1; - - char* new_buffer_ptr = (char*)realloc(buffer, buffer_size_bytes); - - if( new_buffer_ptr == NULL ) - { - done = true; - } - else - { - buffer = new_buffer_ptr; - } - } - else - { - result = buffer; - done = true; - } - - va_end(ap); - - if( ++loop_count > 5 ) - done = true; - } - - free(buffer); - - return result; -} - -string -usb_sysfs_hw_string(const string& sysfs_path) -{ - string serial_number = read_line( sysfs_path + "/serial" ); - - if( serial_number.length() > 0 ) - { - serial_number = format( "SNR=%s", serial_number.c_str() ); - } - - string vid = read_line( sysfs_path + "/idVendor" ); - - string pid = read_line( sysfs_path + "/idProduct" ); - - return format("USB VID:PID=%s:%s %s", vid.c_str(), pid.c_str(), serial_number.c_str() ); -} - -vector -serial::list_ports() -{ - vector results; - - vector search_globs; - search_globs.push_back("/dev/ttyACM*"); - search_globs.push_back("/dev/ttyS*"); - search_globs.push_back("/dev/ttyUSB*"); - search_globs.push_back("/dev/tty.*"); - search_globs.push_back("/dev/cu.*"); - - vector devices_found = glob( search_globs ); - - vector::iterator iter = devices_found.begin(); - - while( iter != devices_found.end() ) - { - string device = *iter++; - - vector sysfs_info = get_sysfs_info( device ); - - string friendly_name = sysfs_info[0]; - - string hardware_id = sysfs_info[1]; - - PortInfo device_entry; - device_entry.port = device; - device_entry.description = friendly_name; - device_entry.hardware_id = hardware_id; - - results.push_back( device_entry ); - - } - - return results; -} - -#endif // defined(__linux__) diff --git a/src/main/native/cpp/serial/list_ports_osx.cc b/src/main/native/cpp/serial/list_ports_osx.cc deleted file mode 100644 index 333c55c..0000000 --- a/src/main/native/cpp/serial/list_ports_osx.cc +++ /dev/null @@ -1,286 +0,0 @@ -#if defined(__APPLE__) - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include "serial/serial.h" - -using serial::PortInfo; -using std::string; -using std::vector; - -#define HARDWARE_ID_STRING_LENGTH 128 - -string cfstring_to_string( CFStringRef cfstring ); -string get_device_path( io_object_t& serial_port ); -string get_class_name( io_object_t& obj ); -io_registry_entry_t get_parent_iousb_device( io_object_t& serial_port ); -string get_string_property( io_object_t& device, const char* property ); -uint16_t get_int_property( io_object_t& device, const char* property ); -string rtrim(const string& str); - -string -cfstring_to_string( CFStringRef cfstring ) -{ - char cstring[MAXPATHLEN]; - string result; - - if( cfstring ) - { - Boolean success = CFStringGetCString( cfstring, - cstring, - sizeof(cstring), - kCFStringEncodingASCII ); - - if( success ) - result = cstring; - } - - return result; -} - -string -get_device_path( io_object_t& serial_port ) -{ - CFTypeRef callout_path; - string device_path; - - callout_path = IORegistryEntryCreateCFProperty( serial_port, - CFSTR(kIOCalloutDeviceKey), - kCFAllocatorDefault, - 0 ); - - if (callout_path) - { - if( CFGetTypeID(callout_path) == CFStringGetTypeID() ) - device_path = cfstring_to_string( static_cast(callout_path) ); - - CFRelease(callout_path); - } - - return device_path; -} - -string -get_class_name( io_object_t& obj ) -{ - string result; - io_name_t class_name; - kern_return_t kern_result; - - kern_result = IOObjectGetClass( obj, class_name ); - - if( kern_result == KERN_SUCCESS ) - result = class_name; - - return result; -} - -io_registry_entry_t -get_parent_iousb_device( io_object_t& serial_port ) -{ - io_object_t device = serial_port; - io_registry_entry_t parent = 0; - io_registry_entry_t result = 0; - kern_return_t kern_result = KERN_FAILURE; - string name = get_class_name(device); - - // Walk the IO Registry tree looking for this devices parent IOUSBDevice. - while( name != "IOUSBDevice" ) - { - kern_result = IORegistryEntryGetParentEntry( device, - kIOServicePlane, - &parent ); - - if(kern_result != KERN_SUCCESS) - { - result = 0; - break; - } - - device = parent; - - name = get_class_name(device); - } - - if(kern_result == KERN_SUCCESS) - result = device; - - return result; -} - -string -get_string_property( io_object_t& device, const char* property ) -{ - string property_name; - - if( device ) - { - CFStringRef property_as_cfstring = CFStringCreateWithCString ( - kCFAllocatorDefault, - property, - kCFStringEncodingASCII ); - - CFTypeRef name_as_cfstring = IORegistryEntryCreateCFProperty( - device, - property_as_cfstring, - kCFAllocatorDefault, - 0 ); - - if( name_as_cfstring ) - { - if( CFGetTypeID(name_as_cfstring) == CFStringGetTypeID() ) - property_name = cfstring_to_string( static_cast(name_as_cfstring) ); - - CFRelease(name_as_cfstring); - } - - if(property_as_cfstring) - CFRelease(property_as_cfstring); - } - - return property_name; -} - -uint16_t -get_int_property( io_object_t& device, const char* property ) -{ - uint16_t result = 0; - - if( device ) - { - CFStringRef property_as_cfstring = CFStringCreateWithCString ( - kCFAllocatorDefault, - property, - kCFStringEncodingASCII ); - - CFTypeRef number = IORegistryEntryCreateCFProperty( device, - property_as_cfstring, - kCFAllocatorDefault, - 0 ); - - if(property_as_cfstring) - CFRelease(property_as_cfstring); - - if( number ) - { - if( CFGetTypeID(number) == CFNumberGetTypeID() ) - { - bool success = CFNumberGetValue( static_cast(number), - kCFNumberSInt16Type, - &result ); - - if( !success ) - result = 0; - } - - CFRelease(number); - } - - } - - return result; -} - -string rtrim(const string& str) -{ - string result = str; - - string whitespace = " \t\f\v\n\r"; - - std::size_t found = result.find_last_not_of(whitespace); - - if (found != std::string::npos) - result.erase(found+1); - else - result.clear(); - - return result; -} - -vector -serial::list_ports(void) -{ - vector devices_found; - CFMutableDictionaryRef classes_to_match; - io_iterator_t serial_port_iterator; - io_object_t serial_port; - mach_port_t master_port; - kern_return_t kern_result; - - kern_result = IOMasterPort(MACH_PORT_NULL, &master_port); - - if(kern_result != KERN_SUCCESS) - return devices_found; - - classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue); - - if (classes_to_match == NULL) - return devices_found; - - CFDictionarySetValue( classes_to_match, - CFSTR(kIOSerialBSDTypeKey), - CFSTR(kIOSerialBSDAllTypes) ); - - kern_result = IOServiceGetMatchingServices(master_port, classes_to_match, &serial_port_iterator); - - if (KERN_SUCCESS != kern_result) - return devices_found; - - while ( (serial_port = IOIteratorNext(serial_port_iterator)) ) - { - string device_path = get_device_path( serial_port ); - io_registry_entry_t parent = get_parent_iousb_device( serial_port ); - IOObjectRelease(serial_port); - - if( device_path.empty() ) - continue; - - PortInfo port_info; - port_info.port = device_path; - port_info.description = "n/a"; - port_info.hardware_id = "n/a"; - - string device_name = rtrim( get_string_property( parent, "USB Product Name" ) ); - string vendor_name = rtrim( get_string_property( parent, "USB Vendor Name") ); - string description = rtrim( vendor_name + " " + device_name ); - if( !description.empty() ) - port_info.description = description; - - string serial_number = rtrim(get_string_property( parent, "USB Serial Number" ) ); - uint16_t vendor_id = get_int_property( parent, "idVendor" ); - uint16_t product_id = get_int_property( parent, "idProduct" ); - - if( vendor_id && product_id ) - { - char cstring[HARDWARE_ID_STRING_LENGTH]; - - if(serial_number.empty()) - serial_number = "None"; - - int ret = snprintf( cstring, HARDWARE_ID_STRING_LENGTH, "USB VID:PID=%04x:%04x SNR=%s", - vendor_id, - product_id, - serial_number.c_str() ); - - if( (ret >= 0) && (ret < HARDWARE_ID_STRING_LENGTH) ) - port_info.hardware_id = cstring; - } - - devices_found.push_back(port_info); - } - - IOObjectRelease(serial_port_iterator); - return devices_found; -} - -#endif // defined(__APPLE__) diff --git a/src/main/native/cpp/serial/list_ports_win.cc b/src/main/native/cpp/serial/list_ports_win.cc deleted file mode 100644 index 8d384b1..0000000 --- a/src/main/native/cpp/serial/list_ports_win.cc +++ /dev/null @@ -1,160 +0,0 @@ -#if defined(_WIN32) - -/* - * Copyright (c) 2014 Craig Lilley - * This software is made available under the terms of the MIT licence. - * A copy of the licence can be obtained from: - * http://opensource.org/licenses/MIT - */ - -#include "serial.h" -#include -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#pragma comment(lib, "winusb.lib") -#pragma comment(lib, "setupapi.lib") -#pragma comment(lib, "ole32.lib") -#pragma comment(lib, "advapi32.lib") -#endif - -using serial::PortInfo; -using std::vector; -using std::string; - -static const DWORD port_name_max_length = 256; -static const DWORD friendly_name_max_length = 256; -static const DWORD hardware_id_max_length = 256; - -// Convert a wide Unicode string to an UTF8 string -std::string utf8_encode(const std::wstring &wstr) -{ - int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL); - std::string strTo( size_needed, 0 ); - WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL); - return strTo; -} - -vector -serial::list_ports() -{ - vector devices_found; - - HDEVINFO device_info_set = SetupDiGetClassDevs( - (const GUID *) &GUID_DEVCLASS_PORTS, - NULL, - NULL, - DIGCF_PRESENT); - - unsigned int device_info_set_index = 0; - SP_DEVINFO_DATA device_info_data; - - device_info_data.cbSize = sizeof(SP_DEVINFO_DATA); - - while(SetupDiEnumDeviceInfo(device_info_set, device_info_set_index, &device_info_data)) - { - device_info_set_index++; - - // Get port name - - HKEY hkey = SetupDiOpenDevRegKey( - device_info_set, - &device_info_data, - DICS_FLAG_GLOBAL, - 0, - DIREG_DEV, - KEY_READ); - - TCHAR port_name[port_name_max_length]; - DWORD port_name_length = port_name_max_length; - - LONG return_code = RegQueryValueEx( - hkey, - _T("PortName"), - NULL, - NULL, - (LPBYTE)port_name, - &port_name_length); - - RegCloseKey(hkey); - - if(return_code != EXIT_SUCCESS) - continue; - - if(port_name_length > 0 && port_name_length <= port_name_max_length) - port_name[port_name_length-1] = '\0'; - else - port_name[0] = '\0'; - - // Ignore parallel ports - - if(_tcsstr(port_name, _T("LPT")) != NULL) - continue; - - // Get port friendly name - - TCHAR friendly_name[friendly_name_max_length]; - DWORD friendly_name_actual_length = 0; - - BOOL got_friendly_name = SetupDiGetDeviceRegistryProperty( - device_info_set, - &device_info_data, - SPDRP_FRIENDLYNAME, - NULL, - (PBYTE)friendly_name, - friendly_name_max_length, - &friendly_name_actual_length); - - if(got_friendly_name == TRUE && friendly_name_actual_length > 0) - friendly_name[friendly_name_actual_length-1] = '\0'; - else - friendly_name[0] = '\0'; - - // Get hardware ID - - TCHAR hardware_id[hardware_id_max_length]; - DWORD hardware_id_actual_length = 0; - - BOOL got_hardware_id = SetupDiGetDeviceRegistryProperty( - device_info_set, - &device_info_data, - SPDRP_HARDWAREID, - NULL, - (PBYTE)hardware_id, - hardware_id_max_length, - &hardware_id_actual_length); - - if(got_hardware_id == TRUE && hardware_id_actual_length > 0) - hardware_id[hardware_id_actual_length-1] = '\0'; - else - hardware_id[0] = '\0'; - - #ifdef UNICODE - std::string portName = utf8_encode(port_name); - std::string friendlyName = utf8_encode(friendly_name); - std::string hardwareId = utf8_encode(hardware_id); - #else - std::string portName = port_name; - std::string friendlyName = friendly_name; - std::string hardwareId = hardware_id; - #endif - - PortInfo port_entry; - port_entry.port = portName; - port_entry.description = friendlyName; - port_entry.hardware_id = hardwareId; - - devices_found.push_back(port_entry); - } - - SetupDiDestroyDeviceInfoList(device_info_set); - - return devices_found; -} - -#endif // #if defined(_WIN32) diff --git a/src/main/native/cpp/serial/serial.cc b/src/main/native/cpp/serial/serial.cc deleted file mode 100644 index 504098a..0000000 --- a/src/main/native/cpp/serial/serial.cc +++ /dev/null @@ -1,430 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison */ -#include - -#if !defined(_WIN32) && !defined(__OpenBSD__) && !defined(__FreeBSD__) -# include -#endif - -#if defined (__MINGW32__) -# define alloca __builtin_alloca -#endif - -#include "serial.h" - -#ifdef _WIN32 -#include "win.h" -#else -#include "unix.h" -#endif - -using std::invalid_argument; -using std::min; -using std::numeric_limits; -using std::vector; -using std::size_t; -using std::string; - -using serial::Serial; -using serial::SerialException; -using serial::IOException; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; - -class Serial::ScopedReadLock { -public: - ScopedReadLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->readLock(); - } - ~ScopedReadLock() { - this->pimpl_->readUnlock(); - } -private: - // Disable copy constructors - ScopedReadLock(const ScopedReadLock&); - const ScopedReadLock& operator=(ScopedReadLock); - - SerialImpl *pimpl_; -}; - -class Serial::ScopedWriteLock { -public: - ScopedWriteLock(SerialImpl *pimpl) : pimpl_(pimpl) { - this->pimpl_->writeLock(); - } - ~ScopedWriteLock() { - this->pimpl_->writeUnlock(); - } -private: - // Disable copy constructors - ScopedWriteLock(const ScopedWriteLock&); - const ScopedWriteLock& operator=(ScopedWriteLock); - SerialImpl *pimpl_; -}; - -Serial::Serial (const string &port, uint32_t baudrate, serial::Timeout timeout, - bytesize_t bytesize, parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : pimpl_(new SerialImpl (port, baudrate, bytesize, parity, - stopbits, flowcontrol)) -{ - pimpl_->setTimeout(timeout); -} - -Serial::~Serial () -{ - delete pimpl_; -} - -void -Serial::open () -{ - pimpl_->open (); -} - -void -Serial::close () -{ - pimpl_->close (); -} - -bool -Serial::isOpen () const -{ - return pimpl_->isOpen (); -} - -size_t -Serial::available () -{ - return pimpl_->available (); -} - -bool -Serial::waitReadable () -{ - serial::Timeout timeout(pimpl_->getTimeout ()); - return pimpl_->waitReadable(timeout.read_timeout_constant); -} - -void -Serial::waitByteTimes (size_t count) -{ - pimpl_->waitByteTimes(count); -} - -size_t -Serial::read_ (uint8_t *buffer, size_t size) -{ - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (uint8_t *buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - return this->pimpl_->read (buffer, size); -} - -size_t -Serial::read (std::vector &buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = 0; - - try { - bytes_read = this->pimpl_->read (buffer_, size); - } - catch (const std::exception &e) { - delete[] buffer_; - throw e; - } - - buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); - delete[] buffer_; - return bytes_read; -} - -size_t -Serial::read (std::string &buffer, size_t size) -{ - ScopedReadLock lock(this->pimpl_); - uint8_t *buffer_ = new uint8_t[size]; - size_t bytes_read = 0; - try { - bytes_read = this->pimpl_->read (buffer_, size); - } - catch (const std::exception &e) { - delete[] buffer_; - throw e; - } - buffer.append (reinterpret_cast(buffer_), bytes_read); - delete[] buffer_; - return bytes_read; -} - -string -Serial::read (size_t size) -{ - std::string buffer; - this->read (buffer, size); - return buffer; -} - -size_t -Serial::readline (string &buffer, size_t size, string eol) -{ - ScopedReadLock lock(this->pimpl_); - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - while (true) - { - size_t bytes_read = this->read_ (buffer_ + read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - break; // EOL found - } - if (read_so_far == size) { - break; // Reached the maximum read length - } - } - buffer.append(reinterpret_cast (buffer_), read_so_far); - return read_so_far; -} - -string -Serial::readline (size_t size, string eol) -{ - std::string buffer; - this->readline (buffer, size, eol); - return buffer; -} - -vector -Serial::readlines (size_t size, string eol) -{ - ScopedReadLock lock(this->pimpl_); - std::vector lines; - size_t eol_len = eol.length (); - uint8_t *buffer_ = static_cast - (alloca (size * sizeof (uint8_t))); - size_t read_so_far = 0; - size_t start_of_line = 0; - while (read_so_far < size) { - size_t bytes_read = this->read_ (buffer_+read_so_far, 1); - read_so_far += bytes_read; - if (bytes_read == 0) { - if (start_of_line != read_so_far) { - lines.push_back ( - string (reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Timeout occured on reading 1 byte - } - if (string (reinterpret_cast - (buffer_ + read_so_far - eol_len), eol_len) == eol) { - // EOL found - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - start_of_line = read_so_far; - } - if (read_so_far == size) { - if (start_of_line != read_so_far) { - lines.push_back( - string(reinterpret_cast (buffer_ + start_of_line), - read_so_far - start_of_line)); - } - break; // Reached the maximum read length - } - } - return lines; -} - -size_t -Serial::write (const string &data) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_ (reinterpret_cast(data.c_str()), - data.length()); -} - -size_t -Serial::write (const std::vector &data) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_ (&data[0], data.size()); -} - -size_t -Serial::write (const uint8_t *data, size_t size) -{ - ScopedWriteLock lock(this->pimpl_); - return this->write_(data, size); -} - -size_t -Serial::write_ (const uint8_t *data, size_t length) -{ - return pimpl_->write (data, length); -} - -void -Serial::setPort (const string &port) -{ - ScopedReadLock rlock(this->pimpl_); - ScopedWriteLock wlock(this->pimpl_); - bool was_open = pimpl_->isOpen (); - if (was_open) close(); - pimpl_->setPort (port); - if (was_open) open (); -} - -string -Serial::getPort () const -{ - return pimpl_->getPort (); -} - -void -Serial::setTimeout (serial::Timeout &timeout) -{ - pimpl_->setTimeout (timeout); -} - -serial::Timeout -Serial::getTimeout () const { - return pimpl_->getTimeout (); -} - -void -Serial::setBaudrate (uint32_t baudrate) -{ - pimpl_->setBaudrate (baudrate); -} - -uint32_t -Serial::getBaudrate () const -{ - return uint32_t(pimpl_->getBaudrate ()); -} - -void -Serial::setBytesize (bytesize_t bytesize) -{ - pimpl_->setBytesize (bytesize); -} - -bytesize_t -Serial::getBytesize () const -{ - return pimpl_->getBytesize (); -} - -void -Serial::setParity (parity_t parity) -{ - pimpl_->setParity (parity); -} - -parity_t -Serial::getParity () const -{ - return pimpl_->getParity (); -} - -void -Serial::setStopbits (stopbits_t stopbits) -{ - pimpl_->setStopbits (stopbits); -} - -stopbits_t -Serial::getStopbits () const -{ - return pimpl_->getStopbits (); -} - -void -Serial::setFlowcontrol (flowcontrol_t flowcontrol) -{ - pimpl_->setFlowcontrol (flowcontrol); -} - -flowcontrol_t -Serial::getFlowcontrol () const -{ - return pimpl_->getFlowcontrol (); -} - -void Serial::flush () -{ - ScopedReadLock rlock(this->pimpl_); - ScopedWriteLock wlock(this->pimpl_); - pimpl_->flush (); -} - -void Serial::flushInput () -{ - ScopedReadLock lock(this->pimpl_); - pimpl_->flushInput (); -} - -void Serial::flushOutput () -{ - ScopedWriteLock lock(this->pimpl_); - pimpl_->flushOutput (); -} - -void Serial::sendBreak (int duration) -{ - pimpl_->sendBreak (duration); -} - -void Serial::setBreak (bool level) -{ - pimpl_->setBreak (level); -} - -void Serial::setRTS (bool level) -{ - pimpl_->setRTS (level); -} - -void Serial::setDTR (bool level) -{ - pimpl_->setDTR (level); -} - -bool Serial::waitForChange() -{ - return pimpl_->waitForChange(); -} - -bool Serial::getCTS () -{ - return pimpl_->getCTS (); -} - -bool Serial::getDSR () -{ - return pimpl_->getDSR (); -} - -bool Serial::getRI () -{ - return pimpl_->getRI (); -} - -bool Serial::getCD () -{ - return pimpl_->getCD (); -} diff --git a/src/main/native/cpp/serial/symbols.txt b/src/main/native/cpp/serial/symbols.txt deleted file mode 100644 index eed099f..0000000 --- a/src/main/native/cpp/serial/symbols.txt +++ /dev/null @@ -1 +0,0 @@ -list_ports \ No newline at end of file diff --git a/src/main/native/cpp/serial/unix.cc b/src/main/native/cpp/serial/unix.cc deleted file mode 100644 index 4283548..0000000 --- a/src/main/native/cpp/serial/unix.cc +++ /dev/null @@ -1,1066 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison - * - * Additional Contributors: Christopher Baker @bakercp - */ - -#if !defined(_WIN32) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__linux__) -# include -#endif - -#include -#include -#include -#ifdef __MACH__ -#include -#include -#include -#endif - -#include "unix.h" - -#ifndef TIOCINQ -#ifdef FIONREAD -#define TIOCINQ FIONREAD -#else -#define TIOCINQ 0x541B -#endif -#endif - -#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3) -#include -#endif - -using std::string; -using std::stringstream; -using std::invalid_argument; -using serial::MillisecondTimer; -using serial::Serial; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - - -MillisecondTimer::MillisecondTimer (const uint32_t millis) - : expiry(timespec_now()) -{ - int64_t tv_nsec = expiry.tv_nsec + (millis * 1e6); - if (tv_nsec >= 1e9) { - int64_t sec_diff = tv_nsec / static_cast (1e9); - expiry.tv_nsec = tv_nsec % static_cast(1e9); - expiry.tv_sec += sec_diff; - } else { - expiry.tv_nsec = tv_nsec; - } -} - -int64_t -MillisecondTimer::remaining () -{ - timespec now(timespec_now()); - int64_t millis = (expiry.tv_sec - now.tv_sec) * 1e3; - millis += (expiry.tv_nsec - now.tv_nsec) / 1e6; - return millis; -} - -timespec -MillisecondTimer::timespec_now () -{ - timespec time; -# ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time - clock_serv_t cclock; - mach_timespec_t mts; - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - time.tv_sec = mts.tv_sec; - time.tv_nsec = mts.tv_nsec; -# else - clock_gettime(CLOCK_MONOTONIC, &time); -# endif - return time; -} - -timespec -timespec_from_ms (const uint32_t millis) -{ - timespec time; - time.tv_sec = millis / 1e3; - time.tv_nsec = (millis - (time.tv_sec * 1e3)) * 1e6; - return time; -} - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (false), rtscts_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - pthread_mutex_init(&this->read_mutex, NULL); - pthread_mutex_init(&this->write_mutex, NULL); - if (port_.empty () == false) - open (); -} - -Serial::SerialImpl::~SerialImpl () -{ - close(); - pthread_mutex_destroy(&this->read_mutex); - pthread_mutex_destroy(&this->write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - - if (fd_ == -1) { - switch (errno) { - case EINTR: - // Recurse because this is a recoverable error. - open (); - return; - case ENFILE: - case EMFILE: - THROW (IOException, "Too many file handles open."); - default: - THROW (IOException, errno); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == -1) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - struct termios options; // The options for the file descriptor - - if (tcgetattr(fd_, &options) == -1) { - THROW (IOException, "::tcgetattr"); - } - - // set up raw mode / no echo / binary - options.c_cflag |= (tcflag_t) (CLOCAL | CREAD); - options.c_lflag &= (tcflag_t) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | - ISIG | IEXTEN); //|ECHOPRT - - options.c_oflag &= (tcflag_t) ~(OPOST); - options.c_iflag &= (tcflag_t) ~(INLCR | IGNCR | ICRNL | IGNBRK); -#ifdef IUCLC - options.c_iflag &= (tcflag_t) ~IUCLC; -#endif -#ifdef PARMRK - options.c_iflag &= (tcflag_t) ~PARMRK; -#endif - - // setup baud rate - bool custom_baud = false; - speed_t baud; - switch (baudrate_) { -#ifdef B0 - case 0: baud = B0; break; -#endif -#ifdef B50 - case 50: baud = B50; break; -#endif -#ifdef B75 - case 75: baud = B75; break; -#endif -#ifdef B110 - case 110: baud = B110; break; -#endif -#ifdef B134 - case 134: baud = B134; break; -#endif -#ifdef B150 - case 150: baud = B150; break; -#endif -#ifdef B200 - case 200: baud = B200; break; -#endif -#ifdef B300 - case 300: baud = B300; break; -#endif -#ifdef B600 - case 600: baud = B600; break; -#endif -#ifdef B1200 - case 1200: baud = B1200; break; -#endif -#ifdef B1800 - case 1800: baud = B1800; break; -#endif -#ifdef B2400 - case 2400: baud = B2400; break; -#endif -#ifdef B4800 - case 4800: baud = B4800; break; -#endif -#ifdef B7200 - case 7200: baud = B7200; break; -#endif -#ifdef B9600 - case 9600: baud = B9600; break; -#endif -#ifdef B14400 - case 14400: baud = B14400; break; -#endif -#ifdef B19200 - case 19200: baud = B19200; break; -#endif -#ifdef B28800 - case 28800: baud = B28800; break; -#endif -#ifdef B57600 - case 57600: baud = B57600; break; -#endif -#ifdef B76800 - case 76800: baud = B76800; break; -#endif -#ifdef B38400 - case 38400: baud = B38400; break; -#endif -#ifdef B115200 - case 115200: baud = B115200; break; -#endif -#ifdef B128000 - case 128000: baud = B128000; break; -#endif -#ifdef B153600 - case 153600: baud = B153600; break; -#endif -#ifdef B230400 - case 230400: baud = B230400; break; -#endif -#ifdef B256000 - case 256000: baud = B256000; break; -#endif -#ifdef B460800 - case 460800: baud = B460800; break; -#endif -#ifdef B500000 - case 500000: baud = B500000; break; -#endif -#ifdef B576000 - case 576000: baud = B576000; break; -#endif -#ifdef B921600 - case 921600: baud = B921600; break; -#endif -#ifdef B1000000 - case 1000000: baud = B1000000; break; -#endif -#ifdef B1152000 - case 1152000: baud = B1152000; break; -#endif -#ifdef B1500000 - case 1500000: baud = B1500000; break; -#endif -#ifdef B2000000 - case 2000000: baud = B2000000; break; -#endif -#ifdef B2500000 - case 2500000: baud = B2500000; break; -#endif -#ifdef B3000000 - case 3000000: baud = B3000000; break; -#endif -#ifdef B3500000 - case 3500000: baud = B3500000; break; -#endif -#ifdef B4000000 - case 4000000: baud = B4000000; break; -#endif - default: - custom_baud = true; - // OS X support -#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) - // Starting with Tiger, the IOSSIOSPEED ioctl can be used to set arbitrary baud rates - // other than those specified by POSIX. The driver for the underlying serial hardware - // ultimately determines which baud rates can be used. This ioctl sets both the input - // and output speed. - speed_t new_baud = static_cast (baudrate_); - if (-1 == ioctl (fd_, IOSSIOSPEED, &new_baud, 1)) { - THROW (IOException, errno); - } - // Linux Support -#elif defined(__linux__) && defined (TIOCSSERIAL) - struct serial_struct ser; - - if (-1 == ioctl (fd_, TIOCGSERIAL, &ser)) { - THROW (IOException, errno); - } - - // set custom divisor - ser.custom_divisor = ser.baud_base / static_cast (baudrate_); - // update flags - ser.flags &= ~ASYNC_SPD_MASK; - ser.flags |= ASYNC_SPD_CUST; - - if (-1 == ioctl (fd_, TIOCSSERIAL, &ser)) { - THROW (IOException, errno); - } -#else - throw invalid_argument ("OS does not currently support custom bauds"); -#endif - } - if (custom_baud == false) { -#ifdef _BSD_SOURCE - ::cfsetspeed(&options, baud); -#else - ::cfsetispeed(&options, baud); - ::cfsetospeed(&options, baud); -#endif - } - - // setup char len - options.c_cflag &= (tcflag_t) ~CSIZE; - if (bytesize_ == eightbits) - options.c_cflag |= CS8; - else if (bytesize_ == sevenbits) - options.c_cflag |= CS7; - else if (bytesize_ == sixbits) - options.c_cflag |= CS6; - else if (bytesize_ == fivebits) - options.c_cflag |= CS5; - else - throw invalid_argument ("invalid char len"); - // setup stopbits - if (stopbits_ == stopbits_one) - options.c_cflag &= (tcflag_t) ~(CSTOPB); - else if (stopbits_ == stopbits_one_point_five) - // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 - options.c_cflag |= (CSTOPB); - else if (stopbits_ == stopbits_two) - options.c_cflag |= (CSTOPB); - else - throw invalid_argument ("invalid stop bit"); - // setup parity - options.c_iflag &= (tcflag_t) ~(INPCK | ISTRIP); - if (parity_ == parity_none) { - options.c_cflag &= (tcflag_t) ~(PARENB | PARODD); - } else if (parity_ == parity_even) { - options.c_cflag &= (tcflag_t) ~(PARODD); - options.c_cflag |= (PARENB); - } else if (parity_ == parity_odd) { - options.c_cflag |= (PARENB | PARODD); - } -#ifdef CMSPAR - else if (parity_ == parity_mark) { - options.c_cflag |= (PARENB | CMSPAR | PARODD); - } - else if (parity_ == parity_space) { - options.c_cflag |= (PARENB | CMSPAR); - options.c_cflag &= (tcflag_t) ~(PARODD); - } -#else - // CMSPAR is not defined on OSX. So do not support mark or space parity. - else if (parity_ == parity_mark || parity_ == parity_space) { - throw invalid_argument ("OS does not support mark or space parity"); - } -#endif // ifdef CMSPAR - else { - throw invalid_argument ("invalid parity"); - } - // setup flow control - if (flowcontrol_ == flowcontrol_none) { - xonxoff_ = false; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_software) { - xonxoff_ = true; - rtscts_ = false; - } - if (flowcontrol_ == flowcontrol_hardware) { - xonxoff_ = false; - rtscts_ = true; - } - // xonxoff -#ifdef IXANY - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); //|IXANY) - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF | IXANY); -#else - if (xonxoff_) - options.c_iflag |= (IXON | IXOFF); - else - options.c_iflag &= (tcflag_t) ~(IXON | IXOFF); -#endif - // rtscts -#ifdef CRTSCTS - if (rtscts_) - options.c_cflag |= (CRTSCTS); - else - options.c_cflag &= (unsigned long) ~(CRTSCTS); -#elif defined CNEW_RTSCTS - if (rtscts_) - options.c_cflag |= (CNEW_RTSCTS); - else - options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS); -#else -#error "OS Support seems wrong." -#endif - - // http://www.unixwiz.net/techtips/termios-vmin-vtime.html - // this basically sets the read call up to be a polling read, - // but we are using select to ensure there is data available - // to read before each call, so we should never needlessly poll - options.c_cc[VMIN] = 0; - options.c_cc[VTIME] = 0; - - // activate settings - ::tcsetattr (fd_, TCSANOW, &options); - - // Update byte_time_ based on the new settings. - uint32_t bit_time_ns = 1e9 / baudrate_; - byte_time_ns_ = bit_time_ns * (1 + bytesize_ + parity_ + stopbits_); - - // Compensate for the stopbits_one_point_five enum being equal to int 3, - // and not 1.5. - if (stopbits_ == stopbits_one_point_five) { - byte_time_ns_ += ((1.5 - stopbits_one_point_five) * bit_time_ns); - } -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != -1) { - int ret; - ret = ::close (fd_); - if (ret == 0) { - fd_ = -1; - } else { - THROW (IOException, errno); - } - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - int count = 0; - if (-1 == ioctl (fd_, TIOCINQ, &count)) { - THROW (IOException, errno); - } else { - return static_cast (count); - } -} - -bool -Serial::SerialImpl::waitReadable (uint32_t timeout) -{ - // Setup a select call to block for serial data or a timeout - fd_set readfds; - FD_ZERO (&readfds); - FD_SET (fd_, &readfds); - timespec timeout_ts (timespec_from_ms (timeout)); - int r = pselect (fd_ + 1, &readfds, NULL, NULL, &timeout_ts, NULL); - - if (r < 0) { - // Select was interrupted - if (errno == EINTR) { - return false; - } - // Otherwise there was some error - THROW (IOException, errno); - } - // Timeout occurred - if (r == 0) { - return false; - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - if (!FD_ISSET (fd_, &readfds)) { - THROW (IOException, "select reports ready to read, but our fd isn't" - " in the list, this shouldn't happen!"); - } - // Data available to read. - return true; -} - -void -Serial::SerialImpl::waitByteTimes (size_t count) -{ - timespec wait_time = { 0, static_cast(byte_time_ns_ * count)}; - pselect (0, NULL, NULL, NULL, &wait_time, NULL); -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - // If the port is not open, throw - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - size_t bytes_read = 0; - - // Calculate total timeout in milliseconds t_c + (t_m * N) - long total_timeout_ms = timeout_.read_timeout_constant; - total_timeout_ms += timeout_.read_timeout_multiplier * static_cast (size); - MillisecondTimer total_timeout(total_timeout_ms); - - // Pre-fill buffer with available bytes - { - ssize_t bytes_read_now = ::read (fd_, buf, size); - if (bytes_read_now > 0) { - bytes_read = bytes_read_now; - } - } - - while (bytes_read < size) { - int64_t timeout_remaining_ms = total_timeout.remaining(); - if (timeout_remaining_ms <= 0) { - // Timed out - break; - } - // Timeout for the next select is whichever is less of the remaining - // total read timeout and the inter-byte timeout. - uint32_t timeout = std::min(static_cast (timeout_remaining_ms), - timeout_.inter_byte_timeout); - // Wait for the device to be readable, and then attempt to read. - if (waitReadable(timeout)) { - // If it's a fixed-length multi-byte read, insert a wait here so that - // we can attempt to grab the whole thing in a single IO call. Skip - // this wait if a non-max inter_byte_timeout is specified. - if (size > 1 && timeout_.inter_byte_timeout == Timeout::max()) { - size_t bytes_available = available(); - if (bytes_available + bytes_read < size) { - waitByteTimes(size - (bytes_available + bytes_read)); - } - } - // This should be non-blocking returning only what is available now - // Then returning so that select can block again. - ssize_t bytes_read_now = - ::read (fd_, buf + bytes_read, size - bytes_read); - // read should always return some data as select reported it was - // ready to read when we get to this point. - if (bytes_read_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to read immediately - // but reading returns nothing. - throw SerialException ("device reports readiness to read but " - "returned no data (device disconnected?)"); - } - // Update bytes_read - bytes_read += static_cast (bytes_read_now); - // If bytes_read == size then we have read everything we need - if (bytes_read == size) { - break; - } - // If bytes_read < size then we have more to read - if (bytes_read < size) { - continue; - } - // If bytes_read > size then we have over read, which shouldn't happen - if (bytes_read > size) { - throw SerialException ("read over read, too many bytes where " - "read, this shouldn't happen, might be " - "a logical error!"); - } - } - } - return bytes_read; -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - fd_set writefds; - size_t bytes_written = 0; - - // Calculate total timeout in milliseconds t_c + (t_m * N) - long total_timeout_ms = timeout_.write_timeout_constant; - total_timeout_ms += timeout_.write_timeout_multiplier * static_cast (length); - MillisecondTimer total_timeout(total_timeout_ms); - - bool first_iteration = true; - while (bytes_written < length) { - int64_t timeout_remaining_ms = total_timeout.remaining(); - // Only consider the timeout if it's not the first iteration of the loop - // otherwise a timeout of 0 won't be allowed through - if (!first_iteration && (timeout_remaining_ms <= 0)) { - // Timed out - break; - } - first_iteration = false; - - timespec timeout(timespec_from_ms(timeout_remaining_ms)); - - FD_ZERO (&writefds); - FD_SET (fd_, &writefds); - - // Do the select - int r = pselect (fd_ + 1, NULL, &writefds, NULL, &timeout, NULL); - - // Figure out what happened by looking at select's response 'r' - /** Error **/ - if (r < 0) { - // Select was interrupted, try again - if (errno == EINTR) { - continue; - } - // Otherwise there was some error - THROW (IOException, errno); - } - /** Timeout **/ - if (r == 0) { - break; - } - /** Port ready to write **/ - if (r > 0) { - // Make sure our file descriptor is in the ready to write list - if (FD_ISSET (fd_, &writefds)) { - // This will write some - ssize_t bytes_written_now = - ::write (fd_, data + bytes_written, length - bytes_written); - // write should always return some data as select reported it was - // ready to write when we get to this point. - if (bytes_written_now < 1) { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to write immediately - // but writing returns nothing. - throw SerialException ("device reports readiness to write but " - "returned no data (device disconnected?)"); - } - // Update bytes_written - bytes_written += static_cast (bytes_written_now); - // If bytes_written == size then we have written everything we need to - if (bytes_written == length) { - break; - } - // If bytes_written < size then we have more to write - if (bytes_written < length) { - continue; - } - // If bytes_written > size then we have over written, which shouldn't happen - if (bytes_written > length) { - throw SerialException ("write over wrote, too many bytes where " - "written, this shouldn't happen, might be " - "a logical error!"); - } - } - // This shouldn't happen, if r > 0 our fd has to be in the list! - THROW (IOException, "select reports ready to write, but our fd isn't" - " in the list, this shouldn't happen!"); - } - } - return bytes_written; -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = port; -} - -string -Serial::SerialImpl::getPort () const -{ - return port_; -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) - reconfigurePort (); -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) - reconfigurePort (); -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) - reconfigurePort (); -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) - reconfigurePort (); -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) - reconfigurePort (); -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - tcdrain (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushInput"); - } - tcflush (fd_, TCIFLUSH); -} - -void -Serial::SerialImpl::flushOutput () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flushOutput"); - } - tcflush (fd_, TCOFLUSH); -} - -void -Serial::SerialImpl::sendBreak (int duration) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::sendBreak"); - } - tcsendbreak (fd_, static_cast (duration / 4)); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - - if (level) { - if (-1 == ioctl (fd_, TIOCSBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCSBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCCBRK)) - { - stringstream ss; - ss << "setBreak failed on a call to ioctl(TIOCCBRK): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - - int command = TIOCM_RTS; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setRTS failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - - int command = TIOCM_DTR; - - if (level) { - if (-1 == ioctl (fd_, TIOCMBIS, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIS): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } else { - if (-1 == ioctl (fd_, TIOCMBIC, &command)) - { - stringstream ss; - ss << "setDTR failed on a call to ioctl(TIOCMBIC): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - } -} - -bool -Serial::SerialImpl::waitForChange () -{ -#ifndef TIOCMIWAIT - -while (is_open_ == true) { - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "waitForChange failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - if (0 != (status & TIOCM_CTS) - || 0 != (status & TIOCM_DSR) - || 0 != (status & TIOCM_RI) - || 0 != (status & TIOCM_CD)) - { - return true; - } - } - - usleep(1000); - } - - return false; -#else - int command = (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS); - - if (-1 == ioctl (fd_, TIOCMIWAIT, &command)) { - stringstream ss; - ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): " - << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - return true; -#endif -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCTS failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CTS); - } -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getDSR failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_DSR); - } -} - -bool -Serial::SerialImpl::getRI () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getRI failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_RI); - } -} - -bool -Serial::SerialImpl::getCD () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - - int status; - - if (-1 == ioctl (fd_, TIOCMGET, &status)) - { - stringstream ss; - ss << "getCD failed on a call to ioctl(TIOCMGET): " << errno << " " << strerror(errno); - throw(SerialException(ss.str().c_str())); - } - else - { - return 0 != (status & TIOCM_CD); - } -} - -void -Serial::SerialImpl::readLock () -{ - int result = pthread_mutex_lock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::readUnlock () -{ - int result = pthread_mutex_unlock(&this->read_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeLock () -{ - int result = pthread_mutex_lock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -void -Serial::SerialImpl::writeUnlock () -{ - int result = pthread_mutex_unlock(&this->write_mutex); - if (result) { - THROW (IOException, result); - } -} - -#endif // !defined(_WIN32) diff --git a/src/main/native/cpp/serial/win.cc b/src/main/native/cpp/serial/win.cc deleted file mode 100644 index 3b8b760..0000000 --- a/src/main/native/cpp/serial/win.cc +++ /dev/null @@ -1,651 +0,0 @@ -#if defined(_WIN32) - -/* Copyright 2012 William Woodall and John Harrison */ - -#include - -#include "win.h" - -using std::string; -using std::wstring; -using std::stringstream; -using std::invalid_argument; -using serial::Serial; -using serial::Timeout; -using serial::bytesize_t; -using serial::parity_t; -using serial::stopbits_t; -using serial::flowcontrol_t; -using serial::SerialException; -using serial::PortNotOpenedException; -using serial::IOException; - -inline wstring -_prefix_port_if_needed(const wstring &input) -{ - static wstring windows_com_port_prefix = L"\\\\.\\"; - if (input.compare(windows_com_port_prefix) != 0) - { - return windows_com_port_prefix + input; - } - return input; -} - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) - : port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false), - baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - // if (port_.empty () == false) - // open (); - read_mutex = CreateMutex(NULL, false, NULL); - write_mutex = CreateMutex(NULL, false, NULL); -} - -Serial::SerialImpl::~SerialImpl () -{ - this->close(); - CloseHandle(read_mutex); - CloseHandle(write_mutex); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty ()) { - throw invalid_argument ("Empty port is invalid."); - } - if (is_open_ == true) { - throw SerialException ("Serial port already open."); - } - - // See: https://github.com/wjwwood/serial/issues/84 - wstring port_with_prefix = _prefix_port_if_needed(port_); - LPCWSTR lp_port = port_with_prefix.c_str(); - fd_ = CreateFileW(lp_port, - GENERIC_READ | GENERIC_WRITE, - 0, - 0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - 0); - - if (fd_ == INVALID_HANDLE_VALUE) { - DWORD create_file_err = GetLastError(); - stringstream ss; - // if (create_file_err) { - // return; - // } - switch (create_file_err) { - case ERROR_FILE_NOT_FOUND: - // Use this->getPort to convert to a std::string - ss << "Specified port, " << this->getPort() << ", does not exist."; - THROW (IOException, ss.str().c_str()); - break; - default: - ss << "Unknown error opening the serial port: " << create_file_err; - THROW (IOException, ss.str().c_str()); - } - } - - reconfigurePort(); - is_open_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == INVALID_HANDLE_VALUE) { - // Can only operate on a valid file descriptor - THROW (IOException, "Invalid file descriptor, is the serial port open?"); - } - - DCB dcbSerialParams = {0}; - - dcbSerialParams.DCBlength=sizeof(dcbSerialParams); - - if (!GetCommState(fd_, &dcbSerialParams)) { - //error getting state - THROW (IOException, "Error getting the serial port state."); - } - - // setup baud rate - switch (baudrate_) { -#ifdef CBR_0 - case 0: dcbSerialParams.BaudRate = CBR_0; break; -#endif -#ifdef CBR_50 - case 50: dcbSerialParams.BaudRate = CBR_50; break; -#endif -#ifdef CBR_75 - case 75: dcbSerialParams.BaudRate = CBR_75; break; -#endif -#ifdef CBR_110 - case 110: dcbSerialParams.BaudRate = CBR_110; break; -#endif -#ifdef CBR_134 - case 134: dcbSerialParams.BaudRate = CBR_134; break; -#endif -#ifdef CBR_150 - case 150: dcbSerialParams.BaudRate = CBR_150; break; -#endif -#ifdef CBR_200 - case 200: dcbSerialParams.BaudRate = CBR_200; break; -#endif -#ifdef CBR_300 - case 300: dcbSerialParams.BaudRate = CBR_300; break; -#endif -#ifdef CBR_600 - case 600: dcbSerialParams.BaudRate = CBR_600; break; -#endif -#ifdef CBR_1200 - case 1200: dcbSerialParams.BaudRate = CBR_1200; break; -#endif -#ifdef CBR_1800 - case 1800: dcbSerialParams.BaudRate = CBR_1800; break; -#endif -#ifdef CBR_2400 - case 2400: dcbSerialParams.BaudRate = CBR_2400; break; -#endif -#ifdef CBR_4800 - case 4800: dcbSerialParams.BaudRate = CBR_4800; break; -#endif -#ifdef CBR_7200 - case 7200: dcbSerialParams.BaudRate = CBR_7200; break; -#endif -#ifdef CBR_9600 - case 9600: dcbSerialParams.BaudRate = CBR_9600; break; -#endif -#ifdef CBR_14400 - case 14400: dcbSerialParams.BaudRate = CBR_14400; break; -#endif -#ifdef CBR_19200 - case 19200: dcbSerialParams.BaudRate = CBR_19200; break; -#endif -#ifdef CBR_28800 - case 28800: dcbSerialParams.BaudRate = CBR_28800; break; -#endif -#ifdef CBR_57600 - case 57600: dcbSerialParams.BaudRate = CBR_57600; break; -#endif -#ifdef CBR_76800 - case 76800: dcbSerialParams.BaudRate = CBR_76800; break; -#endif -#ifdef CBR_38400 - case 38400: dcbSerialParams.BaudRate = CBR_38400; break; -#endif -#ifdef CBR_115200 - case 115200: dcbSerialParams.BaudRate = CBR_115200; break; -#endif -#ifdef CBR_128000 - case 128000: dcbSerialParams.BaudRate = CBR_128000; break; -#endif -#ifdef CBR_153600 - case 153600: dcbSerialParams.BaudRate = CBR_153600; break; -#endif -#ifdef CBR_230400 - case 230400: dcbSerialParams.BaudRate = CBR_230400; break; -#endif -#ifdef CBR_256000 - case 256000: dcbSerialParams.BaudRate = CBR_256000; break; -#endif -#ifdef CBR_460800 - case 460800: dcbSerialParams.BaudRate = CBR_460800; break; -#endif -#ifdef CBR_921600 - case 921600: dcbSerialParams.BaudRate = CBR_921600; break; -#endif - default: - // Try to blindly assign it - dcbSerialParams.BaudRate = baudrate_; - } - - // setup char len - if (bytesize_ == eightbits) - dcbSerialParams.ByteSize = 8; - else if (bytesize_ == sevenbits) - dcbSerialParams.ByteSize = 7; - else if (bytesize_ == sixbits) - dcbSerialParams.ByteSize = 6; - else if (bytesize_ == fivebits) - dcbSerialParams.ByteSize = 5; - else - throw invalid_argument ("invalid char len"); - - // setup stopbits - if (stopbits_ == stopbits_one) - dcbSerialParams.StopBits = ONESTOPBIT; - else if (stopbits_ == stopbits_one_point_five) - dcbSerialParams.StopBits = ONE5STOPBITS; - else if (stopbits_ == stopbits_two) - dcbSerialParams.StopBits = TWOSTOPBITS; - else - throw invalid_argument ("invalid stop bit"); - - // setup parity - if (parity_ == parity_none) { - dcbSerialParams.Parity = NOPARITY; - } else if (parity_ == parity_even) { - dcbSerialParams.Parity = EVENPARITY; - } else if (parity_ == parity_odd) { - dcbSerialParams.Parity = ODDPARITY; - } else if (parity_ == parity_mark) { - dcbSerialParams.Parity = MARKPARITY; - } else if (parity_ == parity_space) { - dcbSerialParams.Parity = SPACEPARITY; - } else { - throw invalid_argument ("invalid parity"); - } - - // setup flowcontrol - if (flowcontrol_ == flowcontrol_none) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - if (flowcontrol_ == flowcontrol_software) { - dcbSerialParams.fOutxCtsFlow = false; - dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE; - dcbSerialParams.fOutX = true; - dcbSerialParams.fInX = true; - } - if (flowcontrol_ == flowcontrol_hardware) { - dcbSerialParams.fOutxCtsFlow = true; - dcbSerialParams.fRtsControl = RTS_CONTROL_HANDSHAKE; - dcbSerialParams.fOutX = false; - dcbSerialParams.fInX = false; - } - - // activate settings - if (!SetCommState(fd_, &dcbSerialParams)){ - CloseHandle(fd_); - THROW (IOException, "Error setting serial port settings."); - } - - // Setup timeouts - COMMTIMEOUTS timeouts = {0}; - timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout; - timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant; - timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier; - timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant; - timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier; - if (!SetCommTimeouts(fd_, &timeouts)) { - THROW (IOException, "Error setting timeouts."); - } -} - -void -Serial::SerialImpl::close () -{ - if (is_open_ == true) { - if (fd_ != INVALID_HANDLE_VALUE) { - int ret; - ret = CloseHandle(fd_); - if (ret == 0) { - stringstream ss; - ss << "Error while closing serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } else { - fd_ = INVALID_HANDLE_VALUE; - } - } - is_open_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return is_open_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!is_open_) { - return 0; - } - COMSTAT cs; - if (!ClearCommError(fd_, NULL, &cs)) { - stringstream ss; - ss << "Error while checking status of the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return static_cast(cs.cbInQue); -} - -bool -Serial::SerialImpl::waitReadable (uint32_t /*timeout*/) -{ - THROW (IOException, "waitReadable is not implemented on Windows."); - return false; -} - -void -Serial::SerialImpl::waitByteTimes (size_t /*count*/) -{ - THROW (IOException, "waitByteTimes is not implemented on Windows."); -} - -size_t -Serial::SerialImpl::read (uint8_t *buf, size_t size) -{ - if (!is_open_) { - throw PortNotOpenedException ("Serial::read"); - } - DWORD bytes_read; - if (!ReadFile(fd_, buf, static_cast(size), &bytes_read, NULL)) { - stringstream ss; - ss << "Error while reading from the serial port: " << GetLastError(); - printf(ss.str().c_str()); - // THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_read); -} - -size_t -Serial::SerialImpl::write (const uint8_t *data, size_t length) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::write"); - } - DWORD bytes_written; - if (!WriteFile(fd_, data, static_cast(length), &bytes_written, NULL)) { - stringstream ss; - ss << "Error while writing to the serial port: " << GetLastError(); - THROW (IOException, ss.str().c_str()); - } - return (size_t) (bytes_written); -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = wstring(port.begin(), port.end()); -} - -string -Serial::SerialImpl::getPort () const -{ - return string(port_.begin(), port_.end()); -} - -void -Serial::SerialImpl::setTimeout (serial::Timeout &timeout) -{ - timeout_ = timeout; - if (is_open_) { - reconfigurePort (); - } -} - -serial::Timeout -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (is_open_) { - reconfigurePort (); - } -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (is_open_) { - reconfigurePort (); - } -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (is_open_) { - reconfigurePort (); - } -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (is_open_) { - reconfigurePort (); - } -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (is_open_) { - reconfigurePort (); - } -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::flush"); - } - FlushFileBuffers (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - if (is_open_ == false) { - throw PortNotOpenedException("Serial::flushInput"); - } - PurgeComm(fd_, PURGE_RXCLEAR); -} - -void -Serial::SerialImpl::flushOutput () -{ - if (is_open_ == false) { - throw PortNotOpenedException("Serial::flushOutput"); - } - PurgeComm(fd_, PURGE_TXCLEAR); -} - -void -Serial::SerialImpl::sendBreak (int /*duration*/) -{ - THROW (IOException, "sendBreak is not supported on Windows."); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setBreak"); - } - if (level) { - EscapeCommFunction (fd_, SETBREAK); - } else { - EscapeCommFunction (fd_, CLRBREAK); - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setRTS"); - } - if (level) { - EscapeCommFunction (fd_, SETRTS); - } else { - EscapeCommFunction (fd_, CLRRTS); - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::setDTR"); - } - if (level) { - EscapeCommFunction (fd_, SETDTR); - } else { - EscapeCommFunction (fd_, CLRDTR); - } -} - -bool -Serial::SerialImpl::waitForChange () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::waitForChange"); - } - DWORD dwCommEvent; - - if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { - // Error setting communications mask - return false; - } - - if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) { - // An error occurred waiting for the event. - return false; - } else { - // Event has occurred. - return true; - } -} - -bool -Serial::SerialImpl::getCTS () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCTS"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the CTS line."); - } - - return (MS_CTS_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getDSR () -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getDSR"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the DSR line."); - } - - return (MS_DSR_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getRI() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getRI"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - THROW (IOException, "Error getting the status of the RI line."); - } - - return (MS_RING_ON & dwModemStatus) != 0; -} - -bool -Serial::SerialImpl::getCD() -{ - if (is_open_ == false) { - throw PortNotOpenedException ("Serial::getCD"); - } - DWORD dwModemStatus; - if (!GetCommModemStatus(fd_, &dwModemStatus)) { - // Error in GetCommModemStatus; - THROW (IOException, "Error getting the status of the CD line."); - } - - return (MS_RLSD_ON & dwModemStatus) != 0; -} - -void -Serial::SerialImpl::readLock() -{ - if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming read mutex."); - } -} - -void -Serial::SerialImpl::readUnlock() -{ - if (!ReleaseMutex(read_mutex)) { - THROW (IOException, "Error releasing read mutex."); - } -} - -void -Serial::SerialImpl::writeLock() -{ - if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) { - THROW (IOException, "Error claiming write mutex."); - } -} - -void -Serial::SerialImpl::writeUnlock() -{ - if (!ReleaseMutex(write_mutex)) { - THROW (IOException, "Error releasing write mutex."); - } -} - -#endif // #if defined(_WIN32) - diff --git a/src/main/native/include/rev/Drivers/SerialPort/SerialDevice.h b/src/main/native/include/rev/Drivers/SerialPort/SerialDevice.h deleted file mode 100644 index a8c6447..0000000 --- a/src/main/native/include/rev/Drivers/SerialPort/SerialDevice.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -#include "rev/Drivers/SerialPort/SerialDeviceThread.h" -#include "rev/CANDevice.h" -#include "rev/CANMessage.h" -#include "rev/CANStatus.h" - -namespace rev { -namespace usb { - -class SerialDevice : public CANDevice { -public: - SerialDevice() =delete; - SerialDevice(std::string port); - virtual ~SerialDevice(); - - virtual std::string GetName() const override; - virtual std::string GetDescriptor() const override; - virtual int GetNumberOfErrors() override; - - virtual int GetId() const override; - - virtual CANStatus SendCANMessage(const CANMessage& msg, int periodMs) override; - virtual CANStatus ReceiveCANMessage(std::shared_ptr& msg, uint32_t messageID, uint32_t messageMask) override; - virtual CANStatus OpenStreamSession(uint32_t* sessionHandle, CANBridge_CANFilter filter, uint32_t maxSize) override; - virtual CANStatus CloseStreamSession(uint32_t sessionHandle) override; - virtual CANStatus ReadStreamSession(uint32_t sessionHandle, HAL_CANStreamMessage* msgs, uint32_t messagesToRead, uint32_t* messagesRead) override; - - virtual CANStatus GetCANDetailStatus(float* percentBusUtilization, uint32_t* busOff, uint32_t* txFull, uint32_t* receiveErr, uint32_t* transmitErr) override; - virtual CANStatus GetCANDetailStatus(float* percentBusUtilization, uint32_t* busOff, uint32_t* txFull, uint32_t* receiveErr, uint32_t* transmitErr, uint32_t* lastErrorTime) override; - - virtual bool IsConnected() override; - virtual bool CopyReceivedMessagesMap(std::map>& receivedMessagesMap) override; -private: - SerialDeviceThread m_thread; - std::string m_descriptor; - std::string m_name; -}; - -} // namespace usb -} // namespace rev diff --git a/src/main/native/include/rev/Drivers/SerialPort/SerialDeviceThread.h b/src/main/native/include/rev/Drivers/SerialPort/SerialDeviceThread.h deleted file mode 100644 index a85d97d..0000000 --- a/src/main/native/include/rev/Drivers/SerialPort/SerialDeviceThread.h +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -// TODO: remove me -#include -#include -#include -#include - -#include "rev/CANMessage.h" -#include "rev/CANBridgeUtils.h" -#include "rev/CANStatus.h" -#include "rev/Drivers/DriverDeviceThread.h" - -#include "SerialMessage.h" - -#include "serial/serial.h" - -#include -#include - -namespace rev { -namespace usb { - - -class SerialDeviceThread : public DriverDeviceThread { -public: - SerialDeviceThread() =delete; - SerialDeviceThread(std::string port, long long threadIntervalMs = 1) : DriverDeviceThread(0xa45b5597, threadIntervalMs) - { - serial::Timeout timeout = serial::Timeout::simpleTimeout(1); - m_device.setPort(port); - m_device.setBaudrate(115200); - m_device.setTimeout(timeout); - m_device.setBytesize(serial::bytesize_t::eightbits); - m_device.setParity(serial::parity_t::parity_even); - m_device.setStopbits(serial::stopbits_t::stopbits_one); - m_device.setFlowcontrol(serial::flowcontrol_t::flowcontrol_none); - - if (!m_device.isOpen()) { - m_device.open(); - } else { - std::cout << port << " already open" << std::endl; - } - - } - ~SerialDeviceThread() - { - m_device.close(); - } - - void Start() override { - if (m_thread.get() != nullptr && m_thread->joinable()) { - m_thread->join(); - } - m_thread = std::make_unique(&SerialDeviceThread::SerialRun, this); - } - - void OpenStream(uint32_t* handle, CANBridge_CANFilter filter, uint32_t maxSize, CANStatus *status) override { - { - std::lock_guard lock(m_streamMutex); - // Create the handle - *handle = m_counter++; - - // Add to the map - m_readStream[*handle] = std::unique_ptr(new CANStreamHandle{filter.messageId, filter.messageMask, maxSize, utils::CircularBuffer>{maxSize}}); - - } - // use drv status for serial port to identify - uint32_t msgId = 0x2051A80; - uint8_t dataBuffer[8] = {0}; - EnqueueMessage(rev::usb::CANMessage(msgId, dataBuffer, 0, 0), 0); - - *status = CANStatus::kOk; - } - -private: - serial::Serial m_device; - - static const size_t bufferSize = 12; - - void ReadMessages(bool &reading) { - uint8_t data[bufferSize] = {0}; // 12 bytes of data - try { - size_t bytesRead = m_device.read(data, bufferSize); - - if (bytesRead == bufferSize) { - - std::stringstream msgStream; - std::stringstream devStream; - uint32_t msgId; - uint32_t devId; - - // Gets the full message ID - msgStream << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)data[3] << std::setfill('0') << std::setw(2) - << std::hex << (int)data[2] << std::setfill('0') << std::setw(2) << std::hex << (int)data[1] - << std::setfill('0') << std::setw(2) << std::hex << (int)data[0]; - msgStream >> msgId; - - // Gets just the manufacturer and device type IDs - devStream << "0x" << std::setfill('0') << std::setw(2) << std::hex << (int)data[3] << std::setfill('0') << std::setw(2) - << std::hex << (int)data[2] << "0000"; - devStream >> devId; - - // Make sure message ID isn't empty - if (msgId != 0x0 ) { - uint8_t msgData[8]; - // Check if parameter access - if (IsLegacyGetParam(msgId)) { - memcpy(msgData, data+6, 6*sizeof(uint8_t)); - msgId = devId | ((CMD_API_PARAM_ACCESS | data[4]) << 6) | (msgId & 0x3F); - } else { - memcpy(msgData, data+4, 8*sizeof(uint8_t)); - } - - auto msg = std::make_shared(msgId, msgData, 8); - - { - std::lock_guard lock(m_readMutex); - if (msg->GetSize() != 0) { - m_readStore[msgId] = msg; - } - } - - { - std::lock_guard lock(m_streamMutex); - for (auto& stream : m_readStream) { - // Compare current size of the buffer to the max size of the buffer - if (!stream.second->messages.IsFull() - && rev::usb::CANBridge_ProcessMask({stream.second->messageId, stream.second->messageMask}, - msg->GetMessageId())) { - stream.second->messages.Add(msg); - } - } - } - - reading = false; - } - } else { - reading = false; - } - } catch(...) { - // std::cout << e.what() << std::endl; - m_threadStatus = CANStatus::kDeviceWriteError; - m_statusErrCount++; - } - } - - bool WriteMessages(detail::CANThreadSendQueueElement el, std::chrono::steady_clock::time_point now) { - uint32_t sentMsgId = el.m_msg.GetMessageId(); - uint16_t apiId = el.m_msg.GetApiId(); - - if (el.m_msg.GetDeviceType() == CANDeviceType::gearToothSensor) { - //Special message by motor controller to reboot into DFU - sentMsgId |= (1 << 29); - } - // std::cout << "serial write >> " << std::hex << sentMsgId << " Is API ID: " << std::hex << apiId << " Valid? " << (IsValidSerialMessageId(apiId) ? "Yes" : "No") << std::endl; - - - if ((el.m_intervalMs == 0 || now - el.m_prevTimestamp >= std::chrono::milliseconds(el.m_intervalMs)) && (IsValidSerialMessageId(apiId) || IsConfigParameter(apiId))) { - // Little endian - uint8_t idBuffer[4]; - uint8_t dataBuffer[8]; - - //std::cout << "serial write >> " << std::hex << sentMsgId << std::endl; - - idBuffer[0] = (sentMsgId & 0x000000ff); - idBuffer[2] = (sentMsgId & 0x00ff0000) >> 16; - idBuffer[3] = (sentMsgId & 0xff000000) >> 24; - - // Check to see if it's parameter access - if (IsConfigParameter(apiId)) { - uint32_t paramConfig; - // If the message has empty data, then it's getting parameter value. Otherwise setting parameter value - if (el.m_msg.IsEmpty()) { - paramConfig = GET_CONFIG_PARAM; - } else { - paramConfig = SET_CONFIG_PARAM; - } - - // Need to change the id to have the right parameter access value - idBuffer[0] = (paramConfig & 0x000000ff); - idBuffer[1] = (paramConfig & 0x0000ff00) >> 8; - - // Only 5-6 bytes of data for parameter access, leave first 2 spots free for id and buffer 0 - memcpy(dataBuffer + 2, el.m_msg.GetData(), sizeof(uint8_t)*6); - - // First data byte needs to be the parameter id, second one always needs to be a zero - dataBuffer[0] = CMD_API_PARAM_ACCESS | apiId; // needs to be the paramter id - dataBuffer[1] = 0; - - } else { - // If not parameter access, leave api ID as is - idBuffer[1] = (sentMsgId & 0x0000ff00) >> 8; - memcpy(dataBuffer, el.m_msg.GetData(), sizeof(uint8_t)*8); - } - - uint8_t buffer[bufferSize]; - std::copy(dataBuffer, dataBuffer + 8, std::copy(idBuffer, idBuffer + 4, buffer)); - - size_t bytesWritten = 0; - try { - bytesWritten = m_device.write(buffer, bufferSize); - } catch(...) { - m_threadStatus = CANStatus::kDeviceWriteError; - m_statusErrCount++; - } - - //TODO: figure out why this is sometimes neccessary on WIN32 to avoid recieving - //1 byte frames... Maybe reading the buffer when size = 1? - //Maybe on the read side call read with size 1 - //in a loop of 12 with an overall timeout? - std::this_thread::sleep_for(std::chrono::milliseconds(2)); - - // std::this_thread::sleep_for(std::chrono::milliseconds(500)); - if (bytesWritten != bufferSize) { - m_threadStatus = CANStatus::kDeviceWriteError; - m_statusErrCount++; - return false; - } else { - m_threadStatus = CANStatus::kOk; - return true; - // std::cout << "Message sent" << std::endl; - } - } - return false; - } - - void SerialRun() { - while (m_threadComplete == false) { - m_threadStatus = CANStatus::kOk; // Start each loop with the status being good. Really only a write issue. - auto sleepTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(m_threadIntervalMs); - - // Legacy serial port devices always do Write[12 bits] ... Read[12 bits] for every operation - bool doRead = false; - { - std::lock_guard lock(m_writeMutex); - if (m_sendQueue.size() > 0) { - detail::CANThreadSendQueueElement el = m_sendQueue.front(); - m_sendQueue.pop_front(); - if (el.m_intervalMs == -1) { - continue; - } - - auto now = std::chrono::steady_clock::now(); - - // Legacy serial driver skips a lot of unsupported messages, don't requeue - if (WriteMessages(el, now)) { - // Return to end of queue if repeated - if (el.m_intervalMs > 0 ) { - el.m_prevTimestamp = now; - - m_sendQueue.push_back(el); - } - doRead = true; - } - } - } - if (doRead) { - ReadMessages(doRead); - } - - // 3) Stall thread - if (m_sendQueue.size() == 0) { - std::this_thread::sleep_until(sleepTime); - } - } - } -}; - -} // namespace usb -} // namespace rev diff --git a/src/main/native/include/rev/Drivers/SerialPort/SerialDriver.h b/src/main/native/include/rev/Drivers/SerialPort/SerialDriver.h deleted file mode 100644 index dc6bf20..0000000 --- a/src/main/native/include/rev/Drivers/SerialPort/SerialDriver.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -#include "rev/CANDriver.h" - -namespace rev { -namespace usb { - -class SerialDriver : public CANDriver { -public: - SerialDriver() {} - virtual ~SerialDriver() override {} - - virtual std::string GetName() const override {return "Legacy";} - - virtual std::vector GetDevices() override; - virtual std::unique_ptr CreateDeviceFromDescriptor(const char* descriptor) override; -}; - -} // namespace usb -} // namespace rev diff --git a/src/main/native/include/rev/Drivers/SerialPort/SerialMessage.h b/src/main/native/include/rev/Drivers/SerialPort/SerialMessage.h deleted file mode 100644 index 90c404f..0000000 --- a/src/main/native/include/rev/Drivers/SerialPort/SerialMessage.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019 REV Robotics - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of REV Robotics nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#pragma once - -#include -#include - -const int CMD_API_PARAM_ACCESS = 0x300; -const int SET_CONFIG_PARAM = 0x02051C00; -const int GET_CONFIG_PARAM = 0x02051C40; - -bool IsValidSerialMessageId(uint16_t apiId); -bool IsConfigParameter(uint16_t apiId); -bool IsLegacyGetParam(uint32_t msgId); - diff --git a/src/main/native/include/serial/serial.h b/src/main/native/include/serial/serial.h deleted file mode 100644 index 46aa055..0000000 --- a/src/main/native/include/serial/serial.h +++ /dev/null @@ -1,775 +0,0 @@ -/*! - * \file serial/serial.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a cross platform interface for interacting with Serial Ports. - */ - -#ifndef SERIAL_H -#define SERIAL_H - -#include -#include -#include -#include -#include -#include -#include -#include "v8stdint.h" - -#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ -__LINE__, (message) ) - -namespace serial { - -/*! - * Enumeration defines the possible bytesizes for the serial port. - */ -typedef enum { - fivebits = 5, - sixbits = 6, - sevenbits = 7, - eightbits = 8 -} bytesize_t; - -/*! - * Enumeration defines the possible parity types for the serial port. - */ -typedef enum { - parity_none = 0, - parity_odd = 1, - parity_even = 2, - parity_mark = 3, - parity_space = 4 -} parity_t; - -/*! - * Enumeration defines the possible stopbit types for the serial port. - */ -typedef enum { - stopbits_one = 1, - stopbits_two = 2, - stopbits_one_point_five -} stopbits_t; - -/*! - * Enumeration defines the possible flowcontrol types for the serial port. - */ -typedef enum { - flowcontrol_none = 0, - flowcontrol_software, - flowcontrol_hardware -} flowcontrol_t; - -/*! - * Structure for setting the timeout of the serial port, times are - * in milliseconds. - * - * In order to disable the interbyte timeout, set it to Timeout::max(). - */ -struct Timeout { -#ifdef max -# undef max -#endif - static uint32_t max() {return std::numeric_limits::max();} - /*! - * Convenience function to generate Timeout structs using a - * single absolute timeout. - * - * \param timeout A long that defines the time in milliseconds until a - * timeout occurs after a call to read or write is made. - * - * \return Timeout struct that represents this simple timeout provided. - */ - static Timeout simpleTimeout(uint32_t timeout) { - return Timeout(max(), timeout, 0, timeout, 0); - } - - /*! Number of milliseconds between bytes received to timeout on. */ - uint32_t inter_byte_timeout; - /*! A constant number of milliseconds to wait after calling read. */ - uint32_t read_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling read. - */ - uint32_t read_timeout_multiplier; - /*! A constant number of milliseconds to wait after calling write. */ - uint32_t write_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling write. - */ - uint32_t write_timeout_multiplier; - - explicit Timeout (uint32_t inter_byte_timeout_=0, - uint32_t read_timeout_constant_=0, - uint32_t read_timeout_multiplier_=0, - uint32_t write_timeout_constant_=0, - uint32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} -}; - -/*! - * Class that provides a portable serial port interface. - */ -class Serial { -public: - /*! - * Creates a Serial object and opens the port if a port is specified, - * otherwise it remains closed until serial::Serial::open is called. - * - * \param port A std::string containing the address of the serial port, - * which would be something like 'COM1' on Windows and '/dev/ttyS0' - * on Linux. - * - * \param baudrate An unsigned 32-bit integer that represents the baudrate - * - * \param timeout A serial::Timeout struct that defines the timeout - * conditions for the serial port. \see serial::Timeout - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \param flowcontrol Type of flowcontrol used, default is - * flowcontrol_none, possible values are: flowcontrol_none, - * flowcontrol_software, flowcontrol_hardware - * - * \throw serial::PortNotOpenedException - * \throw serial::IOException - * \throw std::invalid_argument - */ - Serial (const std::string &port = "", - uint32_t baudrate = 9600, - Timeout timeout = Timeout(), - bytesize_t bytesize = eightbits, - parity_t parity = parity_none, - stopbits_t stopbits = stopbits_one, - flowcontrol_t flowcontrol = flowcontrol_none); - - /*! Destructor */ - virtual ~Serial (); - - /*! - * Opens the serial port as long as the port is set and the port isn't - * already open. - * - * If the port is provided to the constructor then an explicit call to open - * is not needed. - * - * \see Serial::Serial - * - * \throw std::invalid_argument - * \throw serial::SerialException - * \throw serial::IOException - */ - void - open (); - - /*! Gets the open status of the serial port. - * - * \return Returns true if the port is open, false otherwise. - */ - bool - isOpen () const; - - /*! Closes the serial port. */ - void - close (); - - /*! Return the number of characters in the buffer. */ - size_t - available (); - - /*! Block until there is serial data to read or read_timeout_constant - * number of milliseconds have elapsed. The return value is true when - * the function exits with the port in a readable state, false otherwise - * (due to timeout or select interruption). */ - bool - waitReadable (); - - /*! Block for a period of time corresponding to the transmission time of - * count characters at present serial settings. This may be used in con- - * junction with waitReadable to read larger blocks of data from the - * port. */ - void - waitByteTimes (size_t count); - - /*! Read a given amount of bytes from the serial port into a given buffer. - * - * The read function will return in one of three cases: - * * The number of requested bytes was read. - * * In this case the number of bytes requested will match the size_t - * returned by read. - * * A timeout occurred, in this case the number of bytes read will not - * match the amount requested, but no exception will be thrown. One of - * two possible timeouts occurred: - * * The inter byte timeout expired, this means that number of - * milliseconds elapsed between receiving bytes from the serial port - * exceeded the inter byte timeout. - * * The total timeout expired, which is calculated by multiplying the - * read timeout multiplier by the number of requested bytes and then - * added to the read timeout constant. If that total number of - * milliseconds elapses after the initial call to read a timeout will - * occur. - * * An exception occurred, in this case an actual exception will be thrown. - * - * \param buffer An uint8_t array of at least the requested size. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (uint8_t *buffer, size_t size); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::vector of uint8_t. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (std::vector &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port into a give buffer. - * - * \param buffer A reference to a std::string. - * \param size A size_t defining how many bytes to be read. - * - * \return A size_t representing the number of bytes read as a result of the - * call to read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - read (std::string &buffer, size_t size = 1); - - /*! Read a given amount of bytes from the serial port and return a string - * containing the data. - * - * \param size A size_t defining how many bytes to be read. - * - * \return A std::string containing the data read from the port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::string - read (size_t size = 1); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param buffer A std::string reference used to store the data. - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A size_t representing the number of bytes read. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - size_t - readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); - - /*! Reads in a line or until a given delimiter has been processed. - * - * Reads from the serial port until a single line has been read. - * - * \param size A maximum length of a line, defaults to 65536 (2^16) - * \param eol A string to match against for the EOL. - * - * \return A std::string containing the line. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::string - readline (size_t size = 65536, std::string eol = "\n"); - - /*! Reads in multiple lines until the serial port times out. - * - * This requires a timeout > 0 before it can be run. It will read until a - * timeout occurs and return a list of strings. - * - * \param size A maximum length of combined lines, defaults to 65536 (2^16) - * - * \param eol A string to match against for the EOL. - * - * \return A vector containing the lines. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - */ - std::vector - readlines (size_t size = 65536, std::string eol = "\n"); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \param size A size_t that indicates how many bytes should be written from - * the given data buffer. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const uint8_t *data, size_t size); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const std::vector &data); - - /*! Write a string to the serial port. - * - * \param data A const reference containing the data to be written - * to the serial port. - * - * \return A size_t representing the number of bytes actually written to - * the serial port. - * - * \throw serial::PortNotOpenedException - * \throw serial::SerialException - * \throw serial::IOException - */ - size_t - write (const std::string &data); - - /*! Sets the serial port identifier. - * - * \param port A const std::string reference containing the address of the - * serial port, which would be something like 'COM1' on Windows and - * '/dev/ttyS0' on Linux. - * - * \throw std::invalid_argument - */ - void - setPort (const std::string &port); - - /*! Gets the serial port identifier. - * - * \see Serial::setPort - * - * \throw std::invalid_argument - */ - std::string - getPort () const; - - /*! Sets the timeout for reads and writes using the Timeout struct. - * - * There are two timeout conditions described here: - * * The inter byte timeout: - * * The inter_byte_timeout component of serial::Timeout defines the - * maximum amount of time, in milliseconds, between receiving bytes on - * the serial port that can pass before a timeout occurs. Setting this - * to zero will prevent inter byte timeouts from occurring. - * * Total time timeout: - * * The constant and multiplier component of this timeout condition, - * for both read and write, are defined in serial::Timeout. This - * timeout occurs if the total time since the read or write call was - * made exceeds the specified time in milliseconds. - * * The limit is defined by multiplying the multiplier component by the - * number of requested bytes and adding that product to the constant - * component. In this way if you want a read call, for example, to - * timeout after exactly one second regardless of the number of bytes - * you asked for then set the read_timeout_constant component of - * serial::Timeout to 1000 and the read_timeout_multiplier to zero. - * This timeout condition can be used in conjunction with the inter - * byte timeout condition with out any problems, timeout will simply - * occur when one of the two timeout conditions is met. This allows - * users to have maximum control over the trade-off between - * responsiveness and efficiency. - * - * Read and write functions will return in one of three cases. When the - * reading or writing is complete, when a timeout occurs, or when an - * exception occurs. - * - * A timeout of 0 enables non-blocking mode. - * - * \param timeout A serial::Timeout struct containing the inter byte - * timeout, and the read and write timeout constants and multipliers. - * - * \see serial::Timeout - */ - void - setTimeout (Timeout &timeout); - - /*! Sets the timeout for reads and writes. */ - void - setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, - uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, - uint32_t write_timeout_multiplier) - { - Timeout timeout(inter_byte_timeout, read_timeout_constant, - read_timeout_multiplier, write_timeout_constant, - write_timeout_multiplier); - return setTimeout(timeout); - } - - /*! Gets the timeout for reads in seconds. - * - * \return A Timeout struct containing the inter_byte_timeout, and read - * and write timeout constants and multipliers. - * - * \see Serial::setTimeout - */ - Timeout - getTimeout () const; - - /*! Sets the baudrate for the serial port. - * - * Possible baudrates depends on the system but some safe baudrates include: - * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, - * 57600, 115200 - * Some other baudrates that are supported by some comports: - * 128000, 153600, 230400, 256000, 460800, 500000, 921600 - * - * \param baudrate An integer that sets the baud rate for the serial port. - * - * \throw std::invalid_argument - */ - void - setBaudrate (uint32_t baudrate); - - /*! Gets the baudrate for the serial port. - * - * \return An integer that sets the baud rate for the serial port. - * - * \see Serial::setBaudrate - * - * \throw std::invalid_argument - */ - uint32_t - getBaudrate () const; - - /*! Sets the bytesize for the serial port. - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \throw std::invalid_argument - */ - void - setBytesize (bytesize_t bytesize); - - /*! Gets the bytesize for the serial port. - * - * \see Serial::setBytesize - * - * \throw std::invalid_argument - */ - bytesize_t - getBytesize () const; - - /*! Sets the parity for the serial port. - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \throw std::invalid_argument - */ - void - setParity (parity_t parity); - - /*! Gets the parity for the serial port. - * - * \see Serial::setParity - * - * \throw std::invalid_argument - */ - parity_t - getParity () const; - - /*! Sets the stopbits for the serial port. - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \throw std::invalid_argument - */ - void - setStopbits (stopbits_t stopbits); - - /*! Gets the stopbits for the serial port. - * - * \see Serial::setStopbits - * - * \throw std::invalid_argument - */ - stopbits_t - getStopbits () const; - - /*! Sets the flow control for the serial port. - * - * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, - * possible values are: flowcontrol_none, flowcontrol_software, - * flowcontrol_hardware - * - * \throw std::invalid_argument - */ - void - setFlowcontrol (flowcontrol_t flowcontrol); - - /*! Gets the flow control for the serial port. - * - * \see Serial::setFlowcontrol - * - * \throw std::invalid_argument - */ - flowcontrol_t - getFlowcontrol () const; - - /*! Flush the input and output buffers */ - void - flush (); - - /*! Flush only the input buffer */ - void - flushInput (); - - /*! Flush only the output buffer */ - void - flushOutput (); - - /*! Sends the RS-232 break signal. See tcsendbreak(3). */ - void - sendBreak (int duration); - - /*! Set the break condition to a given level. Defaults to true. */ - void - setBreak (bool level = true); - - /*! Set the RTS handshaking line to the given level. Defaults to true. */ - void - setRTS (bool level = true); - - /*! Set the DTR handshaking line to the given level. Defaults to true. */ - void - setDTR (bool level = true); - - /*! - * Blocks until CTS, DSR, RI, CD changes or something interrupts it. - * - * Can throw an exception if an error occurs while waiting. - * You can check the status of CTS, DSR, RI, and CD once this returns. - * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a - * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a - * polling method is used which can give +-2ms. - * - * \return Returns true if one of the lines changed, false if something else - * occurred. - * - * \throw SerialException - */ - bool - waitForChange (); - - /*! Returns the current status of the CTS line. */ - bool - getCTS (); - - /*! Returns the current status of the DSR line. */ - bool - getDSR (); - - /*! Returns the current status of the RI line. */ - bool - getRI (); - - /*! Returns the current status of the CD line. */ - bool - getCD (); - -private: - // Disable copy constructors - Serial(const Serial&); - Serial& operator=(const Serial&); - - // Pimpl idiom, d_pointer - class SerialImpl; - SerialImpl *pimpl_; - - // Scoped Lock Classes - class ScopedReadLock; - class ScopedWriteLock; - - // Read common function - size_t - read_ (uint8_t *buffer, size_t size); - // Write common function - size_t - write_ (const uint8_t *data, size_t length); - -}; - -class SerialException : public std::exception -{ - // Disable copy constructors - SerialException& operator=(const SerialException&); - std::string e_what_; -public: - SerialException (const char *description) { - std::stringstream ss; - ss << "SerialException " << description << " failed."; - e_what_ = ss.str(); - } - SerialException (const SerialException& other) : e_what_(other.e_what_) {} - virtual ~SerialException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class IOException : public std::exception -{ - // Disable copy constructors - IOException& operator=(const IOException&); - std::string file_; - int line_; - std::string e_what_; - int errno_; -public: - explicit IOException (std::string file, int line, int errnum) - : file_(file), line_(line), errno_(errnum) { - std::stringstream ss; -#if defined(_WIN32) && !defined(__MINGW32__) - char error_str [1024]; - strerror_s(error_str, 1024, errnum); -#else - char * error_str = strerror(errnum); -#endif - ss << "IO Exception (" << errno_ << "): " << error_str; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - explicit IOException (std::string file, int line, const char * description) - : file_(file), line_(line), errno_(0) { - std::stringstream ss; - ss << "IO Exception: " << description; - ss << ", file " << file_ << ", line " << line_ << "."; - e_what_ = ss.str(); - } - virtual ~IOException() throw() {} - IOException (const IOException& other) : line_(other.line_), e_what_(other.e_what_), errno_(other.errno_) {} - - int getErrorNumber () const { return errno_; } - - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -class PortNotOpenedException : public std::exception -{ - // Disable copy constructors - const PortNotOpenedException& operator=(PortNotOpenedException); - std::string e_what_; -public: - PortNotOpenedException (const char * description) { - std::stringstream ss; - ss << "PortNotOpenedException " << description << " failed."; - e_what_ = ss.str(); - } - PortNotOpenedException (const PortNotOpenedException& other) : e_what_(other.e_what_) {} - virtual ~PortNotOpenedException() throw() {} - virtual const char* what () const throw () { - return e_what_.c_str(); - } -}; - -/*! - * Structure that describes a serial device. - */ -struct PortInfo { - - /*! Address of the serial port (this can be passed to the constructor of Serial). */ - std::string port; - - /*! Human readable description of serial device if available. */ - std::string description; - - /*! Hardware ID (e.g. VID:PID of USB serial devices) or "n/a" if not available. */ - std::string hardware_id; - -}; - -/* Lists the serial ports available on the system - * - * Returns a vector of available serial ports, each represented - * by a serial::PortInfo data structure: - * - * \return vector of serial::PortInfo. - */ -std::vector -list_ports(); - -} // namespace serial - -#endif diff --git a/src/main/native/include/serial/unix.h b/src/main/native/include/serial/unix.h deleted file mode 100644 index f1c461f..0000000 --- a/src/main/native/include/serial/unix.h +++ /dev/null @@ -1,221 +0,0 @@ -/*! - * \file serial/impl/unix.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a unix based pimpl for the Serial class. This implementation is - * based off termios.h and uses select for multiplexing the IO ports. - * - */ - -#if !defined(_WIN32) - -#ifndef SERIAL_UNIX_H -#define SERIAL_UNIX_H - -#include "serial.h" - -#include - -namespace serial { - -using std::size_t; -using std::string; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class MillisecondTimer { -public: - MillisecondTimer(const uint32_t millis); - int64_t remaining(); - -private: - static timespec timespec_now(); - timespec expiry; -}; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - bool - waitReadable (uint32_t timeout); - - void - waitByteTimes (size_t count); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - string port_; // Path to the file descriptor - int fd_; // The current file descriptor - - bool is_open_; - bool xonxoff_; - bool rtscts_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - uint32_t byte_time_ns_; // Nanoseconds to transmit/receive a single byte - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - pthread_mutex_t read_mutex; - // Mutex used to lock the write functions - pthread_mutex_t write_mutex; -}; - -} - -#endif // SERIAL_IMPL_UNIX_H - -#endif // !defined(_WIN32) diff --git a/src/main/native/include/serial/v8stdint.h b/src/main/native/include/serial/v8stdint.h deleted file mode 100644 index f3be96b..0000000 --- a/src/main/native/include/serial/v8stdint.h +++ /dev/null @@ -1,57 +0,0 @@ -// This header is from the v8 google project: -// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h - -// Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Load definitions of standard types. - -#ifndef V8STDINT_H_ -#define V8STDINT_H_ - -#include -#include - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include - -#endif - -#endif // V8STDINT_H_ diff --git a/src/main/native/include/serial/win.h b/src/main/native/include/serial/win.h deleted file mode 100644 index f4ac21c..0000000 --- a/src/main/native/include/serial/win.h +++ /dev/null @@ -1,207 +0,0 @@ -/*! - * \file serial/impl/windows.h - * \author William Woodall - * \author John Harrison - * \version 0.1 - * - * \section LICENSE - * - * The MIT License - * - * Copyright (c) 2012 William Woodall, John Harrison - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * \section DESCRIPTION - * - * This provides a windows implementation of the Serial class interface. - * - */ - -#if defined(_WIN32) - -#ifndef SERIAL_WINDOWS_H -#define SERIAL_WINDOWS_H - -#include "serial.h" - -#include "windows.h" - -namespace serial { - -using std::string; -using std::wstring; -using std::invalid_argument; - -using serial::SerialException; -using serial::IOException; - -class serial::Serial::SerialImpl { -public: - SerialImpl (const string &port, - unsigned long baudrate, - bytesize_t bytesize, - parity_t parity, - stopbits_t stopbits, - flowcontrol_t flowcontrol); - - virtual ~SerialImpl (); - - void - open (); - - void - close (); - - bool - isOpen () const; - - size_t - available (); - - bool - waitReadable (uint32_t timeout); - - void - waitByteTimes (size_t count); - - size_t - read (uint8_t *buf, size_t size = 1); - - size_t - write (const uint8_t *data, size_t length); - - void - flush (); - - void - flushInput (); - - void - flushOutput (); - - void - sendBreak (int duration); - - void - setBreak (bool level); - - void - setRTS (bool level); - - void - setDTR (bool level); - - bool - waitForChange (); - - bool - getCTS (); - - bool - getDSR (); - - bool - getRI (); - - bool - getCD (); - - void - setPort (const string &port); - - string - getPort () const; - - void - setTimeout (Timeout &timeout); - - Timeout - getTimeout () const; - - void - setBaudrate (unsigned long baudrate); - - unsigned long - getBaudrate () const; - - void - setBytesize (bytesize_t bytesize); - - bytesize_t - getBytesize () const; - - void - setParity (parity_t parity); - - parity_t - getParity () const; - - void - setStopbits (stopbits_t stopbits); - - stopbits_t - getStopbits () const; - - void - setFlowcontrol (flowcontrol_t flowcontrol); - - flowcontrol_t - getFlowcontrol () const; - - void - readLock (); - - void - readUnlock (); - - void - writeLock (); - - void - writeUnlock (); - -protected: - void reconfigurePort (); - -private: - wstring port_; // Path to the file descriptor - HANDLE fd_; - - bool is_open_; - - Timeout timeout_; // Timeout for read operations - unsigned long baudrate_; // Baudrate - - parity_t parity_; // Parity - bytesize_t bytesize_; // Size of the bytes - stopbits_t stopbits_; // Stop Bits - flowcontrol_t flowcontrol_; // Flow Control - - // Mutex used to lock the read functions - HANDLE read_mutex; - // Mutex used to lock the write functions - HANDLE write_mutex; -}; - -} - -#endif // SERIAL_IMPL_WINDOWS_H - -#endif // if defined(_WIN32)