summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/cangenplugin/cangenplugin.cpp8
-rw-r--r--plugins/cangenplugin/cangenplugin.h6
-rw-r--r--plugins/cansimplugin/cansimplugin.cpp10
-rw-r--r--plugins/cansimplugin/cansimplugin.h6
-rw-r--r--plugins/common/CMakeLists.txt8
-rw-r--r--plugins/common/canadapter.h18
-rw-r--r--plugins/common/canbus.h97
-rw-r--r--plugins/common/canbusimpl.cpp70
-rw-r--r--plugins/common/canbusimpl.h26
-rw-r--r--plugins/common/canframeinfo.h72
-rw-r--r--plugins/common/canobserver.h10
-rw-r--r--plugins/common/cansocket.cpp119
-rw-r--r--plugins/common/cansocket.h68
-rw-r--r--plugins/common/cansocketadapter.cpp23
-rw-r--r--plugins/common/cansocketadapter.h16
-rw-r--r--plugins/common/cansocketbcm.cpp279
-rw-r--r--plugins/common/cansocketbcm.h122
-rw-r--r--plugins/common/cansocketraw.cpp199
-rw-r--r--plugins/common/cansocketraw.h103
-rw-r--r--plugins/common/cansocketreader.cpp90
-rw-r--r--plugins/common/cansocketreader.h7
-rw-r--r--plugins/common/thread.cpp151
-rw-r--r--plugins/common/thread.h9
-rw-r--r--plugins/dbus/dbusinterfacemanager.cpp2
24 files changed, 1179 insertions, 340 deletions
diff --git a/plugins/cangenplugin/cangenplugin.cpp b/plugins/cangenplugin/cangenplugin.cpp
index 73d32538..93d2e718 100644
--- a/plugins/cangenplugin/cangenplugin.cpp
+++ b/plugins/cangenplugin/cangenplugin.cpp
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <logger.h>
#include <ambplugin.h>
+#include <canbusimpl.h>
#include "cangenplugin.h"
@@ -203,7 +204,7 @@ bool CANGenPlugin::sendValue(const std::string& interface, AbstractPropertyType*
auto& canBus = interfaces[interface];
if(!canBus){
- canBus = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ canBus = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
bool started(canBus->start(interface.c_str()));
if(!started)
return false;
@@ -464,3 +465,8 @@ void CANGenPlugin::dataReceived(libwebsocket* socket, const char* data, size_t l
}
}
}
+
+void CANGenPlugin::timeoutDetected(const can_frame& frame)
+{
+ // do nothing
+}
diff --git a/plugins/cangenplugin/cangenplugin.h b/plugins/cangenplugin/cangenplugin.h
index 09e9c4e5..163cde0e 100644
--- a/plugins/cangenplugin/cangenplugin.h
+++ b/plugins/cangenplugin/cangenplugin.h
@@ -137,6 +137,12 @@ public:
* \param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame);
/*!
* Second phase of the plugin initialization.
diff --git a/plugins/cansimplugin/cansimplugin.cpp b/plugins/cansimplugin/cansimplugin.cpp
index b609b3f9..c8b99216 100644
--- a/plugins/cansimplugin/cansimplugin.cpp
+++ b/plugins/cansimplugin/cansimplugin.cpp
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <ambplugin.h>
#include <logger.h>
+#include <canbusimpl.h>
#include "cansimplugin.h"
@@ -86,7 +87,7 @@ CANSimPlugin::CANSimPlugin(AbstractRoutingEngine* re, const map<string, string>&
json_object* obj = (json_object*)array_list_get_idx(ifacelist,i);
const char* str = obj ? json_object_get_string(obj) : nullptr;
if(str){
- interfaces[str] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ interfaces[str] = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
}
}
}
@@ -94,7 +95,7 @@ CANSimPlugin::CANSimPlugin(AbstractRoutingEngine* re, const map<string, string>&
}
// Default interface if none has been configured.
if(interfaces.empty()){
- interfaces[DEFAULT_CAN_IF_NAME] = std::shared_ptr<CANBus>(new CANBus(*static_cast<CANObserver*>(this)));
+ interfaces[DEFAULT_CAN_IF_NAME] = std::shared_ptr<CANBus>(new CANBusImpl(*static_cast<CANObserver*>(this)));
}
addPropertySupport(
@@ -386,4 +387,7 @@ void CANSimPlugin::printFrame(const can_frame& frame) const
LOG_INFO( "CANSimPlugin::printFrame can data" << ss.str() << endl );
}
-
+void CANSimPlugin::timeoutDetected(const can_frame& frame)
+{
+ // do nothing
+}
diff --git a/plugins/cansimplugin/cansimplugin.h b/plugins/cansimplugin/cansimplugin.h
index 40b55d51..43b1f79e 100644
--- a/plugins/cansimplugin/cansimplugin.h
+++ b/plugins/cansimplugin/cansimplugin.h
@@ -126,6 +126,12 @@ public:
* \param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame);/* remote transmission request (SFF/EFF is still present)*/
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame);
/*!
* Second phase of the plugin initialization.
diff --git a/plugins/common/CMakeLists.txt b/plugins/common/CMakeLists.txt
index 052c2c56..407b281e 100644
--- a/plugins/common/CMakeLists.txt
+++ b/plugins/common/CMakeLists.txt
@@ -1,9 +1,9 @@
set(plugins_common_sources abstractio.hpp serialport.hpp bluetoothadapterproxy.c bluetooth.hpp bluetoothmanagerproxy.c bluetoothserialproxy.c bluetooth5.cpp
- canadapter.cpp cansocket.cpp cansocketreader.cpp canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp thread.cpp dbusexport.cpp dbusplugin.cpp
- abstractdbusinterface.cpp dbussignaller.cpp varianttype.cpp)
+ canadapter.cpp cansocket.cpp cansocketraw.cpp cansocketbcm.cpp cansocketreader.cpp canbusimpl.cpp cansocketadapter.cpp logger.cpp mutex.cpp
+ thread.cpp dbusexport.cpp dbusplugin.cpp abstractdbusinterface.cpp dbussignaller.cpp varianttype.cpp)
set(plugins_common_headers_install abstractio.hpp serialport.hpp bluetooth.hpp bluetoothadapterproxy.h bluetoothmanagerproxy.h bluetoothserialproxy.h
- bluetooth5.h canbus.h canadapter.h cansocket.h cansocketreader.h canbusimpl.h cansocketadapter.h canobserver.h logger.h mutex.h thread.h
- dbusexport.h dbusplugin.h abstractdbusinterface.h dbussignaller.h varianttype.h)
+ bluetooth5.h canframeinfo.h canbus.h canadapter.h cansocket.h cansocketraw.h cansocketbcm.h cansocketreader.h canbusimpl.h cansocketadapter.h
+ canobserver.h logger.h mutex.h thread.h dbusexport.h dbusplugin.h abstractdbusinterface.h dbussignaller.h varianttype.h)
add_library(amb-plugins-common SHARED ${plugins_common_sources})
diff --git a/plugins/common/canadapter.h b/plugins/common/canadapter.h
index fa78c102..2efffa03 100644
--- a/plugins/common/canadapter.h
+++ b/plugins/common/canadapter.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -68,6 +70,22 @@ public:
* @return True if frame was sent
*/
virtual bool sendFrame(const can_frame& frame) = 0;
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime) = 0;
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId) = 0;
protected:
/**
diff --git a/plugins/common/canbus.h b/plugins/common/canbus.h
index 319c856a..4d9d856c 100644
--- a/plugins/common/canbus.h
+++ b/plugins/common/canbus.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -16,6 +18,8 @@ License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+/* Refactored to an abstract interface. See http://stackoverflow.com/a/825365 */
+
#ifndef CANBUS_H
#define CANBUS_H
@@ -35,47 +39,60 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
class CANBus
{
public:
- /**
- * @param observer Object derived from #CANObserver that will receive CAN bus frames
- */
- CANBus(CANObserver& observer);
- virtual ~CANBus();
-
- /**
- * Starts the CAN bus instance on the specified interface
- * @fn start
- * @param name Name of the CAN bus network interface
- * @return True if no error occurs.
- */
- virtual bool start(const char* name);
- /**
- * Stops the CAN bus instance
- * @fn stop
- */
- virtual void stop();
- /**
- * Sends standard(11bit) CAN frame over the bus
- * @fn sendStandardFrame
- * @param frame CAN frame to be sent
- * @return True if frame was sent
- */
- virtual bool sendStandardFrame(const can_frame& frame);
- /**
- * Sends extended(29bit) CAN frame over the bus
- * @fn sendExtendedFrame
- * @param frame CAN frame to be sent
- * @return True if frame was sent
- */
- virtual bool sendExtendedFrame(const can_frame& frame);
+ virtual ~CANBus(){} /*LCOV_EXCL_LINE*/
- class Impl;
-protected:
- /**
- * CANBus class private implementation
- * @property d
- * @protected
- */
- Impl* d;
+ /**
+ * Starts the CAN bus instance on the specified interface
+ * @fn start
+ * @param name Name of the CAN bus network interface
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* name) = 0;
+ /**
+ * Stops the CAN bus instance
+ * @fn stop
+ */
+ virtual void stop() = 0;
+ /**
+ * Sends standard(11bit) CAN frame over the bus
+ * @fn sendStandardFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendStandardFrame(const can_frame& frame) = 0;
+ /**
+ * Sends extended(29bit) CAN frame over the bus
+ * @fn sendExtendedFrame
+ * @param frame CAN frame to be sent
+ * @return True if frame was sent
+ */
+ virtual bool sendExtendedFrame(const can_frame& frame) = 0;
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime) = 0;
+ /**
+ * Registers CAN ID of a message for receiving with no timeout. Perfect for sporadic messages.
+ * @fn registerMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerMessageForReceive(int canId)
+ {
+ return registerCyclicMessageForReceive(canId, 0, 0);
+ }
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId) = 0;
};
#endif // CANBUS_H
diff --git a/plugins/common/canbusimpl.cpp b/plugins/common/canbusimpl.cpp
index 993e4a0f..b0a0fa7d 100644
--- a/plugins/common/canbusimpl.cpp
+++ b/plugins/common/canbusimpl.cpp
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -21,25 +23,21 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "canadapter.h"
#include "logger.h"
-//----------------------------------------------------------------------------
-// CANBusImpl
-//----------------------------------------------------------------------------
-
-CANBus::Impl::Impl(CANObserver& observer) :
+CANBusImpl::CANBusImpl(CANObserver& observer) :
mObserver(observer),
mAdapter(NULL)
{
LOG_TRACE("");
}
-CANBus::Impl::~Impl()
+CANBusImpl::~CANBusImpl()
{
LOG_TRACE("");
stop();
}
-bool CANBus::Impl::start(const char* name)
+bool CANBusImpl::start(const char* name)
{
LOG_TRACE("");
@@ -49,7 +47,7 @@ bool CANBus::Impl::start(const char* name)
return mAdapter ? mAdapter->start(name) : false;
}
-void CANBus::Impl::stop()
+void CANBusImpl::stop()
{
LOG_TRACE("");
@@ -60,7 +58,7 @@ void CANBus::Impl::stop()
}
}
-bool CANBus::Impl::sendStandardFrame(const can_frame& frame)
+bool CANBusImpl::sendStandardFrame(const can_frame& frame)
{
LOG_TRACE("");
@@ -72,7 +70,7 @@ bool CANBus::Impl::sendStandardFrame(const can_frame& frame)
return false;
}
-bool CANBus::Impl::sendExtendedFrame(const can_frame& frame)
+bool CANBusImpl::sendExtendedFrame(const can_frame& frame)
{
LOG_TRACE("");
@@ -85,56 +83,24 @@ bool CANBus::Impl::sendExtendedFrame(const can_frame& frame)
return false;
}
-void CANBus::Impl::init()
+void CANBusImpl::init()
{
mAdapter = CANAdapter::createCANAdapter(mObserver);
}
-//----------------------------------------------------------------------------
-// CANBus
-//----------------------------------------------------------------------------
-
-CANBus::CANBus(CANObserver& observer) :
- d(new CANBus::Impl(observer))
-{
- LOG_TRACE("");
-}
-
-CANBus::~CANBus()
+bool CANBusImpl::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
{
- LOG_TRACE("");
-
- if(d) {
- delete d;
- d = 0;
+ if(mAdapter) {
+ return mAdapter->registerCyclicMessageForReceive(canId, minCycleTime, maxCycleTime);
}
+ return false;
}
-bool CANBus::start(const char* name)
-{
- LOG_TRACE("");
-
- return d ? d->start(name) : false;
-}
-
-void CANBus::stop()
-{
- LOG_TRACE("");
-
- if(d)
- d->stop();
-}
-
-bool CANBus::sendStandardFrame(const can_frame& frame)
+bool CANBusImpl::unregisterMessageForReceive(int canId)
{
- LOG_TRACE("");
-
- return d ? d->sendStandardFrame(frame) : false;
+ if(mAdapter) {
+ return mAdapter->unregisterMessageForReceive(canId);
+ }
+ return false;
}
-bool CANBus::sendExtendedFrame(const can_frame& frame)
-{
- LOG_TRACE("");
-
- return d ? d->sendExtendedFrame(frame) : false;
-}
diff --git a/plugins/common/canbusimpl.h b/plugins/common/canbusimpl.h
index e2ccdd9c..c7698b80 100644
--- a/plugins/common/canbusimpl.h
+++ b/plugins/common/canbusimpl.h
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -35,14 +37,14 @@ class CANAdapter;
* @class CANBus::Impl
*/
-class CANBus::Impl
+class CANBusImpl : public CANBus
{
public:
/**
- * @param observer \link #CANObserver Observer \endlink that will receives CAN bus frames
+ * @param observer \link #CANObserver Observer \endlink that will receive CAN bus frames
*/
- Impl(CANObserver& observer);
- virtual ~Impl();
+ CANBusImpl(CANObserver& observer);
+ virtual ~CANBusImpl();
/**
* Starts the CAN bus instance on the specified interface
@@ -70,6 +72,22 @@ public:
* @return True if frame was sent
*/
bool sendExtendedFrame(const can_frame& frame);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
protected:
/**
diff --git a/plugins/common/canframeinfo.h b/plugins/common/canframeinfo.h
new file mode 100644
index 00000000..6469a679
--- /dev/null
+++ b/plugins/common/canframeinfo.h
@@ -0,0 +1,72 @@
+/*
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANFRAMEINFO_H
+#define CANFRAMEINFO_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <stdlib.h>
+#include <linux/can.h>
+
+#include "timestamp.h"
+
+/**
+ * CAN frame with additional information
+ */
+struct CANFrameInfo
+{
+ CANFrameInfo(const can_frame &frame)
+ {
+ this->status = CANFrameInfo::CANMessageStatus::GOOD;
+ this->frame = frame;
+ this->timestamp = amb::currentTime();
+ }
+
+ CANFrameInfo() { }
+
+ enum CANMessageStatus {
+ TIMEOUT = -2,
+ EMPTY = 0,
+ GOOD = 1,
+ };
+
+ /**
+ * The actual frame written or read from socket
+ */
+ struct can_frame frame;
+
+ /**
+ * Status of the message.
+ */
+ CANFrameInfo::CANMessageStatus status;
+
+ /**
+ * Timestamp of sending or receiving action
+ */
+ double timestamp;
+};
+
+#endif // CANFRAMEINFO_H
+
+/** @} */
+
diff --git a/plugins/common/canobserver.h b/plugins/common/canobserver.h
index 0518bd49..549f0700 100644
--- a/plugins/common/canobserver.h
+++ b/plugins/common/canobserver.h
@@ -24,8 +24,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @{
*/
+#include <stdlib.h>
#include <linux/can.h>
+#include "canframeinfo.h"
+
/**
* \brief Interface. Receives notifications about the CAN bus traffic and errors.
*
@@ -76,7 +79,12 @@ public:
* @param frame RTR frame
*/
virtual void remoteTransmissionRequest(const can_frame& frame) = 0; /* remote transmission request (SFF/EFF is still present)*/
-
+ /**
+ * Called when timeout was detected for a cyclic message.
+ * @fn timeoutDetected
+ * @param frame
+ */
+ virtual void timeoutDetected(const can_frame& frame) = 0; /* timeout */
};
#endif // CANOBSERVER_H
diff --git a/plugins/common/cansocket.cpp b/plugins/common/cansocket.cpp
index b59c6bd5..0b5ca9c0 100644
--- a/plugins/common/cansocket.cpp
+++ b/plugins/common/cansocket.cpp
@@ -24,135 +24,54 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "logger.h"
#include "cansocket.h"
-
-CANSocket::CANSocket() :
- mSocket(-1)
+CANSocket::CANSocket()
{
+ // default implementation doesn't do anything
LOG_TRACE("");
}
CANSocket::~CANSocket()
{
+ // default implementation doesn't do anything
LOG_TRACE("");
stop();
}
-bool CANSocket::start(const char* ifName)
-{
- LOG_TRACE("");
-
- if(mSocket < 0) {
- if(!createSocket()) {
- LOG_ERROR("Socket error");
- } else {
- can_err_mask_t errorMask = 0xFFFFFFFF;
- if(!enableCANErrors(errorMask)) {
- LOG_ERROR("Socket error");
- } else {
- mPoll.fd = mSocket;
- mPoll.events = POLLIN | POLLPRI;
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ifName);
- if(!locateInterfaceIndex(ifr)) {
- LOG_ERROR("Socket error");
- stop();
- } else {
- struct sockaddr_can addr;
- memset(&addr, 0, sizeof(addr));
- addr.can_family = AF_CAN;
- addr.can_ifindex = ifr.ifr_ifindex;
- if(!bindSocket(addr)) {
- LOG_ERROR("Socket error");
- stop();
- } else {
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
void CANSocket::stop()
{
- LOG_TRACE("");
-
- if(mSocket >= 0) {
- closeSocket();
- mSocket = -1;
- }
+ // default implementation doesn't do anything
}
-bool CANSocket::write(const struct can_frame &frame, int &bytesWritten)
+bool CANSocket::write(const struct CANFrameInfo &message)
{
+ // default implementation doesn't do anything
LOG_TRACE("");
- bytesWritten = (int)writeFrame(frame);
- return bytesWritten == sizeof(struct can_frame);
-}
-
-CANSocket::CANSocketReadSuccess CANSocket::read(
- struct can_frame& frame, int &bytesRead, unsigned int timeout)
-{
- LOG_TRACE("timeout: " << timeout);
-
- CANSocket::CANSocketReadSuccess success;
-
- switch(waitData(timeout)) {
- case -1:
- LOG_ERROR("reading error");
- success = CANSocket::READING_FAILED;
- break;
- case 0:
- bytesRead = 0;
- success = CANSocket::READING_TIMED_OUT;
- break;
- default:
- bytesRead = (int)readFrame(frame);
- success = bytesRead >= 0 ?CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
- }
- return success;
-}
-
-bool CANSocket::createSocket()
-{
- return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
+ return false;
}
-bool CANSocket::enableCANErrors(can_err_mask_t errorMask)
-{
- return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
-}
-bool CANSocket::locateInterfaceIndex(struct ifreq& ifr)
+CANSocket::CANSocketReadSuccess CANSocket::read(struct CANFrameInfo& message, unsigned int timeout)
{
- return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-bool CANSocket::bindSocket(struct sockaddr_can& addr)
-{
- return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+ return CANSocketReadSuccess::READING_FAILED;
}
-bool CANSocket::closeSocket()
+bool CANSocket::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
{
- return (::close(mSocket) == 0);
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-int CANSocket::waitData(unsigned int timeout)
-{
- return ::poll(&mPoll, 1, timeout);
+ return false;
}
-ssize_t CANSocket::writeFrame(const can_frame& frame)
+bool CANSocket::unregisterMessageForReceive(int canId)
{
- return ::write(mSocket, &frame, sizeof(struct can_frame));
-}
+ // default implementation doesn't do anything
+ LOG_TRACE("");
-ssize_t CANSocket::readFrame(can_frame& frame)
-{
- return ::recv(mSocket, &frame, sizeof(struct can_frame), 0);
+ return false;
}
diff --git a/plugins/common/cansocket.h b/plugins/common/cansocket.h
index f6eaa50a..a201e5a4 100644
--- a/plugins/common/cansocket.h
+++ b/plugins/common/cansocket.h
@@ -24,13 +24,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* @{
*/
-#include <net/if.h>
-#include <sys/poll.h>
-#include <string>
-#include <linux/can/raw.h>
+#include <linux/can.h>
+
+#include "canbus.h"
/**
-* \brief CAN Socket wrapper.
+* \brief Wrapper around different implementations of SocketCAN.
* @class CANSocket
*/
class CANSocket
@@ -45,7 +44,7 @@ public:
enum CANSocketReadSuccess {
READING_FAILED = -1,
READING_TIMED_OUT,
- READING_SUCCEEDED
+ READING_SUCCEEDED,
};
public:
@@ -53,62 +52,49 @@ public:
virtual ~CANSocket();
/**
- * Opens and initialize CAN socket
+ * Opens and initializes CAN socket
* @fn start
* @param ifName Name of the CAN bus network interface.
* @return True if no error occurs.
*/
- virtual bool start(const char* ifName);
+ virtual bool start(const char* ifName) = 0;
/**
- * Closes socket
+ * Closes the socket
* @fn stop
*/
virtual void stop();
/**
* Writes CAN frame using the socket
* @fn write
- * @param frame CAN frame buffer
+ * @param message CAN frame with additional information
* @param bytesWritten Number of written bytes.
* @return True if no error occurs.
*/
- virtual bool write(const struct can_frame &frame, int &bytesWritten);
-
+ virtual bool write(const struct CANFrameInfo &message);
/**
* Try to read CAN frame
* @fn read
- * @param frame CAN frame buffer
- * @param bytesRead Number of read bytes.
- * @param timeout Timeout for reading.
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
* @return Reading operation status code.
*/
- virtual CANSocket::CANSocketReadSuccess read( struct can_frame& frame, int &bytesRead, unsigned int timeout = 1000);
-
-private:
- /**
- * @internal
- */
- virtual bool createSocket();
- virtual bool enableCANErrors(can_err_mask_t errorMask);
- virtual bool locateInterfaceIndex(struct ifreq& ifr);
- virtual bool bindSocket(struct sockaddr_can &addr);
- virtual bool closeSocket();
- virtual int waitData(unsigned int timeout);
- virtual ssize_t writeFrame(const struct can_frame &frame);
- virtual ssize_t readFrame(struct can_frame& frame);
-
-private:
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
/**
- * Socket file descriptor.
- * @property mSocket
- * @private
- */
- int mSocket;
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
/**
- * Data structure describing a polling request.
- * @property mPoll
- * @private
- */
- struct pollfd mPoll;
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
};
#endif // CANSOCKET_H
diff --git a/plugins/common/cansocketadapter.cpp b/plugins/common/cansocketadapter.cpp
index c2e660b7..3395038b 100644
--- a/plugins/common/cansocketadapter.cpp
+++ b/plugins/common/cansocketadapter.cpp
@@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "canobserver.h"
#include "cansocketreader.h"
#include "logger.h"
+#include "cansocketbcm.h"
+#include "cansocketraw.h"
// TODO: handle socket errors
@@ -76,8 +78,8 @@ bool CANSocketAdapter::sendFrame(const can_frame& frame)
LOG_TRACE("");
if(mSocket) {
- int bytesWritten(0);
- return mSocket->write(frame, bytesWritten);
+ CANFrameInfo message(frame);
+ return mSocket->write(message);
}
return false;
}
@@ -85,8 +87,23 @@ bool CANSocketAdapter::sendFrame(const can_frame& frame)
void CANSocketAdapter::init()
{
if(!mSocket)
- mSocket = new CANSocket();
+ mSocket = new CANSocketBCM();
if(!mReader)
mReader = new CANSocketReader(mObserver, *mSocket);
}
+bool CANSocketAdapter::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
+{
+ if(mSocket)
+ return mSocket->registerCyclicMessageForReceive(canId, minCycleTime, maxCycleTime);
+ else
+ return false;
+}
+
+bool CANSocketAdapter::unregisterMessageForReceive(int canId)
+{
+ if(mSocket)
+ return mSocket->unregisterMessageForReceive(canId);
+ else
+ return false;
+}
diff --git a/plugins/common/cansocketadapter.h b/plugins/common/cansocketadapter.h
index 350563ce..811d26a7 100644
--- a/plugins/common/cansocketadapter.h
+++ b/plugins/common/cansocketadapter.h
@@ -63,6 +63,22 @@ public:
* @return True if frame was sent
*/
virtual bool sendFrame(const can_frame& frame);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Un-registers CAN ID of a message used of receiving. Valid for cyclic and sporadic messages.
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
protected:
/**
diff --git a/plugins/common/cansocketbcm.cpp b/plugins/common/cansocketbcm.cpp
new file mode 100644
index 00000000..d923ce3e
--- /dev/null
+++ b/plugins/common/cansocketbcm.cpp
@@ -0,0 +1,279 @@
+/*
+Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <timestamp.h>
+#include "logger.h"
+#include "cansocketbcm.h"
+#include "timestamp.h"
+
+CANSocketBCM::CANSocketBCM() :
+ mSocket(-1)
+{
+ LOG_TRACE("");
+}
+
+bool CANSocketBCM::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0)
+ return false;
+
+ if(!createSocket())
+ {
+ LOG_ERROR("Socket error");
+ return false;
+ }
+
+ // can_err_mask_t errorMask = 0xFFFFFFFF;
+ // if(!enableCANErrors(errorMask)) {
+ // LOG_ERROR("Socket error");
+ // return false;
+ // }
+
+ mPoll.fd = mSocket;
+ mPoll.events = POLLIN | POLLPRI;
+
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ifName);
+ if(!locateInterfaceIndex(ifr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ return false;
+ }
+
+ struct sockaddr_can addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+ if(!connectSocket(addr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ return false;
+ }
+
+ return true;
+}
+
+void CANSocketBCM::stop()
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0) {
+ closeSocket();
+ mSocket = -1;
+ }
+}
+
+bool CANSocketBCM::write(const struct CANFrameInfo &message)
+{
+ LOG_TRACE("");
+
+ return writeFrameOneTime(message.frame);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketBCM::read(struct CANFrameInfo& message, unsigned int timeout)
+{
+ LOG_TRACE("timeout: " << timeout);
+
+ CANSocket::CANSocketReadSuccess success;
+ memset(&message, 0, sizeof(message));
+
+ switch(waitData(timeout)) {
+ case -1:
+ LOG_ERROR("reading error");
+ success = CANSocket::READING_FAILED;
+ break;
+ case 0:
+ success = CANSocket::READING_TIMED_OUT;
+ break;
+ default:
+ success = readMessage(message);
+ break;
+ }
+
+ return success;
+}
+
+bool CANSocketBCM::createSocket()
+{
+ return ((mSocket = ::socket(PF_CAN, SOCK_DGRAM, CAN_BCM)) >= 0);
+}
+
+bool CANSocketBCM::locateInterfaceIndex(struct ifreq& ifr)
+{
+ return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
+}
+
+bool CANSocketBCM::connectSocket(struct sockaddr_can& addr)
+{
+ return (::connect(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+}
+
+bool CANSocketBCM::closeSocket()
+{
+ return (::close(mSocket) == 0);
+}
+
+int CANSocketBCM::waitData(unsigned int timeout)
+{
+ return ::poll(&mPoll, 1, timeout);
+}
+
+/**
+ * BCM header with one message.
+ * @note hdr.nframes must always be 0 or 1.
+ */
+struct __attribute__ ((__packed__)) bcm_msg_one{
+ struct bcm_msg_head hdr;
+ struct can_frame frames[1];
+};
+
+bool CANSocketBCM::writeFrameOneTime(const can_frame& frame)
+{
+ struct bcm_msg_one bcms;
+
+ // fill in the header
+ memset(&bcms.hdr, 0, sizeof(bcms.hdr));
+ bcms.hdr.opcode = TX_SEND;
+ bcms.hdr.nframes = 1;
+ bcms.hdr.can_id = frame.can_id;
+
+ // copy the frame
+ memcpy(&bcms.frames[0], &frame, sizeof(frame));
+
+ // and write everything
+ ssize_t nbytes = ::write(mSocket, &bcms, sizeof(bcms));
+ return nbytes == sizeof(bcms);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketBCM::readMessage(CANFrameInfo& message)
+{
+ struct bcm_msg_one bcms;
+
+ // clear the destination
+ memset(&message, 0, sizeof(message));
+
+ // get data from socket
+ size_t nbytes = ::recv(mSocket, &bcms, sizeof(bcms), 0);
+ if ( nbytes < sizeof(bcms.hdr))
+ {
+ LOG_ERROR("Socket error");
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+ //TODO: implement better timestamps
+ message.timestamp = amb::currentTime();
+
+ switch (bcms.hdr.opcode)
+ {
+ case RX_CHANGED:
+ if (bcms.hdr.nframes >= 1 && nbytes == sizeof(bcms))
+ {
+ if (bcms.hdr.nframes > 1)
+ {
+ LOG_WARNING("Dropped " << bcms.hdr.nframes - 1 << " updates from CAN bus.");
+ }
+
+ // copy the first frame
+ memcpy(&message.frame, &bcms.frames[0], sizeof(bcms.frames[0]));
+ message.status = CANFrameInfo::CANMessageStatus::GOOD;
+ return CANSocket::CANSocketReadSuccess::READING_SUCCEEDED;
+ }
+ else
+ {
+ LOG_ERROR("Unexpected data from the socket"
+ << " " << bcms.hdr.opcode
+ << " " << bcms.hdr.nframes
+ << " " << nbytes);
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+ case RX_TIMEOUT:
+ memcpy(&message.frame, &bcms.frames[0], sizeof(bcms.frames[0]));
+ message.frame.can_id = bcms.hdr.can_id; //doubtful. Do we need to override this?
+ message.status = CANFrameInfo::CANMessageStatus::TIMEOUT;
+ return CANSocket::CANSocketReadSuccess::READING_SUCCEEDED;
+
+ case TX_EXPIRED:
+ // do nothing
+ return CANSocket::CANSocketReadSuccess::READING_TIMED_OUT;
+
+ default:
+ LOG_ERROR("Unexpected opcode " << bcms.hdr.opcode);
+ return CANSocket::CANSocketReadSuccess::READING_FAILED;
+ }
+}
+
+/*
+ 4.2.5 Broadcast Manager receive filter timers
+
+ The timer values ival1 or ival2 may be set to non-zero values at RX_SETUP.
+ When the SET_TIMER flag is set the timers are enabled:
+
+ ival1: Send RX_TIMEOUT when a received message is not received again within
+ the given time. When START_TIMER is set at RX_SETUP the timeout detection
+ is activated directly - even without a former CAN frame reception.
+
+ ival2: Throttle the received message rate down to the value of ival2. This
+ is useful to reduce messages for the application when the signal inside the
+ CAN frame is stateless as state changes within the ival2 periode may get
+ lost.
+*/
+
+bool CANSocketBCM::registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime)
+{
+ struct bcm_msg_head hdr;
+
+ // fill in the header
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.opcode = RX_SETUP;
+ // set RX_FILTER_ID | RX_CHECK_DLC because we don't differentiate messages by dlc or content yet. Only by id
+ // setting RX_ANNOUNCE_RESUME may lead to duplicates in data which should be filtered by amb core.
+ // However, we won't miss any data.
+ hdr.flags = RX_FILTER_ID | RX_CHECK_DLC | SETTIMER | STARTTIMER | RX_ANNOUNCE_RESUME;
+ hdr.nframes = 0;
+ hdr.can_id = canId;
+ hdr.ival1 = amb::Timestamp::toTimeval(maxCycleTime);
+ hdr.ival2 = amb::Timestamp::toTimeval(minCycleTime);
+
+ // and write
+ ssize_t nbytes = ::write(mSocket, &hdr, sizeof(hdr));
+ return nbytes == sizeof(hdr);
+}
+
+bool CANSocketBCM::unregisterMessageForReceive(int canId)
+{
+ struct bcm_msg_head hdr;
+
+ // fill in the header
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.opcode = RX_DELETE;
+ hdr.can_id = canId;
+
+ // and write
+ ssize_t nbytes = ::write(mSocket, &hdr, sizeof(hdr));
+ return nbytes == sizeof(hdr);
+}
+
diff --git a/plugins/common/cansocketbcm.h b/plugins/common/cansocketbcm.h
new file mode 100644
index 00000000..f5403bfc
--- /dev/null
+++ b/plugins/common/cansocketbcm.h
@@ -0,0 +1,122 @@
+/*
+Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKETBCM_H
+#define CANSOCKETBCM_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <net/if.h>
+#include <sys/poll.h>
+#include <string>
+#include <stdlib.h>
+#include <linux/can/bcm.h>
+#include <linux/can/raw.h>
+
+#include "cansocket.h"
+
+/**
+* \brief CAN Socket wrapper.
+* @class CANSocket
+*/
+class CANSocketBCM : public CANSocket
+{
+public:
+ CANSocketBCM();
+ virtual ~CANSocketBCM(){} /*LCOV_EXCL_LINE*/
+
+ /**
+ * Opens and initialize CAN socket
+ * @fn start
+ * @param ifName Name of the CAN bus network interface.
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Writes CAN frame using the socket
+ * @fn write
+ * @param message CAN frame with additional information
+ * @param bytesWritten Number of written bytes.
+ * @return True if no error occurs.
+ */
+ virtual bool write(const struct CANFrameInfo &message);
+ /**
+ * Try to read CAN frame
+ * @fn read
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
+ * @return Reading operation status code.
+ */
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
+ /**
+ * Registers CAN ID of a cyclic message for receiving
+ * @fn registerCyclicMessageForReceive
+ * @param canId CAN ID of the message.
+ * @param minCycleTime Minimal interval between messages in seconds. Set to 0 if not used.
+ * @param maxCycleTime Maximum interval between messages for timeout detection in seconds. Set to 0 if no timeout detection is necessary.
+ * @return True if registration succeeds.
+ */
+ virtual bool registerCyclicMessageForReceive(int canId, double minCycleTime, double maxCycleTime);
+ /**
+ * Unregisters CAN ID for receiving
+ * @fn unregisterMessageForReceive
+ * @param canId CAN ID of the message.
+ * @return True if de-registration succeeds.
+ */
+ virtual bool unregisterMessageForReceive(int canId);
+
+private:
+ /**
+ * @internal
+ */
+ bool createSocket();
+ bool locateInterfaceIndex(struct ifreq& ifr);
+ bool connectSocket(struct sockaddr_can& addr);
+ bool closeSocket();
+ int waitData(unsigned int timeout);
+ bool writeFrameOneTime(const can_frame& frame);
+ CANSocket::CANSocketReadSuccess readMessage(CANFrameInfo& message);
+
+private:
+ /**
+ * Socket file descriptor.
+ * @property mSocket
+ * @private
+ */
+ int mSocket;
+ /**
+ * Data structure describing a polling request.
+ * @property mPoll
+ * @private
+ */
+ struct pollfd mPoll;
+};
+
+#endif // CANSOCKETBCM_H
+
+/** @} */
diff --git a/plugins/common/cansocketraw.cpp b/plugins/common/cansocketraw.cpp
new file mode 100644
index 00000000..2ab5d4f7
--- /dev/null
+++ b/plugins/common/cansocketraw.cpp
@@ -0,0 +1,199 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include "logger.h"
+#include "cansocket.h"
+#include "cansocketraw.h"
+#include "timestamp.h"
+
+CANSocketRaw::CANSocketRaw() :
+ mSocket(-1)
+{
+ LOG_TRACE("");
+}
+
+bool CANSocketRaw::start(const char* ifName)
+{
+ LOG_TRACE("");
+
+ if(mSocket < 0) {
+ if(!createSocket()) {
+ LOG_ERROR("Socket error");
+ } else {
+ can_err_mask_t errorMask = 0xFFFFFFFF;
+ if(!enableCANErrors(errorMask)) {
+ LOG_ERROR("Socket error");
+ } else
+ if(!enableTimestamps()) {
+ LOG_ERROR("Socket error");
+ } else {
+ mPoll.fd = mSocket;
+ mPoll.events = POLLIN | POLLPRI;
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ifName);
+ if(!locateInterfaceIndex(ifr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ struct sockaddr_can addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+ if(!bindSocket(addr)) {
+ LOG_ERROR("Socket error");
+ stop();
+ } else {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+void CANSocketRaw::stop()
+{
+ LOG_TRACE("");
+
+ if(mSocket >= 0) {
+ closeSocket();
+ mSocket = -1;
+ }
+}
+
+bool CANSocketRaw::write(const struct CANFrameInfo &message)
+{
+ LOG_TRACE("");
+
+ return writeFrame(message.frame);
+}
+
+CANSocket::CANSocketReadSuccess CANSocketRaw::read(struct CANFrameInfo& message, unsigned int timeout)
+{
+ LOG_TRACE("timeout: " << timeout);
+
+ CANSocket::CANSocketReadSuccess success;
+ memset(&message, 0, sizeof(message));
+
+ switch(waitData(timeout)) {
+ case -1:
+ LOG_ERROR("reading error");
+ success = CANSocket::READING_FAILED;
+ break;
+ case 0:
+ success = CANSocket::READING_TIMED_OUT;
+ break;
+ default:
+ ssize_t nbytes = (int)readFrame(message.frame, message.timestamp);
+ message.status = CANFrameInfo::CANMessageStatus::GOOD;
+ success = nbytes > 0 ? CANSocket::READING_SUCCEEDED : CANSocket::READING_FAILED;
+ }
+
+ return success;
+}
+
+bool CANSocketRaw::createSocket()
+{
+ return ((mSocket = ::socket(PF_CAN, SOCK_RAW, CAN_RAW)) >= 0);
+}
+
+bool CANSocketRaw::enableTimestamps()
+{
+ const int timestamp = 1;
+
+ return (setsockopt(mSocket, SOL_SOCKET, SO_TIMESTAMP, &timestamp, sizeof(timestamp)) == 0);
+}
+
+bool CANSocketRaw::enableCANErrors(can_err_mask_t errorMask)
+{
+ return (setsockopt(mSocket, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &errorMask, sizeof(errorMask)) == 0);
+}
+
+bool CANSocketRaw::locateInterfaceIndex(struct ifreq& ifr)
+{
+ return (::ioctl(mSocket, SIOCGIFINDEX, &ifr) == 0);
+}
+
+bool CANSocketRaw::bindSocket(struct sockaddr_can& addr)
+{
+ return (::bind(mSocket, (struct sockaddr*)&addr, sizeof(addr)) == 0);
+}
+
+bool CANSocketRaw::closeSocket()
+{
+ return (::close(mSocket) == 0);
+}
+
+int CANSocketRaw::waitData(unsigned int timeout)
+{
+ return ::poll(&mPoll, 1, timeout);
+}
+
+bool CANSocketRaw::writeFrame(const can_frame& frame)
+{
+ return ::write(mSocket, &frame, sizeof(frame)) == sizeof(frame);
+}
+
+ssize_t CANSocketRaw::readFrame(can_frame& frame, double &timestamp)
+{
+ struct iovec io;
+ struct msghdr msgh;
+ struct cmsghdr *cmsg;
+
+ // prepare buffers
+ memset(&msgh, 0, sizeof(msgh));
+ io.iov_base=&frame;
+ io.iov_len=sizeof(can_frame);
+ msgh.msg_iov=&io;
+ msgh.msg_iovlen=1;
+ char buffer[1024];
+ msgh.msg_control=&buffer;
+ msgh.msg_controllen=sizeof(buffer);
+
+ // receive data
+ ssize_t nbytes = ::recvmsg(mSocket, &msgh, 0);
+
+ if (nbytes > 0 )
+ {
+ /* Receive auxiliary data in msgh */
+ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+ if (cmsg->cmsg_type == SO_TIMESTAMP) {
+ struct ::timeval *tv = (struct timeval*) CMSG_DATA(cmsg);
+
+ // convert the timestamp
+ timestamp = amb::Timestamp::fromTimeval(*tv);
+
+ break;
+ }
+ }
+ if (cmsg == NULL) {
+ /* No timestamp is provided by the socket. Use our own. */
+ timestamp = amb::Timestamp::instance()->epochTime();
+ }
+ }
+
+ return nbytes;
+}
diff --git a/plugins/common/cansocketraw.h b/plugins/common/cansocketraw.h
new file mode 100644
index 00000000..aca053df
--- /dev/null
+++ b/plugins/common/cansocketraw.h
@@ -0,0 +1,103 @@
+/*
+Copyright (C) 2012 Intel Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef CANSOCKETRAW_H
+#define CANSOCKETRAW_H
+
+/**
+ * \addtogroup libcanbus
+ * @{
+ */
+
+#include <net/if.h>
+#include <sys/poll.h>
+#include <string>
+#include <linux/can/raw.h>
+
+#include "cansocket.h"
+
+/**
+* \brief CAN Socket wrapper.
+* @class CANSocket
+*/
+class CANSocketRaw : public CANSocket
+{
+public:
+ CANSocketRaw();
+ virtual ~CANSocketRaw(){} /*LCOV_EXCL_LINE*/
+
+ /**
+ * Opens and initializes CAN socket
+ * @fn start
+ * @param ifName Name of the CAN bus network interface.
+ * @return True if no error occurs.
+ */
+ virtual bool start(const char* ifName);
+ /**
+ * Closes socket
+ * @fn stop
+ */
+ virtual void stop();
+ /**
+ * Writes CAN frame using the socket
+ * @fn write
+ * @param message CAN frame with additional information
+ * @return True if no error occurs.
+ */
+ virtual bool write(const struct CANFrameInfo &message);
+ /**
+ * Try to read CAN frame
+ * @fn read
+ * @param message Buffer for CAN frame with additional information
+ * @param timeout Timeout for reading in [ms].
+ * @return Reading operation status code.
+ */
+ virtual CANSocket::CANSocketReadSuccess read(struct CANFrameInfo& message, unsigned int timeout = 1000);
+
+private:
+ /**
+ * @internal
+ */
+ bool createSocket();
+ bool enableCANErrors(can_err_mask_t errorMask);
+ bool enableTimestamps();
+ bool locateInterfaceIndex(struct ifreq& ifr);
+ bool bindSocket(struct sockaddr_can &addr);
+ bool closeSocket();
+ int waitData(unsigned int timeout);
+ bool writeFrame(const struct can_frame &frame);
+ ssize_t readFrame(can_frame& frame, double &timestamp);
+
+private:
+ /**
+ * Socket file descriptor.
+ * @property mSocket
+ * @private
+ */
+ int mSocket;
+ /**
+ * Data structure describing a polling request.
+ * @property mPoll
+ * @private
+ */
+ struct pollfd mPoll;
+};
+
+#endif // CANSOCKETRAW_H
+
+/** @} */
diff --git a/plugins/common/cansocketreader.cpp b/plugins/common/cansocketreader.cpp
index a9663e7f..e5bb42e8 100644
--- a/plugins/common/cansocketreader.cpp
+++ b/plugins/common/cansocketreader.cpp
@@ -1,5 +1,7 @@
/*
Copyright (C) 2012 Intel Corporation
+Copyright (C) 2015 Cogent Embedded Inc.
+Copyright (C) 2015 Renesas Electronics Corporation
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -38,7 +40,11 @@ bool CANSocketReader::start()
{
LOG_TRACE("");
- return CUtil::Thread::start();
+ bool res = CUtil::Thread::start();
+
+ // try to set higher priority
+ if (res) res = setPriority(4);
+ return res;
}
void CANSocketReader::stop()
@@ -55,41 +61,71 @@ void CANSocketReader::run()
while(isRunnable()) {
- struct can_frame frame;
- int bytesRead;
+ CANFrameInfo message;
+ CANSocket::CANSocketReadSuccess success = mSocket.read(message);
+
+ switch(success)
+ {
+ case CANSocket::READING_SUCCEEDED:
+ dispatchMessage(message);
+ break;
- CANSocket::CANSocketReadSuccess success = mSocket.read(frame, bytesRead);
+ case CANSocket::READING_TIMED_OUT:
+ // read again
+ break;
- switch(success) {
case CANSocket::READING_FAILED:
+ default:
LOG_ERROR("reading failed");
mObserver.errorOccured(CANObserver::GENERAL_ERROR);
- return;
- case CANSocket::READING_TIMED_OUT:
- // read again
break;
- default: //CANSocketWrapper::READING_SUCCEEDED
- if(frame.can_id & CAN_ERR_FLAG) {
- frame.can_id &= (CAN_ERR_FLAG|CAN_ERR_MASK);
- mObserver.errorFrameReceived(frame);
- }
- else if(frame.can_id & CAN_RTR_FLAG){
- if(!(frame.can_id & CAN_EFF_FLAG)){
- frame.can_id &= CAN_SFF_MASK;
- }
- else{
- frame.can_id &= (~CAN_RTR_FLAG);
- }
- mObserver.remoteTransmissionRequest(frame);
- }
- else if(frame.can_id & CAN_EFF_FLAG){
- frame.can_id &= CAN_EFF_MASK;
- mObserver.extendedFrameReceived(frame);
+ }
+ }
+}
+
+void CANSocketReader::dispatchMessage(const CANFrameInfo &message)
+{
+ struct can_frame frame = message.frame;
+
+ switch (message.status)
+ {
+ case CANFrameInfo::CANMessageStatus::GOOD:
+ if(frame.can_id & CAN_ERR_FLAG) {
+ frame.can_id &= (CAN_ERR_FLAG|CAN_ERR_MASK);
+ mObserver.errorFrameReceived(frame);
+ }
+ else if( frame.can_id & CAN_RTR_FLAG){
+ if(!( frame.can_id & CAN_EFF_FLAG)){
+ frame.can_id &= CAN_SFF_MASK;
}
else{
- frame.can_id &= CAN_SFF_MASK;
- mObserver.standardFrameReceived(frame);
+ frame.can_id &= (~CAN_RTR_FLAG);
}
+ mObserver.remoteTransmissionRequest(frame);
}
+ else if(frame.can_id & CAN_EFF_FLAG){
+ frame.can_id &= CAN_EFF_MASK;
+ mObserver.extendedFrameReceived(frame);
+ }
+ else{
+ frame.can_id &= CAN_SFF_MASK;
+ mObserver.standardFrameReceived(frame);
+ }
+ break;
+
+ case CANFrameInfo::CANMessageStatus::TIMEOUT:
+ if(frame.can_id & CAN_EFF_FLAG)
+ frame.can_id &= CAN_EFF_MASK;
+ else
+ frame.can_id &= CAN_SFF_MASK;
+
+ mObserver.timeoutDetected(frame);
+ break;
+
+ default:
+ LOG_ERROR("Unexpected CAN message status " << message.status);
+ mObserver.errorOccured(CANObserver::GENERAL_ERROR);
+ break;
}
}
+
diff --git a/plugins/common/cansocketreader.h b/plugins/common/cansocketreader.h
index 623430ae..62d7ead7 100644
--- a/plugins/common/cansocketreader.h
+++ b/plugins/common/cansocketreader.h
@@ -66,6 +66,13 @@ private:
*/
virtual void run();
+ /**
+ * Proceseses CAN message received from SocketCAN and notifies mObserver.
+ * @fn dispatchMessage
+ * @param message CAN message to be processed. Unchanged.
+ */
+ virtual void dispatchMessage(const CANFrameInfo &message);
+
private:
/**
* #CANObserver instance reference
diff --git a/plugins/common/thread.cpp b/plugins/common/thread.cpp
index d9d9c999..504feb38 100644
--- a/plugins/common/thread.cpp
+++ b/plugins/common/thread.cpp
@@ -52,9 +52,9 @@ static void *PosixThreadProc(void *param)
thread->run();
gMutex.lock();
- --gActiveThreadCount;
- LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
- gMutex.unlock();
+ --gActiveThreadCount;
+ LOG_INFO("PosixThreadProc() - active threads: " << gActiveThreadCount);
+ gMutex.unlock();
return 0;
}
@@ -64,59 +64,84 @@ namespace CUtil{
////////////////////////////////////////////////
Thread::Thread() :
- thread(0),
- runnableFlag(false)
+ thread(0),
+ runnableFlag(false)
{
- pthread_cond_init( &cond, NULL );
- pthread_mutex_init( &mutex, NULL );
+ pthread_cond_init( &cond, NULL );
+ pthread_mutex_init( &mutex, NULL );
}
bool Thread::start()
{
- pthread_mutex_lock(&mutex);
- if (runnableFlag) {// already running
- pthread_mutex_unlock(&mutex);
- return false;
- }
- // try to run
- if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
+ pthread_mutex_lock(&mutex);
+ if (runnableFlag) {// already running
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+ // try to run
+ if (pthread_create(&thread, NULL/*&thread_attr*/, PosixThreadProc, this) != 0) {
//pthread_attr_destroy(&thread_attr);
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
return false;
}
//pthread_attr_destroy(&thread_attr);
- runnableFlag = true;
- pthread_mutex_unlock(&mutex);
+ runnableFlag = true;
+ pthread_mutex_unlock(&mutex);
+ return true;
+}
+
+
+bool Thread::setPriority(int priority)
+{
+ pthread_mutex_lock(&mutex);
+ if (!runnableFlag) {// not running yet or terminated already
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+
+ priority = priority < 1 ? 1 : priority;
+ priority = priority < 99 ? priority : 99;
+
+ // set priority
+ struct sched_param pr;
+ pr.__sched_priority = priority;
+ if (pthread_setschedparam(thread, SCHED_FIFO, &pr) < 0)
+ {
+ pthread_mutex_unlock(&mutex);
+ return false;
+ }
+
+ pthread_mutex_unlock(&mutex);
return true;
}
Thread::~Thread()
{
stop();
- pthread_cond_destroy( &cond );
- pthread_mutex_destroy( &mutex );
- thread = 0;
+ pthread_cond_destroy( &cond );
+ pthread_mutex_destroy( &mutex );
+ thread = 0;
}
void Thread::stop()
{
if (setRunnableFlag(false) == true) {
- if( thread != 0 ){
- if (thread == pthread_self()){
- int s = pthread_detach(thread);
- ((void)s);// prevent compiler warning in RELEASE build
- LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
- }
- else{
- int s = pthread_join(thread, NULL);
- if (s != 0){
- LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
- }
- else{
- LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
- }
- }
- thread = 0;
+ if( thread != 0 ){
+ if (thread == pthread_self()){
+ int s = pthread_detach(thread);
+ ((void)s);// prevent compiler warning in RELEASE build
+ LOG_MESSAGE("Thread::stop() - thread " << std::hex << int(thread) << std::dec << " detached, returned value was " << s);
+ }
+ else{
+ int s = pthread_join(thread, NULL);
+ if (s != 0){
+ LOG_ERROR("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ else{
+ LOG_MESSAGE("Thread::stop() - Joined with thread " << std::hex << int(thread) << std::dec << ", returned value was " << s);
+ }
+ }
+ thread = 0;
}
}
return;
@@ -124,44 +149,44 @@ void Thread::stop()
bool Thread::setRunnableFlag(bool flag)
{
- pthread_mutex_lock(&mutex);
- bool retval(runnableFlag);
- runnableFlag = flag;
-
- if(!runnableFlag)
- pthread_cond_signal(&cond);
- pthread_mutex_unlock(&mutex);
- return retval;
+ pthread_mutex_lock(&mutex);
+ bool retval(runnableFlag);
+ runnableFlag = flag;
+
+ if(!runnableFlag)
+ pthread_cond_signal(&cond);
+ pthread_mutex_unlock(&mutex);
+ return retval;
}
bool Thread::isRunnable(long miliseconds)
{
- bool runnable(false);
+ bool runnable(false);
- pthread_mutex_lock(&mutex);
- if (miliseconds != 0){
- wait(miliseconds);
- }
- runnable = runnableFlag;
+ pthread_mutex_lock(&mutex);
+ if (miliseconds != 0){
+ wait(miliseconds);
+ }
+ runnable = runnableFlag;
- pthread_mutex_unlock(&mutex);
+ pthread_mutex_unlock(&mutex);
return runnable;
}
bool Thread::wait( long miliseconds )
{
- struct timespec abstime;
- clock_gettime(CLOCK_REALTIME, &abstime);
- abstime.tv_sec += ( miliseconds / 1000 );
- miliseconds %= 1000;
- abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
- if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
- abstime.tv_sec += 1; // +1s
- abstime.tv_nsec -= 1000000000L; // -1s
- }
-
- int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
- return ( status == ETIMEDOUT );
+ struct timespec abstime;
+ clock_gettime(CLOCK_REALTIME, &abstime);
+ abstime.tv_sec += ( miliseconds / 1000 );
+ miliseconds %= 1000;
+ abstime.tv_nsec += ( miliseconds * 1000000L ); // in nanoseconds
+ if ( abstime.tv_nsec > 1000000000L /* > 1s */ ){
+ abstime.tv_sec += 1; // +1s
+ abstime.tv_nsec -= 1000000000L; // -1s
+ }
+
+ int status = pthread_cond_timedwait( &cond, &mutex, &abstime );
+ return ( status == ETIMEDOUT );
}
}
diff --git a/plugins/common/thread.h b/plugins/common/thread.h
index 8879b5b4..7bc26f21 100644
--- a/plugins/common/thread.h
+++ b/plugins/common/thread.h
@@ -127,6 +127,15 @@ public:
virtual bool start();
/**
+ * Sets the priority of the thread for FIFO scheduling.
+ * @fn set_priority
+ * @param priority Integer ranging from 1 (lowest) to 99 (highest).
+ * @return True if the operation was successful.
+ * @public
+ */
+ bool setPriority(int priority);
+
+ /**
* Stops the thread
* @fn stop
* @public
diff --git a/plugins/dbus/dbusinterfacemanager.cpp b/plugins/dbus/dbusinterfacemanager.cpp
index 4006d50a..b556fd14 100644
--- a/plugins/dbus/dbusinterfacemanager.cpp
+++ b/plugins/dbus/dbusinterfacemanager.cpp
@@ -51,7 +51,7 @@ on_bus_acquired (GDBusConnection *connection, const gchar *name, gpointer user_d
{
DBusInterfaceManager* iface = static_cast<DBusInterfaceManager*>(user_data);
- iface->connection = std::shared_ptr<GDBusConnection>(connection, [=](auto conn){
+ iface->connection = std::shared_ptr<GDBusConnection>(connection, [=](GDBusConnection* conn){
amb::traits<GDBusConnection>::delete_functor functor;
functor(conn);
});