blob: 909fb485cee73743c2cb28718497725c8fe60ef0 [file] [log] [blame]
Robin Pengc2b5ca92021-02-23 20:00:28 +08001/*
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 "android.hardware.usb.gadget@1.2-service.gs101"
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
29namespace android {
30namespace hardware {
31namespace usb {
32namespace gadget {
33namespace V1_2 {
34namespace implementation {
35
36UsbGadget::UsbGadget() {
37 if (access(OS_DESC_PATH, R_OK) != 0) {
38 ALOGE("configfs setup not done yet");
39 abort();
40 }
41}
42
43void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
44 UsbGadget *gadget = (UsbGadget *)payload;
45 gadget->mCurrentUsbFunctionsApplied = functionsApplied;
46}
47
48Return<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
58Return<void> UsbGadget::getUsbSpeed(const sp<V1_2::IUsbGadgetCallback> &callback) {
59 std::string current_speed;
60 if (ReadFileToString(SPEED_PATH, &current_speed)) {
61 current_speed = Trim(current_speed);
62 ALOGI("current USB speed is %s", current_speed.c_str());
63 if (current_speed == "low-speed")
64 mUsbSpeed = UsbSpeed::LOWSPEED;
65 else if (current_speed == "full-speed")
66 mUsbSpeed = UsbSpeed::FULLSPEED;
67 else if (current_speed == "high-speed")
68 mUsbSpeed = UsbSpeed::HIGHSPEED;
69 else if (current_speed == "super-speed")
70 mUsbSpeed = UsbSpeed::SUPERSPEED;
71 else if (current_speed == "super-speed-plus")
72 mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
73 else if (current_speed == "UNKNOWN")
74 mUsbSpeed = UsbSpeed::UNKNOWN;
75 else
76 mUsbSpeed = UsbSpeed::RESERVED_SPEED;
77 } else {
78 ALOGE("Fail to read current speed");
79 mUsbSpeed = UsbSpeed::UNKNOWN;
80 }
81
82 if (callback) {
83 Return<void> ret = callback->getUsbSpeedCb(mUsbSpeed);
84
85 if (!ret.isOk())
86 ALOGE("Call to getUsbSpeedCb failed %s", ret.description().c_str());
87 }
88
89 return Void();
90}
91
92V1_0::Status UsbGadget::tearDownGadget() {
93 if (resetGadget() != Status::SUCCESS)
94 return Status::ERROR;
95
96 if (monitorFfs.isMonitorRunning()) {
97 monitorFfs.reset();
98 } else {
99 ALOGI("mMonitor not running");
100 }
101 return Status::SUCCESS;
102}
103
104static V1_0::Status validateAndSetVidPid(uint64_t functions) {
105 V1_0::Status ret = Status::SUCCESS;
106 std::string vendorFunctions = getVendorFunctions();
107
108 switch (functions) {
109 case static_cast<uint64_t>(GadgetFunction::MTP):
110 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
111 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
112 ret = Status::CONFIGURATION_NOT_SUPPORTED;
113 } else {
114 ret = setVidPid("0x18d1", "0x4ee1");
115 }
116 break;
117 case GadgetFunction::ADB | GadgetFunction::MTP:
118 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
119 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
120 ret = Status::CONFIGURATION_NOT_SUPPORTED;
121 } else {
122 ret = setVidPid("0x18d1", "0x4ee2");
123 }
124 break;
125 case static_cast<uint64_t>(GadgetFunction::RNDIS):
126 case GadgetFunction::RNDIS | GadgetFunction::NCM:
127 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
128 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
129 ret = Status::CONFIGURATION_NOT_SUPPORTED;
130 } else {
131 ret = setVidPid("0x18d1", "0x4ee3");
132 }
133 break;
134 case GadgetFunction::ADB | GadgetFunction::RNDIS:
135 case GadgetFunction::ADB | GadgetFunction::RNDIS | GadgetFunction::NCM:
136 if (vendorFunctions == "dm") {
137 ret = setVidPid("0x04e8", "0x6862");
138 } else {
139 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
140 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
141 ret = Status::CONFIGURATION_NOT_SUPPORTED;
142 } else {
143 ret = setVidPid("0x18d1", "0x4ee4");
144 }
145 }
146 break;
147 case static_cast<uint64_t>(GadgetFunction::PTP):
148 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
149 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
150 ret = Status::CONFIGURATION_NOT_SUPPORTED;
151 } else {
152 ret = setVidPid("0x18d1", "0x4ee5");
153 }
154 break;
155 case GadgetFunction::ADB | GadgetFunction::PTP:
156 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
157 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
158 ret = Status::CONFIGURATION_NOT_SUPPORTED;
159 } else {
160 ret = setVidPid("0x18d1", "0x4ee6");
161 }
162 break;
163 case static_cast<uint64_t>(GadgetFunction::ADB):
164 if (vendorFunctions == "dm") {
165 ret = setVidPid("0x04e8", "0x6862");
166 } else if (vendorFunctions == "etr_miu") {
167 ret = setVidPid("0x18d1", "0x4ee2");
168 } else {
169 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
170 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
171 ret = Status::CONFIGURATION_NOT_SUPPORTED;
172 } else {
173 ret = setVidPid("0x18d1", "0x4ee7");
174 }
175 }
176 break;
177 case static_cast<uint64_t>(GadgetFunction::MIDI):
178 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
179 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
180 ret = Status::CONFIGURATION_NOT_SUPPORTED;
181 } else {
182 ret = setVidPid("0x18d1", "0x4ee8");
183 }
184 break;
185 case GadgetFunction::ADB | GadgetFunction::MIDI:
186 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
187 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
188 ret = Status::CONFIGURATION_NOT_SUPPORTED;
189 } else {
190 ret = setVidPid("0x18d1", "0x4ee9");
191 }
192 break;
193 case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
194 if (!(vendorFunctions == "user" || vendorFunctions == ""))
195 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
196 ret = setVidPid("0x18d1", "0x2d00");
197 break;
198 case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
199 if (!(vendorFunctions == "user" || vendorFunctions == ""))
200 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
201 ret = setVidPid("0x18d1", "0x2d01");
202 break;
203 case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
204 if (!(vendorFunctions == "user" || vendorFunctions == ""))
205 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
206 ret = setVidPid("0x18d1", "0x2d02");
207 break;
208 case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
209 if (!(vendorFunctions == "user" || vendorFunctions == ""))
210 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
211 ret = setVidPid("0x18d1", "0x2d03");
212 break;
213 case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
214 if (!(vendorFunctions == "user" || vendorFunctions == ""))
215 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
216 ret = setVidPid("0x18d1", "0x2d04");
217 break;
218 case GadgetFunction::ADB | GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
219 if (!(vendorFunctions == "user" || vendorFunctions == ""))
220 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
221 ret = setVidPid("0x18d1", "0x2d05");
222 break;
223 case static_cast<uint64_t>(GadgetFunction::NCM):
224 if (!(vendorFunctions == "user" || vendorFunctions == ""))
225 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800226 ret = setVidPid("0x18d1", "0x4eeb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800227 break;
228 case GadgetFunction::ADB | GadgetFunction::NCM:
229 if (!(vendorFunctions == "user" || vendorFunctions == ""))
230 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800231 ret = setVidPid("0x18d1", "0x4eec");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800232 break;
233 default:
234 ALOGE("Combination not supported");
235 ret = Status::CONFIGURATION_NOT_SUPPORTED;
236 }
237 return ret;
238}
239
240Return<Status> UsbGadget::reset() {
241 ALOGI("USB Gadget reset");
242
243 if (!WriteStringToFile("none", PULLUP_PATH)) {
244 ALOGI("Gadget cannot be pulled down");
245 return Status::ERROR;
246 }
247
248 usleep(kDisconnectWaitUs);
249
250 if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
251 ALOGI("Gadget cannot be pulled up");
252 return Status::ERROR;
253 }
254
255 return Status::SUCCESS;
256}
257
258V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
259 const sp<V1_0::IUsbGadgetCallback> &callback,
260 uint64_t timeout) {
261 bool ffsEnabled = false;
262 int i = 0;
263
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800264 if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) !=
Robin Pengc2b5ca92021-02-23 20:00:28 +0800265 Status::SUCCESS)
266 return Status::ERROR;
267
Robin Pengc2b5ca92021-02-23 20:00:28 +0800268 std::string vendorFunctions = getVendorFunctions();
269
270 if (vendorFunctions == "dm") {
271 ALOGI("enable usbradio debug functions");
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800272 if ((functions & GadgetFunction::RNDIS) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800273 if (linkFunction("acm.gs6", i++))
274 return Status::ERROR;
275 if (linkFunction("dm.gs7", i++))
276 return Status::ERROR;
277 } else {
278 if (linkFunction("dm.gs7", i++))
279 return Status::ERROR;
280 if (linkFunction("acm.gs6", i++))
281 return Status::ERROR;
282 }
283 } else if (vendorFunctions == "etr_miu") {
284 ALOGI("enable etr_miu functions");
285 if (linkFunction("etr_miu.gs11", i++))
286 return Status::ERROR;
287 }
288
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800289 if ((functions & GadgetFunction::ADB) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800290 ffsEnabled = true;
291 if (addAdb(&monitorFfs, &i) != Status::SUCCESS)
292 return Status::ERROR;
293 }
294
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800295 if ((functions & GadgetFunction::NCM) != 0) {
296 ALOGI("setCurrentUsbFunctions ncm");
297 if (linkFunction("ncm.gs9", i++))
Robin Pengc2b5ca92021-02-23 20:00:28 +0800298 return Status::ERROR;
299 }
300
301 // Pull up the gadget right away when there are no ffs functions.
302 if (!ffsEnabled) {
303 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
304 return Status::ERROR;
305 mCurrentUsbFunctionsApplied = true;
306 if (callback)
307 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
308 return Status::SUCCESS;
309 }
310
311 monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
312 // Monitors the ffs paths to pull up the gadget when descriptors are written.
313 // Also takes of the pulling up the gadget again if the userspace process
314 // dies and restarts.
315 monitorFfs.startMonitor();
316
317 if (kDebug)
318 ALOGI("Mainthread in Cv");
319
320 if (callback) {
321 bool pullup = monitorFfs.waitForPullUp(timeout);
322 Return<void> ret = callback->setCurrentUsbFunctionsCb(
323 functions, pullup ? Status::SUCCESS : Status::ERROR);
324 if (!ret.isOk())
325 ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
326 }
327
328 return Status::SUCCESS;
329}
330
331Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
332 const sp<V1_0::IUsbGadgetCallback> &callback,
333 uint64_t timeout) {
334 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
335
336 mCurrentUsbFunctions = functions;
337 mCurrentUsbFunctionsApplied = false;
338
339 // Unlink the gadget and stop the monitor if running.
340 V1_0::Status status = tearDownGadget();
341 if (status != Status::SUCCESS) {
342 goto error;
343 }
344
345 ALOGI("Returned from tearDown gadget");
346
347 // Leave the gadget pulled down to give time for the host to sense disconnect.
348 usleep(kDisconnectWaitUs);
349
350 if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
351 if (callback == NULL)
352 return Void();
353 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
354 if (!ret.isOk())
355 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
356 return Void();
357 }
358
359 status = validateAndSetVidPid(functions);
360
361 if (status != Status::SUCCESS) {
362 goto error;
363 }
364
365 status = setupFunctions(functions, callback, timeout);
366 if (status != Status::SUCCESS) {
367 goto error;
368 }
369
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700370 if (functions & GadgetFunction::NCM) {
371 SetProperty("vendor.usb.dwc3_irq", "big");
372 } else {
373 SetProperty("vendor.usb.dwc3_irq", "medium");
374 }
375
Robin Pengc2b5ca92021-02-23 20:00:28 +0800376 ALOGI("Usb Gadget setcurrent functions called successfully");
377 return Void();
378
379error:
380 ALOGI("Usb Gadget setcurrent functions failed");
381 if (callback == NULL)
382 return Void();
383 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
384 if (!ret.isOk())
385 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
386 return Void();
387}
388} // namespace implementation
389} // namespace V1_2
390} // namespace gadget
391} // namespace usb
392} // namespace hardware
393} // namespace android