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