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