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