1 /*
2 * Copyright (C) 2019 The Android Open Source Project
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
17 #include "CanBus.h"
18
19 #include "CloseHandle.h"
20
21 #include <android-base/logging.h>
22 #include <libnetdevice/can.h>
23 #include <libnetdevice/libnetdevice.h>
24 #include <linux/can.h>
25 #include <linux/can/error.h>
26 #include <linux/can/raw.h>
27
28 namespace android::hardware::automotive::can::V1_0::implementation {
29
30 /** Whether to log sent/received packets. */
31 static constexpr bool kSuperVerbose = false;
32
send(const CanMessage & message)33 Return<Result> CanBus::send(const CanMessage& message) {
34 std::lock_guard<std::mutex> lck(mIsUpGuard);
35 if (!mIsUp) return Result::INTERFACE_DOWN;
36
37 if (UNLIKELY(kSuperVerbose)) {
38 LOG(VERBOSE) << "Sending " << toString(message);
39 }
40
41 if (message.payload.size() > CAN_MAX_DLEN) return Result::PAYLOAD_TOO_LONG;
42
43 struct canfd_frame frame = {};
44 frame.can_id = message.id;
45 if (message.isExtendedId) frame.can_id |= CAN_EFF_FLAG;
46 if (message.remoteTransmissionRequest) frame.can_id |= CAN_RTR_FLAG;
47 frame.len = message.payload.size();
48 memcpy(frame.data, message.payload.data(), message.payload.size());
49
50 if (!mSocket->send(frame)) return Result::TRANSMISSION_FAILURE;
51
52 return Result::OK;
53 }
54
listen(const hidl_vec<CanMessageFilter> & filter,const sp<ICanMessageListener> & listenerCb,listen_cb _hidl_cb)55 Return<void> CanBus::listen(const hidl_vec<CanMessageFilter>& filter,
56 const sp<ICanMessageListener>& listenerCb, listen_cb _hidl_cb) {
57 std::lock_guard<std::mutex> lck(mIsUpGuard);
58
59 if (listenerCb == nullptr) {
60 _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
61 return {};
62 }
63 if (!mIsUp) {
64 _hidl_cb(Result::INTERFACE_DOWN, nullptr);
65 return {};
66 }
67
68 std::lock_guard<std::mutex> lckListeners(mMsgListenersGuard);
69
70 sp<CloseHandle> closeHandle = new CloseHandle([this, listenerCb]() {
71 std::lock_guard<std::mutex> lck(mMsgListenersGuard);
72 std::erase_if(mMsgListeners, [&](const auto& e) { return e.callback == listenerCb; });
73 });
74 mMsgListeners.emplace_back(CanMessageListener{listenerCb, filter, closeHandle});
75 auto& listener = mMsgListeners.back();
76
77 // fix message IDs to have all zeros on bits not covered by mask
78 std::for_each(listener.filter.begin(), listener.filter.end(),
79 [](auto& rule) { rule.id &= rule.mask; });
80
81 _hidl_cb(Result::OK, closeHandle);
82 return {};
83 }
84
CanBus()85 CanBus::CanBus() {}
86
CanBus(const std::string & ifname)87 CanBus::CanBus(const std::string& ifname) : mIfname(ifname) {}
88
~CanBus()89 CanBus::~CanBus() {
90 std::lock_guard<std::mutex> lck(mIsUpGuard);
91 CHECK(!mIsUp) << "Interface is still up while being destroyed";
92
93 std::lock_guard<std::mutex> lckListeners(mMsgListenersGuard);
94 CHECK(mMsgListeners.empty()) << "Listener list is not empty while interface is being destroyed";
95 }
96
setErrorCallback(ErrorCallback errcb)97 void CanBus::setErrorCallback(ErrorCallback errcb) {
98 CHECK(!mIsUp) << "Can't set error callback while interface is up";
99 CHECK(mErrCb == nullptr) << "Error callback is already set";
100 mErrCb = errcb;
101 CHECK(!mIsUp) << "Can't set error callback while interface is up";
102 }
103
preUp()104 ICanController::Result CanBus::preUp() {
105 return ICanController::Result::OK;
106 }
107
postDown()108 bool CanBus::postDown() {
109 return true;
110 }
111
up()112 ICanController::Result CanBus::up() {
113 std::lock_guard<std::mutex> lck(mIsUpGuard);
114
115 if (mIsUp) {
116 LOG(WARNING) << "Interface is already up";
117 return ICanController::Result::INVALID_STATE;
118 }
119
120 const auto preResult = preUp();
121 if (preResult != ICanController::Result::OK) return preResult;
122
123 const auto isUp = netdevice::isUp(mIfname);
124 if (!isUp.has_value()) {
125 // preUp() should prepare the interface (either create or make sure it's there)
126 LOG(ERROR) << "Interface " << mIfname << " didn't get prepared";
127 return ICanController::Result::BAD_INTERFACE_ID;
128 }
129
130 if (!*isUp && !netdevice::up(mIfname)) {
131 LOG(ERROR) << "Can't bring " << mIfname << " up";
132 return ICanController::Result::UNKNOWN_ERROR;
133 }
134 mDownAfterUse = !*isUp;
135
136 using namespace std::placeholders;
137 CanSocket::ReadCallback rdcb = std::bind(&CanBus::onRead, this, _1, _2);
138 CanSocket::ErrorCallback errcb = std::bind(&CanBus::onError, this, _1);
139 mSocket = CanSocket::open(mIfname, rdcb, errcb);
140 if (!mSocket) {
141 if (mDownAfterUse) netdevice::down(mIfname);
142 return ICanController::Result::UNKNOWN_ERROR;
143 }
144
145 mIsUp = true;
146 return ICanController::Result::OK;
147 }
148
clearMsgListeners()149 void CanBus::clearMsgListeners() {
150 std::vector<wp<ICloseHandle>> listenersToClose;
151 {
152 std::lock_guard<std::mutex> lck(mMsgListenersGuard);
153 std::transform(mMsgListeners.begin(), mMsgListeners.end(),
154 std::back_inserter(listenersToClose),
155 [](const auto& e) { return e.closeHandle; });
156 }
157
158 for (auto& weakListener : listenersToClose) {
159 /* Between populating listenersToClose and calling close method here, some listeners might
160 * have been already removed from the original mMsgListeners list (resulting in a dangling
161 * weak pointer here). It's fine - we just want to clean them up. */
162 auto listener = weakListener.promote();
163 if (listener != nullptr) listener->close();
164 }
165
166 std::lock_guard<std::mutex> lck(mMsgListenersGuard);
167 CHECK(mMsgListeners.empty()) << "Listeners list wasn't emptied";
168 }
169
clearErrListeners()170 void CanBus::clearErrListeners() {
171 std::lock_guard<std::mutex> lck(mErrListenersGuard);
172 mErrListeners.clear();
173 }
174
listenForErrors(const sp<ICanErrorListener> & listener)175 Return<sp<ICloseHandle>> CanBus::listenForErrors(const sp<ICanErrorListener>& listener) {
176 if (listener == nullptr) {
177 return new CloseHandle();
178 }
179
180 std::lock_guard<std::mutex> upLck(mIsUpGuard);
181 if (!mIsUp) {
182 listener->onError(ErrorEvent::INTERFACE_DOWN, true);
183 return new CloseHandle();
184 }
185
186 std::lock_guard<std::mutex> errLck(mErrListenersGuard);
187 mErrListeners.emplace_back(listener);
188
189 return new CloseHandle([this, listener]() {
190 std::lock_guard<std::mutex> lck(mErrListenersGuard);
191 std::erase(mErrListeners, listener);
192 });
193 }
194
down()195 bool CanBus::down() {
196 std::lock_guard<std::mutex> lck(mIsUpGuard);
197
198 if (!mIsUp) {
199 LOG(WARNING) << "Interface is already down";
200 return false;
201 }
202 mIsUp = false;
203
204 clearMsgListeners();
205 clearErrListeners();
206 mSocket.reset();
207
208 bool success = true;
209
210 if (mDownAfterUse && !netdevice::down(mIfname)) {
211 LOG(ERROR) << "Can't bring " << mIfname << " down";
212 // don't return yet, let's try to do best-effort cleanup
213 success = false;
214 }
215
216 if (!postDown()) success = false;
217
218 return success;
219 }
220
221 /**
222 * Helper function to determine if a flag meets the requirements of a
223 * FilterFlag. See definition of FilterFlag in types.hal
224 *
225 * \param filterFlag FilterFlag object to match flag against
226 * \param flag bool object from CanMessage object
227 */
satisfiesFilterFlag(FilterFlag filterFlag,bool flag)228 static bool satisfiesFilterFlag(FilterFlag filterFlag, bool flag) {
229 if (filterFlag == FilterFlag::DONT_CARE) return true;
230 if (filterFlag == FilterFlag::SET) return flag;
231 if (filterFlag == FilterFlag::NOT_SET) return !flag;
232 return false;
233 }
234
235 /**
236 * Match the filter set against message id.
237 *
238 * For details on the filters syntax, please see CanMessageFilter at
239 * the HAL definition (types.hal).
240 *
241 * \param filter Filter to match against
242 * \param id Message id to filter
243 * \return true if the message id matches the filter, false otherwise
244 */
match(const hidl_vec<CanMessageFilter> & filter,CanMessageId id,bool isRtr,bool isExtendedId)245 static bool match(const hidl_vec<CanMessageFilter>& filter, CanMessageId id, bool isRtr,
246 bool isExtendedId) {
247 if (filter.size() == 0) return true;
248
249 bool anyNonExcludeRulePresent = false;
250 bool anyNonExcludeRuleSatisfied = false;
251 for (auto& rule : filter) {
252 const bool satisfied = ((id & rule.mask) == rule.id) &&
253 satisfiesFilterFlag(rule.rtr, isRtr) &&
254 satisfiesFilterFlag(rule.extendedFormat, isExtendedId);
255
256 if (rule.exclude) {
257 // Any excluded (blacklist) rule not being satisfied invalidates the whole filter set.
258 if (satisfied) return false;
259 } else {
260 anyNonExcludeRulePresent = true;
261 if (satisfied) anyNonExcludeRuleSatisfied = true;
262 }
263 }
264 return !anyNonExcludeRulePresent || anyNonExcludeRuleSatisfied;
265 }
266
notifyErrorListeners(ErrorEvent err,bool isFatal)267 void CanBus::notifyErrorListeners(ErrorEvent err, bool isFatal) {
268 std::lock_guard<std::mutex> lck(mErrListenersGuard);
269 for (auto& listener : mErrListeners) {
270 if (!listener->onError(err, isFatal).isOk()) {
271 LOG(WARNING) << "Failed to notify listener about error";
272 }
273 }
274 }
275
parseErrorFrame(const struct canfd_frame & frame)276 static ErrorEvent parseErrorFrame(const struct canfd_frame& frame) {
277 // decode error frame (to a degree)
278 if ((frame.can_id & (CAN_ERR_BUSERROR | CAN_ERR_BUSOFF)) != 0) {
279 return ErrorEvent::BUS_ERROR;
280 }
281 if ((frame.data[1] & CAN_ERR_CRTL_TX_OVERFLOW) != 0) {
282 return ErrorEvent::TX_OVERFLOW;
283 }
284 if ((frame.data[1] & CAN_ERR_CRTL_RX_OVERFLOW) != 0) {
285 return ErrorEvent::RX_OVERFLOW;
286 }
287 if ((frame.data[2] & CAN_ERR_PROT_OVERLOAD) != 0) {
288 return ErrorEvent::BUS_OVERLOAD;
289 }
290 if ((frame.can_id & CAN_ERR_PROT) != 0) {
291 return ErrorEvent::MALFORMED_INPUT;
292 }
293 if ((frame.can_id & (CAN_ERR_CRTL | CAN_ERR_TRX | CAN_ERR_RESTARTED)) != 0) {
294 // "controller restarted" constitutes a HARDWARE_ERROR imo
295 return ErrorEvent::HARDWARE_ERROR;
296 }
297 return ErrorEvent::UNKNOWN_ERROR;
298 }
299
onRead(const struct canfd_frame & frame,std::chrono::nanoseconds timestamp)300 void CanBus::onRead(const struct canfd_frame& frame, std::chrono::nanoseconds timestamp) {
301 if ((frame.can_id & CAN_ERR_FLAG) != 0) {
302 // error bit is set
303 LOG(WARNING) << "CAN Error frame received";
304 notifyErrorListeners(parseErrorFrame(frame), false);
305 return;
306 }
307
308 CanMessage message = {};
309 message.id = frame.can_id & CAN_EFF_MASK; // mask out eff/rtr/err flags
310 message.payload = hidl_vec<uint8_t>(frame.data, frame.data + frame.len);
311 message.timestamp = timestamp.count();
312 message.isExtendedId = (frame.can_id & CAN_EFF_FLAG) != 0;
313 message.remoteTransmissionRequest = (frame.can_id & CAN_RTR_FLAG) != 0;
314
315 if (UNLIKELY(kSuperVerbose)) {
316 LOG(VERBOSE) << "Got message " << toString(message);
317 }
318
319 std::lock_guard<std::mutex> lck(mMsgListenersGuard);
320 for (auto& listener : mMsgListeners) {
321 if (!match(listener.filter, message.id, message.remoteTransmissionRequest,
322 message.isExtendedId))
323 continue;
324 if (!listener.callback->onReceive(message).isOk() && !listener.failedOnce) {
325 listener.failedOnce = true;
326 LOG(WARNING) << "Failed to notify listener about message";
327 }
328 }
329 }
330
onError(int errnoVal)331 void CanBus::onError(int errnoVal) {
332 auto eventType = ErrorEvent::HARDWARE_ERROR;
333
334 if (errnoVal == ENODEV || errnoVal == ENETDOWN) {
335 mDownAfterUse = false;
336 eventType = ErrorEvent::INTERFACE_DOWN;
337 }
338 notifyErrorListeners(eventType, true);
339
340 const auto errcb = mErrCb;
341 if (errcb != nullptr) errcb();
342 }
343
344 } // namespace android::hardware::automotive::can::V1_0::implementation
345