1 /*
2 * Copyright (C) 2018 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 "android.hardware.usb.gadget@1.1-service.coral"
18
19 #include "UsbGadget.h"
20 #include <dirent.h>
21 #include <fcntl.h>
22 #include <stdio.h>
23 #include <sys/inotify.h>
24 #include <sys/mount.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 namespace android {
30 namespace hardware {
31 namespace usb {
32 namespace gadget {
33 namespace V1_1 {
34 namespace implementation {
35
UsbGadget()36 UsbGadget::UsbGadget() {
37 if (access(OS_DESC_PATH, R_OK) != 0) {
38 ALOGE("configfs setup not done yet");
39 abort();
40 }
41 }
42
currentFunctionsAppliedCallback(bool functionsApplied,void * payload)43 void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
44 UsbGadget *gadget = (UsbGadget *)payload;
45 gadget->mCurrentUsbFunctionsApplied = functionsApplied;
46 }
47
getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback> & callback)48 Return<void> UsbGadget::getCurrentUsbFunctions(const sp<V1_0::IUsbGadgetCallback> &callback) {
49 Return<void> ret = callback->getCurrentUsbFunctionsCb(
50 mCurrentUsbFunctions,
51 mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED);
52 if (!ret.isOk())
53 ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.description().c_str());
54
55 return Void();
56 }
57
tearDownGadget()58 V1_0::Status UsbGadget::tearDownGadget() {
59 if (resetGadget() != Status::SUCCESS)
60 return Status::ERROR;
61
62 if (monitorFfs.isMonitorRunning()) {
63 monitorFfs.reset();
64 } else {
65 ALOGI("mMonitor not running");
66 }
67 return Status::SUCCESS;
68 }
69
validateAndSetVidPid(uint64_t functions)70 static V1_0::Status validateAndSetVidPid(uint64_t functions) {
71 V1_0::Status ret = Status::SUCCESS;
72 std::string vendorFunctions = getVendorFunctions();
73
74 switch (functions) {
75 case static_cast<uint64_t>(GadgetFunction::MTP):
76 if (vendorFunctions == "diag") {
77 ret = setVidPid("0x05C6", "0x901B");
78 } else {
79 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
80 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
81 ret = Status::CONFIGURATION_NOT_SUPPORTED;
82 } else {
83 ret = setVidPid("0x18d1", "0x4ee1");
84 }
85 }
86 break;
87 case GadgetFunction::ADB | GadgetFunction::MTP:
88 if (vendorFunctions == "diag") {
89 ret = setVidPid("0x05C6", "0x903A");
90 } else {
91 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
92 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
93 ret = Status::CONFIGURATION_NOT_SUPPORTED;
94 } else {
95 ret = setVidPid("0x18d1", "0x4ee2");
96 }
97 }
98 break;
99 case static_cast<uint64_t>(GadgetFunction::RNDIS):
100 if (vendorFunctions == "diag") {
101 ret = setVidPid("0x05C6", "0x902C");
102 } else if (vendorFunctions == "serial_cdev,diag") {
103 ret = setVidPid("0x05C6", "0x90B5");
104 } else if (vendorFunctions == "diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl_gsi") {
105 ret = setVidPid("0x05C6", "0x90E6");
106 } else {
107 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
108 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
109 ret = Status::CONFIGURATION_NOT_SUPPORTED;
110 } else {
111 ret = setVidPid("0x18d1", "0x4ee3");
112 }
113 }
114 break;
115 case GadgetFunction::ADB | GadgetFunction::RNDIS:
116 if (vendorFunctions == "diag") {
117 ret = setVidPid("0x05C6", "0x902D");
118 } else if (vendorFunctions == "serial_cdev,diag") {
119 ret = setVidPid("0x05C6", "0x90B6");
120 } else if (vendorFunctions == "diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl_gsi") {
121 ret = setVidPid("0x05C6", "0x90E7");
122 } else {
123 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
124 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
125 ret = Status::CONFIGURATION_NOT_SUPPORTED;
126 } else {
127 ret = setVidPid("0x18d1", "0x4ee4");
128 }
129 }
130 break;
131 case static_cast<uint64_t>(GadgetFunction::PTP):
132 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
133 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
134 ret = Status::CONFIGURATION_NOT_SUPPORTED;
135 } else {
136 ret = setVidPid("0x18d1", "0x4ee5");
137 }
138 break;
139 case GadgetFunction::ADB | GadgetFunction::PTP:
140 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
141 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
142 ret = Status::CONFIGURATION_NOT_SUPPORTED;
143 } else {
144 ret = setVidPid("0x18d1", "0x4ee6");
145 }
146 break;
147 case static_cast<uint64_t>(GadgetFunction::ADB):
148 if (vendorFunctions == "diag") {
149 ret = setVidPid("0x05C6", "0x901D");
150 } else if (vendorFunctions == "diag,serial_cdev,rmnet_gsi") {
151 ret = setVidPid("0x05C6", "0x9091");
152 } else if (vendorFunctions == "diag,serial_cdev") {
153 ret = setVidPid("0x05C6", "0x901F");
154 } else if (vendorFunctions ==
155 "diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl_gsi,rmnet_gsi") {
156 ret = setVidPid("0x05C6", "0x90E5");
157 } else {
158 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
159 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
160 ret = Status::CONFIGURATION_NOT_SUPPORTED;
161 } else {
162 ret = setVidPid("0x18d1", "0x4ee7");
163 }
164 }
165 break;
166 case static_cast<uint64_t>(GadgetFunction::MIDI):
167 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
168 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
169 ret = Status::CONFIGURATION_NOT_SUPPORTED;
170 } else {
171 ret = setVidPid("0x18d1", "0x4ee8");
172 }
173 break;
174 case GadgetFunction::ADB | GadgetFunction::MIDI:
175 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
176 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
177 ret = Status::CONFIGURATION_NOT_SUPPORTED;
178 } else {
179 ret = setVidPid("0x18d1", "0x4ee9");
180 }
181 break;
182 case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
183 if (!(vendorFunctions == "user" || vendorFunctions == ""))
184 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
185 ret = setVidPid("0x18d1", "0x2d00");
186 break;
187 case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
188 if (!(vendorFunctions == "user" || vendorFunctions == ""))
189 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
190 ret = setVidPid("0x18d1", "0x2d01");
191 break;
192 case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
193 if (!(vendorFunctions == "user" || vendorFunctions == ""))
194 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
195 ret = setVidPid("0x18d1", "0x2d02");
196 break;
197 case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
198 if (!(vendorFunctions == "user" || vendorFunctions == ""))
199 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
200 ret = setVidPid("0x18d1", "0x2d03");
201 break;
202 case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
203 if (!(vendorFunctions == "user" || vendorFunctions == ""))
204 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
205 ret = setVidPid("0x18d1", "0x2d04");
206 break;
207 case GadgetFunction::ADB | GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
208 if (!(vendorFunctions == "user" || vendorFunctions == ""))
209 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
210 ret = setVidPid("0x18d1", "0x2d05");
211 break;
212 default:
213 ALOGE("Combination not supported");
214 ret = Status::CONFIGURATION_NOT_SUPPORTED;
215 }
216 return ret;
217 }
218
reset()219 Return<Status> UsbGadget::reset() {
220 if (!WriteStringToFile("none", PULLUP_PATH)) {
221 ALOGI("Gadget cannot be pulled down");
222 return Status::ERROR;
223 }
224
225 return Status::SUCCESS;
226 }
227
setupFunctions(uint64_t functions,const sp<V1_0::IUsbGadgetCallback> & callback,uint64_t timeout)228 V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
229 const sp<V1_0::IUsbGadgetCallback> &callback,
230 uint64_t timeout) {
231 bool ffsEnabled = false;
232 int i = 0;
233
234 if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) != Status::SUCCESS)
235 return Status::ERROR;
236
237 std::string vendorFunctions = getVendorFunctions();
238
239 if (vendorFunctions != "") {
240 ALOGI("enable usbradio debug functions");
241 char *function = strtok(const_cast<char *>(vendorFunctions.c_str()), ",");
242 while (function != NULL) {
243 if (string(function) == "diag" && linkFunction("diag.diag", i++))
244 return Status::ERROR;
245 if (string(function) == "diag_mdm" && linkFunction("diag.diag_mdm", i++))
246 return Status::ERROR;
247 if (string(function) == "qdss" && linkFunction("qdss.qdss", i++))
248 return Status::ERROR;
249 if (string(function) == "qdss_mdm" && linkFunction("qdss.qdss_mdm", i++))
250 return Status::ERROR;
251 if (string(function) == "serial_cdev" && linkFunction("cser.dun.0", i++))
252 return Status::ERROR;
253 if (string(function) == "dpl_gsi" && linkFunction("gsi.dpl", i++))
254 return Status::ERROR;
255 if (string(function) == "rmnet_gsi" && linkFunction("gsi.rmnet", i++))
256 return Status::ERROR;
257 function = strtok(NULL, ",");
258 }
259 }
260
261 if ((functions & GadgetFunction::ADB) != 0) {
262 ffsEnabled = true;
263 if (addAdb(&monitorFfs, &i) != Status::SUCCESS)
264 return Status::ERROR;
265 }
266
267 // Pull up the gadget right away when there are no ffs functions.
268 if (!ffsEnabled) {
269 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
270 return Status::ERROR;
271 mCurrentUsbFunctionsApplied = true;
272 if (callback)
273 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
274 return Status::SUCCESS;
275 }
276
277 monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this);
278 // Monitors the ffs paths to pull up the gadget when descriptors are written.
279 // Also takes of the pulling up the gadget again if the userspace process
280 // dies and restarts.
281 monitorFfs.startMonitor();
282
283 if (kDebug)
284 ALOGI("Mainthread in Cv");
285
286 if (callback) {
287 bool pullup = monitorFfs.waitForPullUp(timeout);
288 Return<void> ret = callback->setCurrentUsbFunctionsCb(
289 functions, pullup ? Status::SUCCESS : Status::ERROR);
290 if (!ret.isOk())
291 ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
292 }
293
294 return Status::SUCCESS;
295 }
296
setCurrentUsbFunctions(uint64_t functions,const sp<V1_0::IUsbGadgetCallback> & callback,uint64_t timeout)297 Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
298 const sp<V1_0::IUsbGadgetCallback> &callback,
299 uint64_t timeout) {
300 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
301
302 mCurrentUsbFunctions = functions;
303 mCurrentUsbFunctionsApplied = false;
304
305 // Unlink the gadget and stop the monitor if running.
306 V1_0::Status status = tearDownGadget();
307 if (status != Status::SUCCESS) {
308 goto error;
309 }
310
311 ALOGI("Returned from tearDown gadget");
312
313 // Leave the gadget pulled down to give time for the host to sense disconnect.
314 usleep(kDisconnectWaitUs);
315
316 if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
317 if (callback == NULL)
318 return Void();
319 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
320 if (!ret.isOk())
321 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
322 return Void();
323 }
324
325 status = validateAndSetVidPid(functions);
326
327 if (status != Status::SUCCESS) {
328 goto error;
329 }
330
331 status = setupFunctions(functions, callback, timeout);
332 if (status != Status::SUCCESS) {
333 goto error;
334 }
335
336 ALOGI("Usb Gadget setcurrent functions called successfully");
337 return Void();
338
339 error:
340 ALOGI("Usb Gadget setcurrent functions failed");
341 if (callback == NULL)
342 return Void();
343 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
344 if (!ret.isOk())
345 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
346 return Void();
347 }
348 } // namespace implementation
349 } // namespace V1_1
350 } // namespace gadget
351 } // namespace usb
352 } // namespace hardware
353 } // namespace android
354