SocketCANDriver.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 __SocketCANDriver_h__
00041 #define __SocketCANDriver_h__
00042
00043 #include <sys/types.h>
00044 #include <sys/socket.h>
00045 #include <sys/ioctl.h>
00046 #include <net/if.h>
00047
00048 #include "util/CommandLineParameterGenerator.h"
00049
00050 #include <boost/thread.hpp>
00051 #include <boost/bind.hpp>
00052 #include "debug.h"
00053 #include <stdint.h>
00054 #include <errno.h>
00055 #include <fcntl.h>
00056
00057 #include "mw/nl/can/canID_LE_PC.h"
00058
00059 #include <linux/can.h>
00060 #include <linux/can/raw.h>
00061
00062 #ifndef PF_CAN
00063 #define PF_CAN 29
00064 #endif
00065
00066 #ifndef AF_CAN
00067 #define AF_CAN PF_CAN
00068 #endif
00069
00070
00071 namespace device {
00072 namespace nic {
00073 namespace CAN {
00074
00075 CLP1(SocketCANOptions,
00076 "Socket CAN Driver",
00077 "scan,s",
00078 "The device that is used\n"
00079 "(e.g. can0 (default))",
00080 std::string, device, "can0");
00081
00085 template< typename IDDesc=famouso::mw::nl::CAN::detail::famouso_CAN_ID_LE_PC>
00086 class SocketCANDriver {
00087 public:
00088
00089 class MOB : private can_frame {
00090 public:
00091 typedef famouso::mw::nl::CAN::detail::ID<
00092 IDDesc
00093 > IDType;
00094
00095 void extended() {
00096 can_id |= CAN_EFF_FLAG;
00097 }
00098 IDType& id() {
00099 return *reinterpret_cast<IDType*>(&can_id);
00100 }
00101 uint8_t& len() {
00102 return can_dlc;
00103 }
00104 void len(uint8_t l) {
00105 can_dlc = l;
00106 }
00107 uint8_t *data() {
00108 return can_frame::data;
00109 }
00110 void data(uint8_t *) {}
00111 uint8_t &data(uint8_t i) {
00112 return can_frame::data[i];
00113 }
00114 explicit MOB() {can_id=0;}
00115 };
00116
00117 explicit SocketCANDriver() : _can_socket(0) {
00118 }
00119
00120 ~SocketCANDriver() {
00121 close(_can_socket);
00122 }
00123
00131 bool read(MOB& mob) {
00132 if (::read(_can_socket, &mob, sizeof(MOB)) == sizeof(MOB)) {
00133 return true;
00134 } else {
00135 return false;
00136 }
00137 }
00138
00143 void write(MOB &mob) {
00144
00145 if ( ::write(_can_socket, &mob, sizeof(mob)) != sizeof(mob)) {
00146 ::logging::log::emit< ::logging::Error>()
00147 << "error on writing on SocketCAN socket "
00148 << ::logging::log::endl;
00149 exit(errno);
00150 }
00151 }
00152
00154 void init() {
00155 CLP::config::SocketCANOptions::Parameter param;
00156 CLP::config::SocketCANOptions::instance().getParameter(param);
00157
00158 struct sockaddr_can addr;
00159 struct ifreq ifr;
00160 if ((_can_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
00161 ::logging::log::emit< ::logging::Error>()
00162 << "can't create SocketCAN socket"
00163 << ::logging::log::endl;
00164 exit(errno);
00165 }
00166 strcpy(ifr.ifr_name, param.device.c_str());
00167 if (ioctl(_can_socket, SIOCGIFINDEX, &ifr) < 0) {
00168 ::logging::log::emit< ::logging::Error>()
00169 << "SIOCGIFINDEX " << param.device.c_str()
00170 << "no such CAN device found."
00171 << ::logging::log::endl;
00172 exit(errno);
00173 }
00174 addr.can_ifindex = ifr.ifr_ifindex;
00175
00176 if (bind(_can_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00177 ::logging::log::emit< ::logging::Error>()
00178 << "can't bind CAN device " << param.device.c_str()
00179 << ::logging::log::endl;
00180 exit(errno);
00181 }
00182 }
00183
00184 private:
00188 int _can_socket;
00189 };
00190
00191 }
00192 }
00193 }
00194
00195 #endif
00196