Go to the documentation of this file.00001 #ifndef H_CAN_LAYER
00002 #define H_CAN_LAYER
00003
00004 #include <socketcan_interface/threading.h>
00005 #include "layer.h"
00006
00007 namespace canopen{
00008
00009 class CANLayer: public Layer{
00010 boost::mutex mutex_;
00011 boost::shared_ptr<can::DriverInterface> driver_;
00012 const std::string device_;
00013 const bool loopback_;
00014 can::Frame last_error_;
00015 can::CommInterface::FrameListener::Ptr error_listener_;
00016 void handleFrame(const can::Frame & msg){
00017 boost::mutex::scoped_lock lock(mutex_);
00018 last_error_ = msg;
00019 LOG("ID: " << msg.id);
00020 }
00021 boost::shared_ptr<boost::thread> thread_;
00022
00023 public:
00024 CANLayer(const boost::shared_ptr<can::DriverInterface> &driver, const std::string &device, bool loopback)
00025 : Layer(device + " Layer"), driver_(driver), device_(device), loopback_(loopback) { assert(driver_); }
00026
00027 virtual void handleRead(LayerStatus &status, const LayerState ¤t_state) {
00028 if(current_state > Init){
00029 if(!driver_->getState().isReady()) status.error("CAN not ready");
00030 }
00031 }
00032 virtual void handleWrite(LayerStatus &status, const LayerState ¤t_state) {
00033 if(current_state > Init){
00034 if(!driver_->getState().isReady()) status.error("CAN not ready");
00035 }
00036 }
00037
00038 virtual void handleDiag(LayerReport &report){
00039 can::State s = driver_->getState();
00040 if(!s.isReady()){
00041 report.error("CAN layer not ready");
00042 report.add("driver_state", int(s.driver_state));
00043 }
00044 if(s.error_code){
00045 report.add("socket_error", s.error_code);
00046 }
00047 if(s.internal_error != 0){
00048 report.add("internal_error", int(s.internal_error));
00049 std::string desc;
00050 if(driver_->translateError(s.internal_error, desc)) report.add("internal_error_desc", desc);
00051 std::stringstream sstr;
00052 sstr << std::hex;
00053 {
00054 boost::mutex::scoped_lock lock(mutex_);
00055 for(size_t i=0; i < last_error_.dlc; ++i){
00056 sstr << (unsigned int) last_error_.data[i] << " ";
00057 }
00058 }
00059 report.add("can_error_frame", sstr.str());
00060
00061 }
00062
00063 }
00064
00065 virtual void handleInit(LayerStatus &status){
00066 if(thread_){
00067 status.warn("CAN thread already running");
00068 } else if(!driver_->init(device_, loopback_)) {
00069 status.error("CAN init failed");
00070 } else {
00071 can::StateWaiter waiter(driver_.get());
00072
00073 thread_.reset(new boost::thread(&can::DriverInterface::run, driver_));
00074 error_listener_ = driver_->createMsgListener(can::ErrorHeader(), can::CommInterface::FrameDelegate(this, &CANLayer::handleFrame));
00075
00076 if(!waiter.wait(can::State::ready, boost::posix_time::seconds(1))){
00077 status.error("CAN init timed out");
00078 }
00079 }
00080 if(!driver_->getState().isReady()){
00081 status.error("CAN is not ready");
00082 }
00083 }
00084 virtual void handleShutdown(LayerStatus &status){
00085 can::StateWaiter waiter(driver_.get());
00086 error_listener_.reset();
00087 driver_->shutdown();
00088 if(!waiter.wait(can::State::closed, boost::posix_time::seconds(1))){
00089 status.warn("CAN shutdown timed out");
00090 }
00091 if(thread_){
00092 thread_->interrupt();
00093 thread_->join();
00094 thread_.reset();
00095 }
00096 }
00097
00098 virtual void handleHalt(LayerStatus &status) { }
00099
00100 virtual void handleRecover(LayerStatus &status){
00101 if(!driver_->getState().isReady()){
00102 handleShutdown(status);
00103 handleInit(status);
00104 }
00105 }
00106
00107 };
00108 }
00109
00110 #endif