XenomaiRTCANDriver.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef __XenomaiRTCANDriver_h__
00041 #define __XenomaiRTCANDriver_h__
00042
00043 #include <stdio.h>
00044 #include <rtdm/rtcan.h>
00045 #include <string.h>
00046 #include <sys/mman.h>
00047
00048 #include "util/CommandLineParameterGenerator.h"
00049
00050 #include "debug.h"
00051
00052 #include "mw/nl/can/canID_LE_PC.h"
00053
00054 namespace device {
00055 namespace nic {
00056 namespace CAN {
00057
00058 CLP1(XenomaiRTCANOptions,
00059 "XenomaiRT CAN Driver",
00060 "scan,s",
00061 "The device that is used\n"
00062 "(e.g. rtcan0 (default))",
00063 std::string, device, "rtcan0");
00064
00068 template < typename IDDesc = famouso::mw::nl::CAN::detail::famouso_CAN_ID_LE_PC >
00069 class XenomaiRTCANDriver {
00070 public:
00071
00072 class MOB : private can_frame {
00073 public:
00074 typedef famouso::mw::nl::CAN::detail::ID <
00075 IDDesc
00076 > IDType;
00077
00078 void extended() {
00079 can_id |= CAN_EFF_FLAG;
00080 }
00081 IDType& id() {
00082 return *reinterpret_cast<IDType*>(&can_id);
00083 }
00084 uint8_t& len() {
00085 return can_dlc;
00086 }
00087 void len(uint8_t l) {
00088 can_dlc = l;
00089 }
00090 uint8_t *data() {
00091 return can_frame::data;
00092 }
00093 void data(uint8_t *) {}
00094 uint8_t &data(uint8_t i) {
00095 return can_frame::data[i];
00096 }
00097 explicit MOB() {
00098 can_id = 0;
00099 }
00100 };
00101
00102 explicit XenomaiRTCANDriver() : _can_socket(0) {
00103 }
00104
00105 ~XenomaiRTCANDriver() {
00106 rt_dev_close(_can_socket);
00107 }
00108
00109 void report_error_and_exit(int error_value, const char* reporter) {
00110 const char *error = 0;
00111 switch (error_value) {
00112 case -ETIMEDOUT:
00113 error = "timed out";
00114 break;
00115 case -EBADF:
00116 error = "aborted because socket was closed";
00117 break;
00118 default:
00119 error = strerror (-error_value);
00120 break;
00121 }
00122
00123 ::logging::log::emit< ::logging::Error>() << reporter
00124 << error << ::logging::log::endl;
00125 exit(errno);
00126 }
00127
00135 bool read(MOB& mob) {
00136 int ret = 0;
00137 if ((ret = rt_dev_recv(_can_socket, &mob, sizeof(MOB), 0)) != sizeof(MOB) ) {
00138 report_error_and_exit(ret,"__FILE__:__LINE__ : rt_dev_recv ");
00139 }
00140 return true;
00141 }
00142
00147 void write(MOB &mob) {
00148
00149 int ret = 0;
00150 if ( (ret = rt_dev_send(_can_socket, &mob, sizeof(mob), 0)) != sizeof(MOB)) {
00151 report_error_and_exit(ret,"__FILE__:__LINE__ : rt_dev_send ");
00152 }
00153 }
00154
00156 void init() {
00157 CLP::config::XenomaiRTCANOptions::Parameter param;
00158 CLP::config::XenomaiRTCANOptions::instance().getParameter(param);
00159
00160 struct sockaddr_can addr;
00161 struct ifreq ifr;
00162 if ((_can_socket = rt_dev_socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
00163 ::logging::log::emit< ::logging::Error>()
00164 << "can't create XenomaiRTCAN socket"
00165 << ::logging::log::endl;
00166 exit(errno);
00167 }
00168 strcpy(ifr.ifr_name, param.device.c_str());
00169 if (rt_dev_ioctl(_can_socket, SIOCGIFINDEX, &ifr) < 0) {
00170 ::logging::log::emit< ::logging::Error>()
00171 << "SIOCGIFINDEX " << param.device.c_str()
00172 << "no such CAN device found."
00173 << ::logging::log::endl;
00174 exit(errno);
00175 }
00176 addr.can_family = AF_CAN;
00177 addr.can_ifindex = ifr.ifr_ifindex;
00178
00179 if (rt_dev_bind(_can_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00180 ::logging::log::emit< ::logging::Error>()
00181 << "can't bind CAN device " << param.device.c_str()
00182 << ::logging::log::endl;
00183 exit(errno);
00184 }
00185 }
00186
00187 private:
00191 int _can_socket;
00192
00193 };
00194
00195 void fnc() __attribute__((constructor));
00196 void fnc() {
00197 mlockall (MCL_CURRENT | MCL_FUTURE);
00198 }
00199 }
00200 }
00201 }
00202
00203 #endif
00204