diff --git a/core/driver/sockcanpp/CanDriver.cpp b/core/driver/sockcanpp/CanDriver.cpp deleted file mode 100644 index f5cfb64..0000000 --- a/core/driver/sockcanpp/CanDriver.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/** - * @file CanDriver.cpp - * @author Simon Cahill (simonc@online.de) - * @brief - * @version 0.1 - * @date 2020-07-01 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -////////////////////////////// -// SYSTEM INCLUDES // -////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -////////////////////////////// -// LOCAL INCLUDES // -////////////////////////////// -#include "CanDriver.hpp" -#include "CanId.hpp" -#include "CanMessage.hpp" -#include "exceptions/CanCloseException.hpp" -#include "exceptions/CanException.hpp" -#include "exceptions/CanInitException.hpp" -#include "exceptions/InvalidSocketException.hpp" - -namespace sockcanpp { - -using exceptions::CanCloseException; -using exceptions::CanException; -using exceptions::CanInitException; -using exceptions::InvalidSocketException; - -using std::mutex; -using std::queue; -using std::string; -using std::strncpy; -using std::unique_lock; -using std::chrono::milliseconds; -using std::this_thread::sleep_for; - -////////////////////////////////////// -// PUBLIC IMPLEMENTATION // -////////////////////////////////////// - -const int32_t CanDriver::CAN_MAX_DATA_LENGTH = 8; -const int32_t CanDriver::CAN_SOCK_RAW = CAN_RAW; -const int32_t CanDriver::CAN_SOCK_SEVEN = 7; - -CanDriver::CanDriver(string canInterface, int32_t canProtocol, const CanId defaultSenderId) - : CanDriver(canInterface, canProtocol, 0 /* match all */, defaultSenderId) {} - -CanDriver::CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId) - : _defaultSenderId(defaultSenderId), _canProtocol(canProtocol), _canInterface(canInterface), _canFilterMask(filterMask), _socketFd(-1) { - initialiseSocketCan(); -} - -/** - * @brief Blocks until one or more CAN messages appear on the bus, or until the - * timeout runs out. - * - * @param timeout The time (in millis) to wait before timing out. - * - * @return true If messages are available on the bus. - * @return false Otherwise. - */ -bool CanDriver::waitForMessages(milliseconds timeout) { - if (_socketFd < 0) { - throw InvalidSocketException("Invalid socket!", _socketFd); - } - - unique_lock locky(_lock); - - fd_set readFileDescriptors; - timeval waitTime; - waitTime.tv_sec = timeout.count() / 1000; - waitTime.tv_usec = timeout.count() * 1000; - - FD_ZERO(&readFileDescriptors); - FD_SET(_socketFd, &readFileDescriptors); - _queueSize = select(_socketFd + 1, &readFileDescriptors, 0, 0, &waitTime); - - return _queueSize > 0; -} - -/** - * @brief Attempts to read a message from the associated CAN bus. - * - * @return CanMessage The message read from the bus. - */ -CanMessage CanDriver::readMessage() { return readMessageLock(); } - -/** - * @brief readMessage deadlock guard, attempts to read a message from the - * associated CAN bus. - * - * @return CanMessage The message read from the bus. - */ -CanMessage CanDriver::readMessageLock(bool const lock) { - std::unique_ptr> _lockLck{nullptr}; - if (lock) _lockLck = std::unique_ptr>{new std::unique_lock{_lock}}; - if (0 > _socketFd) throw InvalidSocketException("Invalid socket!", _socketFd); - int32_t readBytes{0}; - can_frame canFrame; - memset(&canFrame, 0, sizeof(can_frame)); - readBytes = read(_socketFd, &canFrame, sizeof(can_frame)); - if (0 > readBytes) throw CanException(formatString("FAILED to read from CAN! Error: %d => %s", errno, strerror(errno)), _socketFd); - return CanMessage{canFrame}; -} - -/** - * @brief Attempts to send a CAN message on the associated bus. - * - * @param message The message to be sent. - * @param forceExtended Whether or not to force use of an extended ID. - * - * @return int32_t The amount of bytes sent on the bus. - */ -int32_t CanDriver::sendMessage(const CanMessage message, bool forceExtended) { - if (_socketFd < 0) { - throw InvalidSocketException("Invalid socket!", _socketFd); - } - - unique_lock locky(_lock); - - int32_t bytesWritten = 0; - - if (message.getFrameData().size() > CAN_MAX_DATA_LENGTH) { - throw CanException(formatString("INVALID data length! Message must be smaller than %d bytes!", CAN_MAX_DATA_LENGTH), _socketFd); - } - - auto canFrame = message.getRawFrame(); - - if (forceExtended || (message.getCanId() > CAN_SFF_MASK)) { - canFrame.can_id |= CAN_EFF_FLAG; - } - - bytesWritten = write(_socketFd, (const void *)&canFrame, sizeof(canFrame)); - - if (bytesWritten == -1) { - throw CanException(formatString("FAILED to write data to socket! Error: %d => %s", errno, strerror(errno)), _socketFd); - } - - return bytesWritten; -} - -/** - * @brief Attempts to send a queue of messages on the associated CAN bus. - * - * @param messages A queue containing the messages to be sent. - * @param delay If greater than 0, will delay the sending of the next message. - * @param forceExtended Whether or not to force use of an extended ID. - * - * @return int32_t The total amount of bytes sent. - */ -int32_t CanDriver::sendMessageQueue(queue messages, milliseconds delay, bool forceExtended) { - if (_socketFd < 0) { - throw InvalidSocketException("Invalid socket!", _socketFd); - } - - int32_t totalBytesWritten = 0; - - while (!messages.empty()) { - totalBytesWritten += sendMessage(messages.front(), forceExtended); - messages.pop(); - } - - return totalBytesWritten; -} - -/** - * @brief Attempts to read all messages stored in the buffer for the associated - * CAN bus. - * - * @return queue A queue containing the messages read from the bus - * buffer. - */ -queue CanDriver::readQueuedMessages() { - if (_socketFd < 0) throw InvalidSocketException("Invalid socket!", _socketFd); - unique_lock locky(_lock); - queue messages; - for (int32_t i = _queueSize; 0 < i; --i) messages.emplace(readMessageLock(false)); - return messages; -} - -/** - * @brief Attempts to set the filter mask for the associated CAN bus. - * - * @param mask The bit mask to apply. - */ -void CanDriver::setCanFilterMask(const int32_t mask) { - if (_socketFd < 0) { - throw InvalidSocketException("Invalid socket!", _socketFd); - } - - unique_lock locky(_lock); - can_filter canFilter; - - canFilter.can_id = _defaultSenderId; - canFilter.can_mask = mask; - - if (setsockopt(_socketFd, SOL_CAN_RAW, CAN_RAW_FILTER, &canFilter, sizeof(canFilter)) == -1) { - throw CanInitException(formatString("FAILED to set CAN filter mask %x on socket %d! Error: %d => %s", mask, _socketFd, errno, strerror(errno))); - } - - _canFilterMask = mask; -} - -////////////////////////////////////// -// PROTECTED IMPLEMENTATION // -////////////////////////////////////// - -/** - * @brief Initialises the underlying CAN socket. - */ -void CanDriver::initialiseSocketCan() { - // unique_lock locky(_lock); - - struct sockaddr_can address; - struct ifreq ifaceRequest; - int64_t fdOptions = 0; - int32_t tmpReturn; - - memset(&address, 0, sizeof(sizeof(struct sockaddr_can))); - memset(&ifaceRequest, 0, sizeof(sizeof(struct ifreq))); - - _socketFd = socket(PF_CAN, SOCK_RAW, _canProtocol); - - if (_socketFd == -1) { - throw CanInitException(formatString("FAILED to initialise socketcan! Error: %d => %s", errno, strerror(errno))); - } - - strcpy(ifaceRequest.ifr_name, _canInterface.c_str()); - - if ((tmpReturn = ioctl(_socketFd, SIOCGIFINDEX, &ifaceRequest)) == -1) { - throw CanInitException(formatString("FAILED to perform IO control operation on socket %s! Error: %d => %s", _canInterface.c_str(), errno, strerror(errno))); - } - - fdOptions = fcntl(_socketFd, F_GETFL); - fdOptions |= O_NONBLOCK; - tmpReturn = fcntl(_socketFd, F_SETFL, fdOptions); - - address.can_family = AF_CAN; - address.can_ifindex = ifaceRequest.ifr_ifindex; - - setCanFilterMask(_canFilterMask); - - if ((tmpReturn = bind(_socketFd, (struct sockaddr *)&address, sizeof(address))) == -1) { - throw CanInitException(formatString("FAILED to bind to socket CAN! Error: %d => %s", errno, strerror(errno))); - } -} - -/** - * @brief Closes the underlying CAN socket. - */ -void CanDriver::uninitialiseSocketCan() { - unique_lock locky(_lock); - - if (_socketFd <= 0) { - throw CanCloseException("Cannot close invalid socket!"); - } - - if (close(_socketFd) == -1) { - throw CanCloseException(formatString("FAILED to close CAN socket! Error: %d => %s", errno, strerror(errno))); - } - - _socketFd = -1; -} - -} // namespace sockcanpp diff --git a/core/driver/sockcanpp/CanDriver.hpp b/core/driver/sockcanpp/CanDriver.hpp deleted file mode 100644 index ec73ab1..0000000 --- a/core/driver/sockcanpp/CanDriver.hpp +++ /dev/null @@ -1,154 +0,0 @@ -/** - * @file CanDriver.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the declarations for the SocketCAN wrapper in C++. - * @version 0.1 - * @date 2020-07-01 - * - * @copyright Copyright (c) 2020 - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP -#define LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP - -////////////////////////////// -// SYSTEM INCLUDES // -////////////////////////////// -#include -#include -#include -#include - -////////////////////////////// -// LOCAL INCLUDES // -////////////////////////////// -#include "CanId.hpp" -#include "CanMessage.hpp" - -/** - * @brief Main library namespace. - * - * This namespace contains the library's main code. - */ -namespace sockcanpp { - -using std::mutex; -using std::queue; -using std::string; -using std::chrono::milliseconds; - -/** - * @brief CanDriver class; handles communication via CAN. - * - * This class provides the means of easily communicating with other devices via - * CAN in C++. - * - * @remarks - * This class may be inherited by other applications and modified to suit your - * needs. - */ -class CanDriver { - public: // +++ Static +++ - static const int32_t CAN_MAX_DATA_LENGTH; ///!< The maximum amount of bytes - /// allowed in a single CAN frame - static const int32_t CAN_SOCK_RAW; ///!< The raw CAN protocol - static const int32_t CAN_SOCK_SEVEN; ///!< A separate CAN protocol, used by - /// certain embedded device OEMs. - - public: // +++ Constructor / Destructor +++ - CanDriver(const string canInterface, const int32_t canProtocol, - const CanId defaultSenderId = 0); ///!< Constructor - CanDriver(const string canInterface, const int32_t canProtocol, const int32_t filterMask, const CanId defaultSenderId = 0); - CanDriver() {} - virtual ~CanDriver() { uninitialiseSocketCan(); } ///!< Destructor - - public: // +++ Getter / Setter +++ - CanDriver &setDefaultSenderId(const CanId id) { - this->_defaultSenderId = id; - return *this; - } ///!< Sets the default sender ID - - const CanId getDefaultSenderId() const { return this->_defaultSenderId; } ///!< Gets the default sender ID - - const int32_t getFilterMask() const { return this->_canFilterMask; } ///!< Gets the filter mask used by this instance - const int32_t getMessageQueueSize() const { - return this->_queueSize; - } ///!< Gets the amount of CAN messages found after last calling - /// waitForMessages() - const int32_t getSocketFd() const { return this->_socketFd; } ///!< The socket file descriptor used by this instance. - - public: // +++ I/O +++ - virtual bool waitForMessages(milliseconds timeout = milliseconds(3000)); ///!< Waits for CAN messages to appear - - virtual CanMessage readMessage(); ///!< Attempts to read a single message from the bus - - virtual int32_t sendMessage(const CanMessage message, - bool forceExtended = false); ///!< Attempts to send a single CAN message - virtual int32_t sendMessageQueue(queue messages, milliseconds delay = milliseconds(20), - bool forceExtended = false); ///!< Attempts to send a queue of messages - - virtual queue readQueuedMessages(); ///!< Attempts to read all queued messages from the bus - - virtual void setCanFilterMask(const int32_t mask); ///!< Attempts to set a new CAN filter - /// mask to the BIOS - - protected: // +++ Socket Management +++ - virtual void initialiseSocketCan(); ///!< Initialises socketcan - virtual void uninitialiseSocketCan(); ///!< Uninitialises socketcan - - private: - virtual CanMessage readMessageLock(bool const lock = true); ///!< readMessage deadlock guard - CanId _defaultSenderId; ///!< The ID to send messages with if no other ID was - /// set. - - int32_t _canFilterMask; ///!< The bit mask used to filter CAN messages - int32_t _canProtocol; ///!< The protocol used when communicating via CAN - int32_t _socketFd; ///!< The CAN socket file descriptor - int32_t _queueSize; ////!< The size of the message queue read by waitForMessages() - - mutex _lock; ///!< Mutex for thread-safety. - - string _canInterface; ///!< The CAN interface used for communication (e.g. - /// can0, can1, ...) -}; - -/** - * @brief Formats a std string object. - * - * @remarks Yoinked from https://github.com/Beatsleigher/liblogpp :) - * - * @tparam Args The formatting argument types. - * @param format The format string. - * @param args The format arguments (strings must be converted to C-style - * strings!) - * - * @return string The formatted string. - */ -template -string formatString(const string &format, Args... args) { - using std::unique_ptr; - auto stringSize = snprintf(NULL, 0, format.c_str(), args...) + 1; // +1 for \0 - unique_ptr buffer(new char[stringSize]); - - snprintf(buffer.get(), stringSize, format.c_str(), args...); - - return string(buffer.get(), buffer.get() + stringSize - 1); // std::string handles termination for us. -} - -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_CANDRIVER_HPP diff --git a/core/driver/sockcanpp/CanId.hpp b/core/driver/sockcanpp/CanId.hpp deleted file mode 100644 index 7a4cb08..0000000 --- a/core/driver/sockcanpp/CanId.hpp +++ /dev/null @@ -1,247 +0,0 @@ -/** - * @file CanId.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of a value-type representing a CAN - * identifier. - * @version 0.1 - * @date 2020-07-01 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKPP_INCLUDE_CANID_HPP -#define LIBSOCKPP_INCLUDE_CANID_HPP - -////////////////////////////// -// SYSTEM INCLUDES // -////////////////////////////// -#include - -#include -#include -#include - -namespace sockcanpp { - -using std::bitset; -using std::error_code; -using std::exception; -using std::generic_category; -using std::system_error; - -/** - * @brief Represents a CAN ID in a simple and easy-to-use manner. - */ -struct CanId { - public: // +++ Constructors +++ - CanId(const CanId &orig) - : _identifier(orig._identifier), - _isErrorFrame(orig._isErrorFrame), - _isRemoteTransmissionRequest(orig._isRemoteTransmissionRequest), - _isStandardFrameId(orig._isStandardFrameId), - _isExtendedFrameId(orig._isExtendedFrameId) { /* copy */ - } - - CanId(const uint32_t identifier) : _identifier(identifier) { - // TODO: Switch to using bitmasks! - - if (isValidIdentifier(identifier)) { - if (((int32_t)log2(identifier) + 1) < 11) { - _isStandardFrameId = true; - } else { - _isExtendedFrameId = true; - } - } else if (isErrorFrame(identifier)) { - _isErrorFrame = true; - } else if (isRemoteTransmissionRequest(identifier)) { - _isRemoteTransmissionRequest = true; - } - } - - CanId() : _identifier(0), _isStandardFrameId(true) {} - - public: // +++ Operators +++ - operator int16_t() const { - return isStandardFrameId() ? (int16_t)_identifier : throw system_error(error_code(0xbad1d, generic_category()), "INVALID CAST: ID is extended or invalid!"); - } - operator uint16_t() const { - return isStandardFrameId() ? (uint16_t)_identifier - : throw system_error(error_code(0xbad1d, generic_category()), "INVALID CAST: ID is extended or invalid!"); - } - operator int32_t() const { return _identifier; } - operator uint32_t() const { return _identifier; } - - CanId operator&(CanId &x) const { return _identifier & x._identifier; } - CanId operator&(const CanId x) const { return _identifier & x._identifier; } - CanId operator&(const int16_t x) const { return _identifier & x; } - CanId operator&(const uint16_t x) const { return _identifier & x; } - CanId operator&(const int32_t x) const { return _identifier & x; } - CanId operator&(const uint32_t x) const { return _identifier & x; } - CanId operator&(const int64_t x) const { return _identifier & x; } - CanId operator&(const uint64_t x) const { return _identifier & x; } - - CanId operator|(CanId &x) const { return _identifier | x._identifier; } - CanId operator|(const CanId x) const { return _identifier | x._identifier; } - CanId operator|(const int16_t x) const { return _identifier | x; } - CanId operator|(const uint16_t x) const { return _identifier | x; } - CanId operator|(const int32_t x) const { return _identifier | x; } - CanId operator|(const uint32_t x) const { return _identifier | x; } - CanId operator|(const int64_t x) const { return _identifier | x; } - CanId operator|(const uint64_t x) const { return _identifier | x; } - - bool operator==(CanId &x) const { return _identifier == x._identifier; } - bool operator==(const CanId &x) const { return _identifier == x._identifier; } - bool operator==(const int16_t x) const { return int16_t(_identifier) == x; } - bool operator==(const uint16_t x) const { return uint16_t(_identifier) == x; } - bool operator==(const int32_t x) const { return int32_t(_identifier) == x; } - bool operator==(const uint32_t x) const { return uint32_t(_identifier) == x; } - bool operator==(const int64_t x) const { return (x > UINT32_MAX || x < INT32_MIN) ? false : x == int64_t(_identifier); } - bool operator==(const uint64_t x) const { return x > UINT32_MAX ? false : x == uint64_t(_identifier); } - bool operator!=(CanId &x) const { return _identifier != x._identifier; } - bool operator!=(const CanId &x) const { return _identifier != x._identifier; } - bool operator!=(const int16_t x) const { return int16_t(_identifier) != x; } - bool operator!=(const uint16_t x) const { return uint16_t(_identifier) != x; } - bool operator!=(const int32_t x) const { return int32_t(_identifier) != x; } - bool operator!=(const uint32_t x) const { return uint32_t(_identifier) != x; } - bool operator!=(const int64_t x) const { return (x > UINT32_MAX || x < INT32_MIN) ? false : x != _identifier; } - bool operator!=(const uint64_t x) const { return x > UINT32_MAX ? false : x != _identifier; } - - bool operator<(CanId &x) const { return x._identifier < _identifier; } - bool operator<(int32_t x) const { return x < int32_t(_identifier); } - bool operator<(uint32_t x) const { return x < uint32_t(_identifier); } - bool operator<(int16_t x) const { return x < int16_t(_identifier); } - bool operator<(uint16_t x) const { return x < uint16_t(_identifier); } - bool operator<=(CanId &x) const { return x._identifier <= _identifier; } - bool operator>(CanId &x) const { return x._identifier > _identifier; } - bool operator>(int32_t x) const { return x > int32_t(_identifier); } - bool operator>(uint32_t x) const { return x > uint32_t(_identifier); } - bool operator>(int16_t x) const { return x > int16_t(_identifier); } - bool operator>(uint16_t x) const { return x > uint16_t(_identifier); } - bool operator>=(CanId &x) const { return x._identifier >= _identifier; } - bool operator<(const CanId &x) const { return x._identifier < _identifier; } - bool operator<=(const CanId &x) const { return x._identifier <= _identifier; } - bool operator>(const CanId &x) const { return x._identifier > _identifier; } - bool operator>=(const CanId &x) const { return x._identifier >= _identifier; } - - CanId operator=(const int32_t val) { - uint32_t tmpVal = val; - auto tmp = - (isValidIdentifier(tmpVal) ? CanId(val) : throw system_error(error_code(0x5421, generic_category()), "INVALID CAST: ID is extended or invalid!")); - return tmp; - } - - CanId operator=(const uint32_t val) { - uint32_t tmp = val; - return (isValidIdentifier(tmp) ? CanId(val) : throw system_error(error_code(0x5421, generic_category()), "INVALID CAST: ID is extended or invalid!")); - } - - CanId operator=(const int64_t val) { return operator=((int32_t)val); } - - CanId operator+(CanId &x) const { return _identifier + x._identifier; } - CanId operator+(const CanId &x) const { return _identifier + x._identifier; } - CanId operator+(const int16_t x) const { return _identifier + x; } - CanId operator+(const uint16_t x) const { return _identifier + x; } - CanId operator+(const int32_t x) const { return _identifier + x; } - CanId operator+(const uint32_t x) const { return _identifier + x; } - CanId operator+(const int64_t x) const { return _identifier + x; } - CanId operator+(const uint64_t x) const { return _identifier + x; } - - CanId operator-(CanId &x) const { return _identifier - x._identifier; } - CanId operator-(const CanId &x) const { return _identifier - x._identifier; } - CanId operator-(const int16_t x) const { return _identifier - x; } - CanId operator-(const uint16_t x) const { return _identifier - x; } - CanId operator-(const int32_t x) const { return _identifier - x; } - CanId operator-(const uint32_t x) const { return _identifier - x; } - CanId operator-(const int64_t x) const { return _identifier - x; } - CanId operator-(const uint64_t x) const { return _identifier - x; } - - public: // +++ Validity Checks +++ - /** - * @brief Indicates whether or not a given integer is a valid CAN identifier. - * - * @param value The integer to check. - * - * @return true If value is a valid CAN identifier. - * @return false Otherwise. - */ - static bool isValidIdentifier(uint32_t value) { - int32_t tmpValue = ((int32_t)log2(value) + 2); // Get bit count - - // Check for extended frame flag - if (tmpValue >= 29) { - value = (value & CAN_EFF_FLAG) ? (value & CAN_EFF_MASK) : (value & CAN_SFF_MASK); - tmpValue = ((int32_t)log2(value) + 1); // Get bit count again - } - - return (value == 0) /* Default value, also valid ID */ || ((tmpValue <= 29 && tmpValue > 0)); - } - - /** - * @brief Indicates whether or not a given integer contains the error frame - * flag or not. - * - * @param value The integer to check. - * - * @return true If value has the error frame flag (bit) set to 1. - * @return false Otherwise. - */ - static bool isErrorFrame(uint32_t value) { - try { - return bitset(value).test(29); - } catch (...) { - return false; /* Brute-force, but works. */ - } - } - - /** - * @brief Indicates whether the received frame is a remote transmission - * request. - * - * @param value The integer to check. - * - * @return true If the frame is a remote transmission request. - * @return false Otherwise. - */ - static bool isRemoteTransmissionRequest(uint32_t value) { - try { - return bitset(value).test(30); - } catch (...) { - return false; /* Brute-force, but works. */ - } - } - - public: // +++ Getters +++ - bool hasErrorFrameFlag() const { return _isErrorFrame; } - bool hasRtrFrameFlag() const { return _isRemoteTransmissionRequest; } - bool isStandardFrameId() const { return _isStandardFrameId; } - bool isExtendedFrameId() const { return _isExtendedFrameId; } - - public: // +++ Equality Checks +++ - bool equals(CanId otherId) const { return *this == otherId; } - - private: // +++ Variables +++ - bool _isErrorFrame = false; - bool _isRemoteTransmissionRequest = false; - bool _isStandardFrameId = false; - bool _isExtendedFrameId = false; - - uint32_t _identifier = 0; -}; - -} // namespace sockcanpp - -#endif // LIBSOCKPP_INCLUDE_CANID_HPP diff --git a/core/driver/sockcanpp/CanMessage.hpp b/core/driver/sockcanpp/CanMessage.hpp deleted file mode 100644 index 16a53d6..0000000 --- a/core/driver/sockcanpp/CanMessage.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @file CanMessage.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of a CAN message representation in C++. - * @version 0.1 - * @date 2020-07-01 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP -#define LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP - -////////////////////////////// -// SYSTEM INCLUDES // -////////////////////////////// -#include - -#include -#include -#include -#include - -////////////////////////////// -// LOCAL INCLUDES // -////////////////////////////// -#include "CanId.hpp" - -namespace sockcanpp { - -using std::error_code; -using std::generic_category; -using std::memcpy; -using std::string; -using std::system_error; - -/** - * @brief Represents a CAN message that was received. - */ -class CanMessage { - public: // +++ Constructor / Destructor +++ - CanMessage(const struct can_frame frame) : _canIdentifier(frame.can_id), _frameData((const char *)frame.data, frame.can_dlc), _rawFrame(frame) {} - - CanMessage(const CanId canId, const string frameData) : _canIdentifier(canId), _frameData(frameData) { - if (frameData.size() > 8) { - throw system_error(error_code(0xbadd1c, generic_category()), "Payload too big!"); - } - - struct can_frame rawFrame; - rawFrame.can_id = canId; - memcpy(rawFrame.data, frameData.data(), frameData.size()); - rawFrame.can_dlc = frameData.size(); - - _rawFrame = rawFrame; - } - - virtual ~CanMessage() {} - - public: // +++ Getters +++ - const CanId getCanId() const { return this->_canIdentifier; } - const string getFrameData() const { return this->_frameData; } - const can_frame getRawFrame() const { return this->_rawFrame; } - - private: - CanId _canIdentifier; - - string _frameData; - - struct can_frame _rawFrame; -}; - -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_CANMESSAGE_HPP diff --git a/core/driver/sockcanpp/README.md b/core/driver/sockcanpp/README.md deleted file mode 100644 index 3524f77..0000000 --- a/core/driver/sockcanpp/README.md +++ /dev/null @@ -1,130 +0,0 @@ - -``` -BaseOn: - https://github.com/SimonCahill/libsockcanpp - 4d0e6a3e679a34dee4449a9d22b7f794a3cf9871 - -localGit - http://192.168.1.3:3000/z3rd_lib/libsockcanpp - -Demo: - http://192.168.1.3:3000/z3rd_lib/libsockcanpp/src/branch/master/test/src/Main.cpp -``` - - -# Usage -```cpp -/** - * @file Main.cpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of a test application using this library. - * @version 0.1 - * @date 2020-07-02 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include -#include - -using sockcanpp::CanDriver; -using sockcanpp::CanId; -using sockcanpp::exceptions::CanException; -using sockcanpp::exceptions::CanInitException; -using sockcanpp::exceptions::InvalidSocketException; -using sockcanpp::CanMessage; - -using std::cerr; -using std::cout; -using std::endl; -using std::string; - -void printHelp(string); - -int main(int32_t argCount, char** argValues) { - int32_t desiredCanSocket = 0; - string canInterface; - - if (argCount > 2) { - for (int32_t i = 1; i < argCount; i++) { - if (argValues[i] == "--help" || argValues[i] == "-h") { - printHelp(argValues[0]); - return 0; - } else if (argValues[i] == "-protocol") { - desiredCanSocket = atoi(argValues[i + 1]); - i += 1; - continue; - } else if (argValues[i] == "-iface") { - canInterface = (argValues[i + 1]); - i += 1; - continue; - } - } - } - - if (desiredCanSocket <= 0) - desiredCanSocket = CanDriver::CAN_SOCK_RAW; - if (canInterface == "") - canInterface = "can0"; - - CanDriver* canDriver; - try { - canDriver = new CanDriver(canInterface, CAN_RAW); - } catch (CanInitException& ex) { - cerr << "An error occurred while initialising CanDriver: " << ex.what() << endl; - delete canDriver; - return -1; - } - - while (true) { - printf("Writing test message:\n"); - try { canDriver->sendMessage(CanMessage(0x555, "abcdefg8")); } - catch (CanException& ex) { cerr << "Failed to send test message! " << ex.what() << endl; } - catch (InvalidSocketException& ex) { cerr << "Failed to send test message! " << ex.what() << endl; } - - printf("Reading messages\n"); - if (!canDriver->waitForMessages()) continue; - - cout << "Reading queue..." << endl; - auto canMessages = canDriver->readQueuedMessages(); - while (!canMessages.empty()) { - auto msg = canMessages.front(); - canMessages.pop(); - - cout << "CAN ID: " << (int32_t)msg.getCanId() << endl - << "CAN data: "; - for (auto byte : msg.getFrameData()) - cout << std::hex << byte << " "; - cout << endl; - } - } -} - -void printHelp(string appname) { - cout << appname << endl << endl - << "-h\t\tPrints this menu" << endl - << "--help\t\tPrints this menu" << endl - << "-protocol " << endl - << "-iface " << endl; -} -``` - diff --git a/core/driver/sockcanpp/exceptions/CanCloseException.hpp b/core/driver/sockcanpp/exceptions/CanCloseException.hpp deleted file mode 100644 index de828b4..0000000 --- a/core/driver/sockcanpp/exceptions/CanCloseException.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file CanCloseException.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of an exception that may be thrown when an - * error occurs while closing a CAN socket. - * @version 0.1 - * @date 2020-07-02 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP -#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP - -#include -#include - -namespace sockcanpp { -namespace exceptions { - -using std::exception; -using std::string; - -/** - * @brief An exception that may be thrown when an error occurs while closing a - * CAN socket. - */ -class CanCloseException : public exception { - public: // +++ Constructor / Destructor +++ - CanCloseException(string message) : _message(message) {} - ~CanCloseException() {} - - public: // +++ Overrides +++ - const char *what() { return _message.c_str(); } - - private: - string _message; -}; - -} // namespace exceptions -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANCLOSEEXCEPTION_HPP \ No newline at end of file diff --git a/core/driver/sockcanpp/exceptions/CanException.hpp b/core/driver/sockcanpp/exceptions/CanException.hpp deleted file mode 100644 index a5a142f..0000000 --- a/core/driver/sockcanpp/exceptions/CanException.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file CanException.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of a general-purpose exception which may - * be thrown when an error occurs when performing IO on a CAN socket. - * @version 0.1 - * @date 2020-07-02 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP -#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP - -#include -#include - -namespace sockcanpp { -namespace exceptions { - -using std::exception; -using std::string; - -/** - * @brief An exception that may be thrown when an error occurs while closing a - * CAN socket. - */ -class CanException : public exception { - public: // +++ Constructor / Destructor +++ - CanException(string message, int32_t socket) : _message(message), _socket(socket) {} - ~CanException() {} - - public: // +++ Overrides +++ - const char *what() { return _message.c_str(); } - - public: // +++ Getter +++ - const int32_t getSocket() const { return _socket; } - - private: - int32_t _socket; - - string _message; -}; - -} // namespace exceptions -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANEXCEPTION_HPP \ No newline at end of file diff --git a/core/driver/sockcanpp/exceptions/CanInitException.hpp b/core/driver/sockcanpp/exceptions/CanInitException.hpp deleted file mode 100644 index 0938c7b..0000000 --- a/core/driver/sockcanpp/exceptions/CanInitException.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file CanInitException.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of an exception that is thrown when a CAN - * socket couldn't be inintialised. - * @version 0.1 - * @date 2020-07-02 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP -#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP - -#include -#include - -namespace sockcanpp { -namespace exceptions { - -using std::exception; -using std::string; - -/** - * @brief An exception that may be thrown when an error occurred while - * initialising a CAN socket. - */ -class CanInitException : public exception { - public: // +++ Constructor / Destructor +++ - CanInitException(string message) : _message(message) {} - virtual ~CanInitException() {} - - public: // +++ Override +++ - const char *what() { return _message.c_str(); } - - private: - string _message; -}; - -} // namespace exceptions -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_CANINITEXCEPTION_HPP \ No newline at end of file diff --git a/core/driver/sockcanpp/exceptions/InvalidSocketException.hpp b/core/driver/sockcanpp/exceptions/InvalidSocketException.hpp deleted file mode 100644 index 177a8d8..0000000 --- a/core/driver/sockcanpp/exceptions/InvalidSocketException.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file InvalidSocketException.hpp - * @author Simon Cahill (simonc@online.de) - * @brief Contains the implementation of an exception that may be thrown when an - * invalid CAN socket is detected. - * @version 0.1 - * @date 2020-07-02 - * - * @copyright Copyright (c) 2020 Simon Cahill - * - * Copyright 2020 Simon Cahill - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP -#define LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP - -#include -#include - -namespace sockcanpp { -namespace exceptions { - -using std::exception; -using std::string; - -/** - * @brief An exception that may be thrown when an error occurs while closing a - * CAN socket. - */ -class InvalidSocketException : public exception { - public: // +++ Constructor / Destructor +++ - InvalidSocketException(string message, int32_t socket) : _message(message), _socket(socket) {} - ~InvalidSocketException() {} - - public: // +++ Overrides +++ - const char *what() { return _message.c_str(); } - - public: // +++ Getter +++ - const int32_t getSocket() const { return _socket; } - - private: - int32_t _socket; - - string _message; -}; - -} // namespace exceptions -} // namespace sockcanpp - -#endif // LIBSOCKCANPP_INCLUDE_EXCEPTIONS_INVALIDSOCKETEXCEPTION_HPP \ No newline at end of file diff --git a/core/driver/socketcan/socketcan.cpp b/core/driver/socketcan/socketcan.cpp new file mode 100644 index 0000000..e69de29 diff --git a/core/driver/socketcan/socketcan.hpp b/core/driver/socketcan/socketcan.hpp new file mode 100644 index 0000000..e69de29 diff --git a/core/driver/socketcan/socketcan_frame.hpp b/core/driver/socketcan/socketcan_frame.hpp new file mode 100644 index 0000000..e69de29