Apollo 11.0
自动驾驶开放平台
socket_can_client_raw.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
24
25#include "absl/strings/str_cat.h"
26
28
29namespace apollo {
30namespace drivers {
31namespace canbus {
32namespace can {
33
34#define CAN_ID_MASK 0x1FFFF800U // can_filter mask
35#define CAN_STANDARD_MAX_ID 0x7FFU
36
38
40 if (!parameter.has_channel_id()) {
41 AERROR << "Init CAN failed: parameter does not have channel id. The "
42 "parameter is "
43 << parameter.DebugString();
44 return false;
45 }
46
47 port_ = parameter.channel_id();
48 interface_ = parameter.interface();
49 auto num_ports = parameter.num_ports();
50 if (port_ > static_cast<int32_t>(num_ports) || port_ < 0) {
51 AERROR << "Can port number [" << port_ << "] is out of range [0, "
52 << num_ports << ") !";
53 return false;
54 }
55 return true;
56}
57
59 if (dev_handler_) {
60 Stop();
61 }
62}
63
65 if (is_started_) {
66 return ErrorCode::OK;
67 }
68 struct sockaddr_can addr;
69 struct ifreq ifr;
70
71 // open device
72 // guss net is the device minor number, if one card is 0,1
73 // if more than one card, when install driver u can specify the minior id
74 // int32_t ret = canOpen(net, pCtx->mode, txbufsize, rxbufsize, 0, 0,
75 // &dev_handler_);
76 dev_handler_ = socket(PF_CAN, SOCK_RAW, CAN_RAW);
77 if (dev_handler_ < 0) {
78 AERROR << "open device error code [" << dev_handler_ << "]: ";
79 return ErrorCode::CAN_CLIENT_ERROR_BASE;
80 }
81
82 // init config and state
83 int ret;
84
85 // 1. for non virtual busses, set receive message_id filter, ie white list
86 if (interface_ != CANCardParameter::VIRTUAL) {
87 // set a scope for each EID instead of a single filter rule for each EID
88 struct can_filter filter[1];
89 // filter[0].can_mask = CAN_ID_MASK;
90 // all EID without filter
91 filter[0].can_id = 0x000;
92 filter[0].can_mask = 0x000;
93
94 ret = setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FILTER, &filter,
95 sizeof(filter));
96 if (ret < 0) {
97 AERROR << "add receive msg id filter error code: " << ret;
98 return ErrorCode::CAN_CLIENT_ERROR_BASE;
99 }
100 }
101
102 // 2. enable reception of can frames.
103 int enable = 1;
104 ret = ::setsockopt(dev_handler_, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable,
105 sizeof(enable));
106 if (ret < 0) {
107 AERROR << "enable reception of can frame error code: " << ret;
108 return ErrorCode::CAN_CLIENT_ERROR_BASE;
109 }
110
111 std::string interface_prefix;
112 if (interface_ == CANCardParameter::VIRTUAL) {
113 interface_prefix = "vcan";
114 } else if (interface_ == CANCardParameter::SLCAN) {
115 interface_prefix = "slcan";
116 } else { // default: CANCardParameter::NATIVE
117 interface_prefix = "can";
118 }
119
120 const std::string can_name = absl::StrCat(interface_prefix, port_);
121 std::strncpy(ifr.ifr_name, can_name.c_str(), IFNAMSIZ);
122 if (ioctl(dev_handler_, SIOCGIFINDEX, &ifr) < 0) {
123 AERROR << "ioctl error";
124 return ErrorCode::CAN_CLIENT_ERROR_BASE;
125 }
126
127 // bind socket to network interface
128
129 addr.can_family = AF_CAN;
130 addr.can_ifindex = ifr.ifr_ifindex;
131 ret = ::bind(dev_handler_, reinterpret_cast<struct sockaddr *>(&addr),
132 sizeof(addr));
133
134 if (ret < 0) {
135 AERROR << "bind socket to network interface error code: " << ret;
136 return ErrorCode::CAN_CLIENT_ERROR_BASE;
137 }
138
139 is_started_ = true;
140 return ErrorCode::OK;
141}
142
144 if (is_started_) {
145 is_started_ = false;
146
147 int ret = close(dev_handler_);
148 if (ret < 0) {
149 AERROR << "close error code:" << ret << ", " << GetErrorString(ret);
150 } else {
151 AINFO << "close socket can ok. port:" << port_;
152 }
153 }
154}
155
156// Synchronous transmission of CAN messages
157ErrorCode SocketCanClientRaw::Send(const std::vector<CanFrame> &frames,
158 int32_t *const frame_num) {
159 CHECK_NOTNULL(frame_num);
160 CHECK_EQ(frames.size(), static_cast<size_t>(*frame_num));
161
162 if (!is_started_) {
163 AERROR << "Nvidia can client has not been initiated! Please init first!";
164 return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
165 }
166 for (size_t i = 0; i < frames.size() && i < MAX_CAN_SEND_FRAME_LEN; ++i) {
167 if (frames[i].len > CANBUS_MESSAGE_LENGTH || frames[i].len < 0) {
168 AERROR << "frames[" << i << "].len = " << frames[i].len
169 << ", which is not equal to can message data length ("
170 << CANBUS_MESSAGE_LENGTH << ").";
171 return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
172 }
173 if (frames[i].id > CAN_STANDARD_MAX_ID) {
174 send_frames_[i].can_id = (frames[i].id & CAN_EFF_MASK) | CAN_EFF_FLAG;
175 } else {
176 send_frames_[i].can_id = (frames[i].id & CAN_SFF_MASK);
177 }
178 ADEBUG << "send can id is " << send_frames_[i].can_id;
179 send_frames_[i].can_dlc = frames[i].len;
180 std::memcpy(send_frames_[i].data, frames[i].data, frames[i].len);
181
182 // Synchronous transmission of CAN messages
183 int ret = static_cast<int>(
184 write(dev_handler_, &send_frames_[i], sizeof(send_frames_[i])));
185 if (ret <= 0) {
186 AERROR << "send message failed, error code: " << ret;
187 return ErrorCode::CAN_CLIENT_ERROR_BASE;
188 }
189 }
190
191 return ErrorCode::OK;
192}
193
194// buf size must be 8 bytes, every time, we receive only one frame
195ErrorCode SocketCanClientRaw::Receive(std::vector<CanFrame> *const frames,
196 int32_t *const frame_num) {
197 if (!is_started_) {
198 AERROR << "Nvidia can client is not init! Please init first!";
199 return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
200 }
201
202 if (*frame_num > MAX_CAN_RECV_FRAME_LEN || *frame_num < 0) {
203 AERROR << "recv can frame num not in range[0, " << MAX_CAN_RECV_FRAME_LEN
204 << "], frame_num:" << *frame_num;
205 // TODO(Authors): check the difference of returning frame_num/error_code
206 return ErrorCode::CAN_CLIENT_ERROR_FRAME_NUM;
207 }
208
209 for (int32_t i = 0; i < *frame_num && i < MAX_CAN_RECV_FRAME_LEN; ++i) {
210 CanFrame cf;
211 auto ret = read(dev_handler_, &recv_frames_[i], sizeof(recv_frames_[i]));
212
213 if (ret < 0) {
214 AERROR << "receive message failed, error code: " << ret;
215 return ErrorCode::CAN_CLIENT_ERROR_BASE;
216 }
217 if (recv_frames_[i].can_dlc > CANBUS_MESSAGE_LENGTH ||
218 recv_frames_[i].can_dlc < 0) {
219 AERROR << "recv_frames_[" << i
220 << "].can_dlc = " << recv_frames_[i].can_dlc
221 << ", which is not equal to can message data length ("
222 << CANBUS_MESSAGE_LENGTH << ").";
223 return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
224 }
225 if (recv_frames_[i].can_id > CAN_STANDARD_MAX_ID) {
226 cf.id = FLAGS_enable_can_err_check
227 ? recv_frames_[i].can_id & CAN_EFF_MASK | CAN_ERR_FLAG
228 : recv_frames_[i].can_id & CAN_EFF_MASK;
229 } else {
230 cf.id = (recv_frames_[i].can_id & CAN_SFF_MASK);
231 }
232 ADEBUG << "Socket can receive can id is " << recv_frames_[i].can_id;
233 cf.len = recv_frames_[i].can_dlc;
234 std::memcpy(cf.data, recv_frames_[i].data, recv_frames_[i].can_dlc);
235 frames->push_back(cf);
236 }
237 return ErrorCode::OK;
238}
239
240std::string SocketCanClientRaw::GetErrorString(const int32_t /*status*/) {
241 return "";
242}
243
244} // namespace can
245} // namespace canbus
246} // namespace drivers
247} // namespace apollo
bool is_started_
The CAN client is started.
Definition can_client.h:165
void Stop() override
Stop the ESD CAN client.
apollo::common::ErrorCode Send(const std::vector< CanFrame > &frames, int32_t *const frame_num) override
Send messages
apollo::common::ErrorCode Start() override
Start the ESD CAN client.
apollo::common::ErrorCode Receive(std::vector< CanFrame > *const frames, int32_t *const frame_num) override
Receive messages
bool Init(const CANCardParameter &parameter) override
Initialize the ESD CAN client by specified CAN card parameters.
std::string GetErrorString(const int32_t status) override
Get the error string.
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
const int32_t MAX_CAN_RECV_FRAME_LEN
const int32_t CANBUS_MESSAGE_LENGTH
const int32_t MAX_CAN_SEND_FRAME_LEN
class register implement
Definition arena_queue.h:37
#define CAN_STANDARD_MAX_ID
Defines the SocketCanClientRaw class which inherits CanClient.
The class which defines the information to send and receive.
Definition can_client.h:48
uint8_t len
Message length
Definition can_client.h:52
uint8_t data[8]
Message content
Definition can_client.h:54