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 "CanSocket.h"
18 
19 #include <android-base/logging.h>
20 #include <libnetdevice/can.h>
21 #include <libnetdevice/libnetdevice.h>
22 #include <linux/can.h>
23 #include <utils/SystemClock.h>
24 
25 #include <chrono>
26 
27 namespace android::hardware::automotive::can::V1_0::implementation {
28 
29 using namespace std::chrono_literals;
30 
31 /* How frequently the read thread checks whether the interface was asked to be down.
32  *
33  * Note: This does *not* affect read timing or bandwidth, just CPU load vs time to
34  *       down the interface. */
35 static constexpr auto kReadPooling = 100ms;
36 
open(const std::string & ifname,ReadCallback rdcb,ErrorCallback errcb)37 std::unique_ptr<CanSocket> CanSocket::open(const std::string& ifname, ReadCallback rdcb,
38                                            ErrorCallback errcb) {
39     auto sock = netdevice::can::socket(ifname);
40     if (!sock.ok()) {
41         LOG(ERROR) << "Can't open CAN socket on " << ifname;
42         return nullptr;
43     }
44 
45     // Can't use std::make_unique due to private CanSocket constructor.
46     return std::unique_ptr<CanSocket>(new CanSocket(std::move(sock), rdcb, errcb));
47 }
48 
CanSocket(base::unique_fd socket,ReadCallback rdcb,ErrorCallback errcb)49 CanSocket::CanSocket(base::unique_fd socket, ReadCallback rdcb, ErrorCallback errcb)
50     : mReadCallback(rdcb),
51       mErrorCallback(errcb),
52       mSocket(std::move(socket)),
53       mReaderThread(&CanSocket::readerThread, this) {}
54 
~CanSocket()55 CanSocket::~CanSocket() {
56     mStopReaderThread = true;
57 
58     /* CanSocket can be brought down as a result of read failure, from the same thread,
59      * so let's just detach and let it finish on its own. */
60     if (mReaderThreadFinished) {
61         mReaderThread.detach();
62     } else {
63         mReaderThread.join();
64     }
65 }
66 
send(const struct canfd_frame & frame)67 bool CanSocket::send(const struct canfd_frame& frame) {
68     const auto res = write(mSocket.get(), &frame, CAN_MTU);
69     if (res < 0) {
70         PLOG(DEBUG) << "CanSocket send failed";
71         return false;
72     }
73     if (res != CAN_MTU) {
74         LOG(DEBUG) << "CanSocket sent wrong number of bytes: " << res;
75         return false;
76     }
77     return true;
78 }
79 
toTimeval(std::chrono::microseconds t)80 static struct timeval toTimeval(std::chrono::microseconds t) {
81     struct timeval tv;
82     tv.tv_sec = t / 1s;
83     tv.tv_usec = (t % 1s) / 1us;
84     return tv;
85 }
86 
selectRead(const base::unique_fd & fd,std::chrono::microseconds timeout)87 static int selectRead(const base::unique_fd& fd, std::chrono::microseconds timeout) {
88     auto timeouttv = toTimeval(timeout);
89     fd_set readfds;
90     FD_ZERO(&readfds);
91     FD_SET(fd.get(), &readfds);
92     return select(fd.get() + 1, &readfds, nullptr, nullptr, &timeouttv);
93 }
94 
readerThread()95 void CanSocket::readerThread() {
96     LOG(VERBOSE) << "Reader thread started";
97     int errnoCopy = 0;
98 
99     while (!mStopReaderThread) {
100         /* The ideal would be to have a blocking read(3) call and interrupt it with shutdown(3).
101          * This is unfortunately not supported for SocketCAN, so we need to rely on select(3). */
102         const auto sel = selectRead(mSocket, kReadPooling);
103         if (sel == 0) continue;  // timeout
104         if (sel == -1) {
105             PLOG(ERROR) << "Select failed";
106             break;
107         }
108 
109         struct canfd_frame frame;
110         const auto nbytes = read(mSocket.get(), &frame, CAN_MTU);
111 
112         /* We could use SIOCGSTAMP to get a precise UNIX timestamp for a given packet, but what
113          * we really need is a time since boot. There is no direct way to convert between these
114          * clocks. We could implement a class to calculate the difference between the clocks
115          * (querying both several times and picking the smallest difference); apply the difference
116          * to a SIOCGSTAMP returned value; re-synchronize if the elapsed time is too much in the
117          * past (indicating the UNIX timestamp might have been adjusted).
118          *
119          * Apart from the added complexity, it's possible the added calculations and system calls
120          * would add so much time to the processing pipeline so the precision of the reported time
121          * was buried under the subsystem latency. Let's just use a local time since boot here and
122          * leave precise hardware timestamps for custom proprietary implementations (if needed). */
123         const std::chrono::nanoseconds ts(elapsedRealtimeNano());
124 
125         if (nbytes != CAN_MTU) {
126             if (nbytes >= 0) {
127                 LOG(ERROR) << "Failed to read CAN packet, got " << nbytes << " bytes";
128                 break;
129             }
130             if (errno == EAGAIN) continue;
131 
132             errnoCopy = errno;
133             PLOG(ERROR) << "Failed to read CAN packet";
134             break;
135         }
136 
137         mReadCallback(frame, ts);
138     }
139 
140     bool failed = !mStopReaderThread;
141     auto errCb = mErrorCallback;
142     mReaderThreadFinished = true;
143 
144     // Don't access any fields from here, see CanSocket::~CanSocket comment about detached thread
145     if (failed) errCb(errnoCopy);
146 
147     LOG(VERBOSE) << "Reader thread stopped";
148 }
149 
150 }  // namespace android::hardware::automotive::can::V1_0::implementation
151