1 /*
2  * Copyright (C) 2020 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 #define LOG_TAG "libusbconfigfs"
18 
19 #include "include/UsbGadgetCommon.h"
20 
21 namespace android {
22 namespace hardware {
23 namespace usb {
24 namespace gadget {
25 
26 static volatile bool gadgetPullup;
27 
MonitorFfs(const char * const gadget)28 MonitorFfs::MonitorFfs(const char* const gadget)
29     : mWatchFd(),
30       mEndpointList(),
31       mLock(),
32       mCv(),
33       mLockFd(),
34       mCurrentUsbFunctionsApplied(false),
35       mMonitor(),
36       mCallback(NULL),
37       mPayload(NULL),
38       mGadgetName(gadget),
39       mMonitorRunning(false) {
40     unique_fd eventFd(eventfd(0, 0));
41     if (eventFd == -1) {
42         ALOGE("mEventFd failed to create %d", errno);
43         abort();
44     }
45 
46     unique_fd epollFd(epoll_create(2));
47     if (epollFd == -1) {
48         ALOGE("mEpollFd failed to create %d", errno);
49         abort();
50     }
51 
52     unique_fd inotifyFd(inotify_init());
53     if (inotifyFd < 0) {
54         ALOGE("inotify init failed");
55         abort();
56     }
57 
58     if (addEpollFd(epollFd, inotifyFd) == -1) abort();
59 
60     if (addEpollFd(epollFd, eventFd) == -1) abort();
61 
62     mEpollFd = move(epollFd);
63     mInotifyFd = move(inotifyFd);
64     mEventFd = move(eventFd);
65     gadgetPullup = false;
66 }
67 
displayInotifyEvent(struct inotify_event * i)68 static void displayInotifyEvent(struct inotify_event* i) {
69     ALOGE("    wd =%2d; ", i->wd);
70     if (i->cookie > 0) ALOGE("cookie =%4d; ", i->cookie);
71 
72     ALOGE("mask = ");
73     if (i->mask & IN_ACCESS) ALOGE("IN_ACCESS ");
74     if (i->mask & IN_ATTRIB) ALOGE("IN_ATTRIB ");
75     if (i->mask & IN_CLOSE_NOWRITE) ALOGE("IN_CLOSE_NOWRITE ");
76     if (i->mask & IN_CLOSE_WRITE) ALOGE("IN_CLOSE_WRITE ");
77     if (i->mask & IN_CREATE) ALOGE("IN_CREATE ");
78     if (i->mask & IN_DELETE) ALOGE("IN_DELETE ");
79     if (i->mask & IN_DELETE_SELF) ALOGE("IN_DELETE_SELF ");
80     if (i->mask & IN_IGNORED) ALOGE("IN_IGNORED ");
81     if (i->mask & IN_ISDIR) ALOGE("IN_ISDIR ");
82     if (i->mask & IN_MODIFY) ALOGE("IN_MODIFY ");
83     if (i->mask & IN_MOVE_SELF) ALOGE("IN_MOVE_SELF ");
84     if (i->mask & IN_MOVED_FROM) ALOGE("IN_MOVED_FROM ");
85     if (i->mask & IN_MOVED_TO) ALOGE("IN_MOVED_TO ");
86     if (i->mask & IN_OPEN) ALOGE("IN_OPEN ");
87     if (i->mask & IN_Q_OVERFLOW) ALOGE("IN_Q_OVERFLOW ");
88     if (i->mask & IN_UNMOUNT) ALOGE("IN_UNMOUNT ");
89     ALOGE("\n");
90 
91     if (i->len > 0) ALOGE("        name = %s\n", i->name);
92 }
93 
startMonitorFd(void * param)94 void* MonitorFfs::startMonitorFd(void* param) {
95     MonitorFfs* monitorFfs = (MonitorFfs*)param;
96     char buf[kBufferSize];
97     bool writeUdc = true, stopMonitor = false;
98     struct epoll_event events[kEpollEvents];
99     steady_clock::time_point disconnect;
100 
101     bool descriptorWritten = true;
102     for (int i = 0; i < static_cast<int>(monitorFfs->mEndpointList.size()); i++) {
103         if (access(monitorFfs->mEndpointList.at(i).c_str(), R_OK)) {
104             descriptorWritten = false;
105             break;
106         }
107     }
108 
109     // notify here if the endpoints are already present.
110     if (descriptorWritten) {
111         usleep(kPullUpDelay);
112         if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) {
113             lock_guard<mutex> lock(monitorFfs->mLock);
114             monitorFfs->mCurrentUsbFunctionsApplied = true;
115             monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied, monitorFfs->mPayload);
116             gadgetPullup = true;
117             writeUdc = false;
118             ALOGI("GADGET pulled up");
119             monitorFfs->mCv.notify_all();
120         }
121     }
122 
123     while (!stopMonitor) {
124         int nrEvents = epoll_wait(monitorFfs->mEpollFd, events, kEpollEvents, -1);
125 
126         if (nrEvents <= 0) {
127             ALOGE("epoll wait did not return descriptor number");
128             continue;
129         }
130 
131         for (int i = 0; i < nrEvents; i++) {
132             ALOGI("event=%u on fd=%d\n", events[i].events, events[i].data.fd);
133 
134             if (events[i].data.fd == monitorFfs->mInotifyFd) {
135                 // Process all of the events in buffer returned by read().
136                 int numRead = read(monitorFfs->mInotifyFd, buf, kBufferSize);
137                 for (char* p = buf; p < buf + numRead;) {
138                     struct inotify_event* event = (struct inotify_event*)p;
139                     if (kDebug) displayInotifyEvent(event);
140 
141                     p += sizeof(struct inotify_event) + event->len;
142 
143                     bool descriptorPresent = true;
144                     for (int j = 0; j < static_cast<int>(monitorFfs->mEndpointList.size()); j++) {
145                         if (access(monitorFfs->mEndpointList.at(j).c_str(), R_OK)) {
146                             if (kDebug) ALOGI("%s absent", monitorFfs->mEndpointList.at(j).c_str());
147                             descriptorPresent = false;
148                             break;
149                         }
150                     }
151 
152                     if (!descriptorPresent && !writeUdc) {
153                         if (kDebug) ALOGI("endpoints not up");
154                         writeUdc = true;
155                         disconnect = std::chrono::steady_clock::now();
156                     } else if (descriptorPresent && writeUdc) {
157                         steady_clock::time_point temp = steady_clock::now();
158 
159                         if (std::chrono::duration_cast<microseconds>(temp - disconnect).count() <
160                             kPullUpDelay)
161                             usleep(kPullUpDelay);
162 
163                         if (!!WriteStringToFile(monitorFfs->mGadgetName, PULLUP_PATH)) {
164                             lock_guard<mutex> lock(monitorFfs->mLock);
165                             monitorFfs->mCurrentUsbFunctionsApplied = true;
166                             monitorFfs->mCallback(monitorFfs->mCurrentUsbFunctionsApplied,
167                                                   monitorFfs->mPayload);
168                             ALOGI("GADGET pulled up");
169                             writeUdc = false;
170                             gadgetPullup = true;
171                             // notify the main thread to signal userspace.
172                             monitorFfs->mCv.notify_all();
173                         }
174                     }
175                 }
176             } else {
177                 uint64_t flag;
178                 read(monitorFfs->mEventFd, &flag, sizeof(flag));
179                 if (flag == 100) {
180                     stopMonitor = true;
181                     break;
182                 }
183             }
184         }
185     }
186     return NULL;
187 }
188 
reset()189 void MonitorFfs::reset() {
190     lock_guard<mutex> lock(mLockFd);
191     uint64_t flag = 100;
192     unsigned long ret;
193 
194     if (mMonitorRunning) {
195         // Stop the monitor thread by writing into signal fd.
196         ret = TEMP_FAILURE_RETRY(write(mEventFd, &flag, sizeof(flag)));
197         if (ret < 0) ALOGE("Error writing eventfd errno=%d", errno);
198 
199         ALOGI("mMonitor signalled to exit");
200         mMonitor->join();
201         ALOGI("mMonitor destroyed");
202         mMonitorRunning = false;
203     }
204 
205     for (std::vector<int>::size_type i = 0; i != mWatchFd.size(); i++)
206         inotify_rm_watch(mInotifyFd, mWatchFd[i]);
207 
208     mEndpointList.clear();
209     gadgetPullup = false;
210     mCallback = NULL;
211     mPayload = NULL;
212 }
213 
startMonitor()214 bool MonitorFfs::startMonitor() {
215     mMonitor = unique_ptr<thread>(new thread(this->startMonitorFd, this));
216     mMonitorRunning = true;
217     return true;
218 }
219 
isMonitorRunning()220 bool MonitorFfs::isMonitorRunning() {
221     return mMonitorRunning;
222 }
223 
waitForPullUp(int timeout_ms)224 bool MonitorFfs::waitForPullUp(int timeout_ms) {
225     std::unique_lock<std::mutex> lk(mLock);
226 
227     if (gadgetPullup) return true;
228 
229     if (mCv.wait_for(lk, timeout_ms * 1ms, [] { return gadgetPullup; })) {
230         ALOGI("monitorFfs signalled true");
231         return true;
232     } else {
233         ALOGI("monitorFfs signalled error");
234         // continue monitoring as the descriptors might be written at a later
235         // point.
236         return false;
237     }
238 }
239 
addInotifyFd(string fd)240 bool MonitorFfs::addInotifyFd(string fd) {
241     lock_guard<mutex> lock(mLockFd);
242     int wfd;
243 
244     wfd = inotify_add_watch(mInotifyFd, fd.c_str(), IN_ALL_EVENTS);
245     if (wfd == -1)
246         return false;
247     else
248         mWatchFd.push_back(wfd);
249 
250     return true;
251 }
252 
addEndPoint(string ep)253 void MonitorFfs::addEndPoint(string ep) {
254     lock_guard<mutex> lock(mLockFd);
255 
256     mEndpointList.push_back(ep);
257 }
258 
registerFunctionsAppliedCallback(void (* callback)(bool functionsApplied,void * payload),void * payload)259 void MonitorFfs::registerFunctionsAppliedCallback(void (*callback)(bool functionsApplied,
260                                                                    void* payload),
261                                                   void* payload) {
262     mCallback = callback;
263     mPayload = payload;
264 }
265 
266 }  // namespace gadget
267 }  // namespace usb
268 }  // namespace hardware
269 }  // namespace android
270