Go to the documentation of this file.00001 #ifndef H_CAN_BCM
00002 #define H_CAN_BCM
00003
00004 #include <socketcan_interface/interface.h>
00005
00006 #include <sys/types.h>
00007 #include <sys/socket.h>
00008 #include <sys/ioctl.h>
00009 #include <net/if.h>
00010
00011 #include <linux/can.h>
00012 #include <linux/can/bcm.h>
00013 #include <linux/can/error.h>
00014
00015 namespace can {
00016
00017 class BCMsocket{
00018 int s_;
00019 struct Message {
00020 size_t size;
00021 uint8_t *data;
00022 Message(size_t n)
00023 : size(sizeof(bcm_msg_head) + sizeof(can_frame)*n), data(new uint8_t[size])
00024 {
00025 assert(n<=256);
00026 memset(data, 0, size);
00027 head().nframes = n;
00028 }
00029 bcm_msg_head& head() {
00030 return *(bcm_msg_head*)data;
00031 }
00032 template<typename T> void setIVal2(T period){
00033 long long usec = boost::chrono::duration_cast<boost::chrono::microseconds>(period).count();
00034 head().ival2.tv_sec = usec / 1000000;
00035 head().ival2.tv_usec = usec % 1000000;
00036 }
00037 void setHeader(Header header){
00038 head().can_id = header.id | (header.is_extended?CAN_EFF_FLAG:0);
00039 }
00040 bool write(int s){
00041 return ::write(s, data, size) > 0;
00042 }
00043 ~Message(){
00044 delete[] data;
00045 data = 0;
00046 size = 0;
00047 }
00048 };
00049 public:
00050 BCMsocket():s_(-1){
00051 }
00052 bool init(const std::string &device){
00053 s_ = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
00054
00055 if(s_ < 0 ) return false;
00056 struct ifreq ifr;
00057 strcpy(ifr.ifr_name, device.c_str());
00058 int ret = ioctl(s_, SIOCGIFINDEX, &ifr);
00059
00060 if(ret != 0){
00061 shutdown();
00062 return false;
00063 }
00064
00065 struct sockaddr_can addr = {0};
00066 addr.can_family = AF_CAN;
00067 addr.can_ifindex = ifr.ifr_ifindex;
00068
00069 ret = connect(s_, (struct sockaddr *)&addr, sizeof(addr));
00070
00071 if(ret < 0){
00072 shutdown();
00073 return false;
00074 }
00075 return true;
00076 }
00077 template<typename DurationType> bool startTX(DurationType period, Header header, size_t num, Frame *frames) {
00078 Message msg(num);
00079 msg.setHeader(header);
00080 msg.setIVal2(period);
00081
00082 bcm_msg_head &head = msg.head();
00083
00084 head.opcode = TX_SETUP;
00085 head.flags |= SETTIMER | STARTTIMER;
00086
00087 for(size_t i=0; i < num; ++i){
00088 head.frames[i].can_dlc = frames[i].dlc;
00089 head.frames[i].can_id = head.can_id;
00090 for(size_t j = 0; j < head.frames[i].can_dlc; ++j){
00091 head.frames[i].data[j] = frames[i].data[j];
00092 }
00093 }
00094 return msg.write(s_);
00095 }
00096 bool stopTX(Header header){
00097 Message msg(0);
00098 msg.head().opcode = TX_DELETE;
00099 msg.setHeader(header);
00100 return msg.write(s_);
00101 }
00102 void shutdown(){
00103 if(s_ > 0){
00104 close(s_);
00105 s_ = -1;
00106 }
00107 }
00108
00109 virtual ~BCMsocket(){
00110 shutdown();
00111 }
00112 };
00113
00114 }
00115
00116 #endif