diff --git a/src/Input/FGHIDEventInput.cxx b/src/Input/FGHIDEventInput.cxx index 929ad1541..0e8d088a9 100644 --- a/src/Input/FGHIDEventInput.cxx +++ b/src/Input/FGHIDEventInput.cxx @@ -538,22 +538,6 @@ void FGHIDDevice::update(double dt) _dirtyReports.clear(); } -void writeBits(uint8_t* bytes, size_t bitOffset, size_t bitSize, int value) -{ - size_t wholeBytesToSkip = bitOffset >> 3; - uint8_t* dataByte = bytes + wholeBytesToSkip; - size_t offsetInByte = bitOffset & 0x7; - size_t bitsInByte = std::min(bitSize, 8 - offsetInByte); - uint8_t mask = 0xff >> (8 - bitsInByte); - - *dataByte |= ((value & mask) << offsetInByte); - - if (bitsInByte < bitSize) { - // if we have more bits to write, recurse - writeBits(bytes, bitOffset + bitsInByte, bitSize - bitsInByte, value >> bitsInByte); - } -} - void FGHIDDevice::sendReport(Report* report) const { if (!_device) { @@ -585,33 +569,6 @@ void FGHIDDevice::sendReport(Report* report) const } } -int extractBits(uint8_t* bytes, size_t lengthInBytes, size_t bitOffset, size_t bitSize) -{ - const size_t wholeBytesToSkip = bitOffset >> 3; - const size_t offsetInByte = bitOffset & 0x7; - - // work out how many whole bytes to copy - const size_t bytesToCopy = std::min(sizeof(uint32_t), (offsetInByte + bitSize + 7) / 8); - uint32_t v = 0; - // this goes from byte alignment to word alignment safely - memcpy((void*) &v, bytes + wholeBytesToSkip, bytesToCopy); - - // shift down so lowest bit is aligned - v = v >> offsetInByte; - - // mask off any extraneous top bits - const uint32_t mask = ~(0xffffffff << bitSize); - v &= mask; - - return v; -} - -int signExtend(int inValue, size_t bitSize) -{ - const int m = 1U << (bitSize - 1); - return (inValue ^ m) - m; -} - int FGHIDDevice::maybeSignExtend(Item* item, int inValue) { return item->doSignExtend ? signExtend(inValue, item->bitSize) : inValue; @@ -701,6 +658,50 @@ void FGHIDDevice::Send(const char *eventName, double value) } // of anonymous namespace + +int extractBits(uint8_t* bytes, size_t lengthInBytes, size_t bitOffset, size_t bitSize) +{ + const size_t wholeBytesToSkip = bitOffset >> 3; + const size_t offsetInByte = bitOffset & 0x7; + + // work out how many whole bytes to copy + const size_t bytesToCopy = std::min(sizeof(uint32_t), (offsetInByte + bitSize + 7) / 8); + uint32_t v = 0; + // this goes from byte alignment to word alignment safely + memcpy((void*) &v, bytes + wholeBytesToSkip, bytesToCopy); + + // shift down so lowest bit is aligned + v = v >> offsetInByte; + + // mask off any extraneous top bits + const uint32_t mask = ~(0xffffffff << bitSize); + v &= mask; + + return v; +} + +int signExtend(int inValue, size_t bitSize) +{ + const int m = 1U << (bitSize - 1); + return (inValue ^ m) - m; +} + +void writeBits(uint8_t* bytes, size_t bitOffset, size_t bitSize, int value) +{ + size_t wholeBytesToSkip = bitOffset >> 3; + uint8_t* dataByte = bytes + wholeBytesToSkip; + size_t offsetInByte = bitOffset & 0x7; + size_t bitsInByte = std::min(bitSize, 8 - offsetInByte); + uint8_t mask = 0xff >> (8 - bitsInByte); + + *dataByte |= ((value & mask) << offsetInByte); + + if (bitsInByte < bitSize) { + // if we have more bits to write, recurse + writeBits(bytes, bitOffset + bitsInByte, bitSize - bitsInByte, value >> bitsInByte); + } +} + FGHIDEventInput::FGHIDEventInput() : FGEventInput(), d(new FGHIDEventInputPrivate) diff --git a/src/Input/FGHIDEventInput.hxx b/src/Input/FGHIDEventInput.hxx index 8d755619e..182e648f2 100644 --- a/src/Input/FGHIDEventInput.hxx +++ b/src/Input/FGHIDEventInput.hxx @@ -27,6 +27,12 @@ #include "FGEventInput.hxx" + +int extractBits(uint8_t* bytes, size_t lengthInBytes, size_t bitOffset, size_t bitSize); +int signExtend(int inValue, size_t bitSize); +void writeBits(uint8_t* bytes, size_t bitOffset, size_t bitSize, int value); + + class FGHIDEventInput : public FGEventInput { public: FGHIDEventInput(); diff --git a/test_suite/CMakeLists.txt b/test_suite/CMakeLists.txt index e9b73b336..2a936f298 100644 --- a/test_suite/CMakeLists.txt +++ b/test_suite/CMakeLists.txt @@ -71,6 +71,9 @@ add_test(AddonManagementUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest add_test(AeroElementUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u AeroElementTests) add_test(AutosaveMigrationUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u AutosaveMigrationTests) add_test(FlightplanUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u FlightplanTests) +if(ENABLE_HID_INPUT) + add_test(HIDInputUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u HIDInputTests) +endif() add_test(LaRCSimMatrixUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u LaRCSimMatrixTests) add_test(MktimeUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u MktimeTests) add_test(NasalSysUnitTests ${TESTSUITE_OUTPUT_DIR}/run_test_suite --ctest -u NasalSysTests) diff --git a/test_suite/unit_tests/CMakeLists.txt b/test_suite/unit_tests/CMakeLists.txt index f418a519b..8d2958847 100644 --- a/test_suite/unit_tests/CMakeLists.txt +++ b/test_suite/unit_tests/CMakeLists.txt @@ -3,6 +3,7 @@ foreach( unit_test_category Add-ons general FDM + Input Main Navaids Scripting diff --git a/test_suite/unit_tests/Input/CMakeLists.txt b/test_suite/unit_tests/Input/CMakeLists.txt new file mode 100644 index 000000000..68b79a534 --- /dev/null +++ b/test_suite/unit_tests/Input/CMakeLists.txt @@ -0,0 +1,17 @@ +if(ENABLE_HID_INPUT) + set(HID_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/test_hidinput.cxx) + set(HID_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/test_hidinput.hxx) +endif() + +set(TESTSUITE_SOURCES + ${TESTSUITE_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/TestSuite.cxx + ${HID_SOURCE} + PARENT_SCOPE +) + +set(TESTSUITE_HEADERS + ${TESTSUITE_HEADERS} + ${HID_HEADER} + PARENT_SCOPE +) diff --git a/test_suite/unit_tests/Input/TestSuite.cxx b/test_suite/unit_tests/Input/TestSuite.cxx new file mode 100644 index 000000000..611326ec6 --- /dev/null +++ b/test_suite/unit_tests/Input/TestSuite.cxx @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Edward d'Auvergne + * + * This file is part of the program FlightGear. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "test_hidinput.hxx" + + +// Set up the unit tests. +#ifdef ENABLE_HID_INPUT + CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(HIDInputTests, "Unit tests"); +#endif diff --git a/src/Input/test_hidinput.cxx b/test_suite/unit_tests/Input/test_hidinput.cxx similarity index 56% rename from src/Input/test_hidinput.cxx rename to test_suite/unit_tests/Input/test_hidinput.cxx index 978157f63..2a586844e 100644 --- a/src/Input/test_hidinput.cxx +++ b/test_suite/unit_tests/Input/test_hidinput.cxx @@ -18,33 +18,35 @@ #include "config.h" +#include "test_hidinput.hxx" + #include "test_suite/helpers/globals.hxx" #include -#include "FGHIDEventInput.cxx" +#include -void testValueExtract() +void HIDInputTests::testValueExtract() { uint8_t testDataFromSpec[4] = {0, 0xf4, 0x1 | (0x7 << 2), 0x03}; - SG_VERIFY(extractBits(testDataFromSpec, 4, 8, 10) == 500); - SG_VERIFY(extractBits(testDataFromSpec, 4, 18, 10) == 199); + CPPUNIT_ASSERT(extractBits(testDataFromSpec, 4, 8, 10) == 500); + CPPUNIT_ASSERT(extractBits(testDataFromSpec, 4, 18, 10) == 199); uint8_t testData2[4] = {0x01 << 6 | 0x0f, 0x17 | (1 << 6), 0x3 | (0x11 << 2), 0x3d | (1 << 6) }; - SG_VERIFY(extractBits(testData2, 4, 0, 6) == 15); - SG_VERIFY(extractBits(testData2, 4, 6, 12) == 3421); - SG_VERIFY(extractBits(testData2, 4, 18, 12) == 3921); - SG_VERIFY(extractBits(testData2, 4, 30, 1) == 1); - SG_VERIFY(extractBits(testData2, 4, 31, 1) == 0); + CPPUNIT_ASSERT(extractBits(testData2, 4, 0, 6) == 15); + CPPUNIT_ASSERT(extractBits(testData2, 4, 6, 12) == 3421); + CPPUNIT_ASSERT(extractBits(testData2, 4, 18, 12) == 3921); + CPPUNIT_ASSERT(extractBits(testData2, 4, 30, 1) == 1); + CPPUNIT_ASSERT(extractBits(testData2, 4, 31, 1) == 0); } // void writeBits(uint8_t* bytes, size_t bitOffset, size_t bitSize, int value) -void testValueInsert() +void HIDInputTests::testValueInsert() { uint8_t buf[8]; memset(buf, 0, 8); @@ -54,27 +56,18 @@ void testValueInsert() writeBits(buf, 6, 12, a); writeBits(buf, 18, 12, b); - SG_VERIFY(buf[0] == 0x40); - SG_VERIFY(buf[1] == 0x57); - SG_VERIFY(buf[2] == (0x03 | 0x44)); - SG_VERIFY(buf[3] == 0x3d); + CPPUNIT_ASSERT(buf[0] == 0x40); + CPPUNIT_ASSERT(buf[1] == 0x57); + CPPUNIT_ASSERT(buf[2] == (0x03 | 0x44)); + CPPUNIT_ASSERT(buf[3] == 0x3d); } -void testSignExtension() +void HIDInputTests::testSignExtension() { - SG_VERIFY(signExtend(0x80, 8) == -128); - SG_VERIFY(signExtend(0xff, 8) == -1); - SG_VERIFY(signExtend(0x7f, 8) == 127); + CPPUNIT_ASSERT(signExtend(0x80, 8) == -128); + CPPUNIT_ASSERT(signExtend(0xff, 8) == -1); + CPPUNIT_ASSERT(signExtend(0x7f, 8) == 127); - SG_VERIFY(signExtend(0x831, 12) == -1999); - SG_VERIFY(signExtend(0x7dd, 12) == 2013); -} - -int main(int argc, char* argv[]) -{ - testValueExtract(); - testValueInsert(); - testSignExtension(); - - return EXIT_SUCCESS; + CPPUNIT_ASSERT(signExtend(0x831, 12) == -1999); + CPPUNIT_ASSERT(signExtend(0x7dd, 12) == 2013); } diff --git a/test_suite/unit_tests/Input/test_hidinput.hxx b/test_suite/unit_tests/Input/test_hidinput.hxx new file mode 100644 index 000000000..4e60f5b20 --- /dev/null +++ b/test_suite/unit_tests/Input/test_hidinput.hxx @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 Edward d'Auvergne + * + * This file is part of the program FlightGear. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef _FG_HIDINPUT_UNIT_TESTS_HXX +#define _FG_HIDINPUT_UNIT_TESTS_HXX + + +#include +#include + + +// The unit tests. +class HIDInputTests : public CppUnit::TestFixture +{ + // Set up the test suite. + CPPUNIT_TEST_SUITE(HIDInputTests); + CPPUNIT_TEST(testValueExtract); + CPPUNIT_TEST(testValueInsert); + CPPUNIT_TEST(testSignExtension); + CPPUNIT_TEST_SUITE_END(); + +public: + // Set up function for each test. + void setUp() {} + + // Clean up after each test. + void tearDown() {} + + // The tests. + void testValueExtract(); + void testValueInsert(); + void testSignExtension(); +}; + +#endif // _FG_HIDINPUT_UNIT_TESTS_HXX