blob: 0a6cea318a93cc0d19f73e92c55b7c5d58d6a389 [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");
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800168 } else if (vendorFunctions == "uwb_acm"){
169 ret = setVidPid("0x18d1", "0x4ee2");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800170 } else {
171 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
172 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
173 ret = Status::CONFIGURATION_NOT_SUPPORTED;
174 } else {
175 ret = setVidPid("0x18d1", "0x4ee7");
176 }
177 }
178 break;
179 case static_cast<uint64_t>(GadgetFunction::MIDI):
180 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
181 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
182 ret = Status::CONFIGURATION_NOT_SUPPORTED;
183 } else {
184 ret = setVidPid("0x18d1", "0x4ee8");
185 }
186 break;
187 case GadgetFunction::ADB | GadgetFunction::MIDI:
188 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
189 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
190 ret = Status::CONFIGURATION_NOT_SUPPORTED;
191 } else {
192 ret = setVidPid("0x18d1", "0x4ee9");
193 }
194 break;
195 case static_cast<uint64_t>(GadgetFunction::ACCESSORY):
196 if (!(vendorFunctions == "user" || vendorFunctions == ""))
197 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
198 ret = setVidPid("0x18d1", "0x2d00");
199 break;
200 case GadgetFunction::ADB | GadgetFunction::ACCESSORY:
201 if (!(vendorFunctions == "user" || vendorFunctions == ""))
202 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
203 ret = setVidPid("0x18d1", "0x2d01");
204 break;
205 case static_cast<uint64_t>(GadgetFunction::AUDIO_SOURCE):
206 if (!(vendorFunctions == "user" || vendorFunctions == ""))
207 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
208 ret = setVidPid("0x18d1", "0x2d02");
209 break;
210 case GadgetFunction::ADB | GadgetFunction::AUDIO_SOURCE:
211 if (!(vendorFunctions == "user" || vendorFunctions == ""))
212 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
213 ret = setVidPid("0x18d1", "0x2d03");
214 break;
215 case GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
216 if (!(vendorFunctions == "user" || vendorFunctions == ""))
217 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
218 ret = setVidPid("0x18d1", "0x2d04");
219 break;
220 case GadgetFunction::ADB | GadgetFunction::ACCESSORY | GadgetFunction::AUDIO_SOURCE:
221 if (!(vendorFunctions == "user" || vendorFunctions == ""))
222 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
223 ret = setVidPid("0x18d1", "0x2d05");
224 break;
225 case static_cast<uint64_t>(GadgetFunction::NCM):
226 if (!(vendorFunctions == "user" || vendorFunctions == ""))
227 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800228 ret = setVidPid("0x18d1", "0x4eeb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800229 break;
230 case GadgetFunction::ADB | GadgetFunction::NCM:
231 if (!(vendorFunctions == "user" || vendorFunctions == ""))
232 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800233 ret = setVidPid("0x18d1", "0x4eec");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800234 break;
235 default:
236 ALOGE("Combination not supported");
237 ret = Status::CONFIGURATION_NOT_SUPPORTED;
238 }
239 return ret;
240}
241
242Return<Status> UsbGadget::reset() {
243 ALOGI("USB Gadget reset");
244
245 if (!WriteStringToFile("none", PULLUP_PATH)) {
246 ALOGI("Gadget cannot be pulled down");
247 return Status::ERROR;
248 }
249
250 usleep(kDisconnectWaitUs);
251
252 if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
253 ALOGI("Gadget cannot be pulled up");
254 return Status::ERROR;
255 }
256
257 return Status::SUCCESS;
258}
259
260V1_0::Status UsbGadget::setupFunctions(uint64_t functions,
261 const sp<V1_0::IUsbGadgetCallback> &callback,
262 uint64_t timeout) {
263 bool ffsEnabled = false;
264 int i = 0;
265
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800266 if (addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i) !=
Robin Pengc2b5ca92021-02-23 20:00:28 +0800267 Status::SUCCESS)
268 return Status::ERROR;
269
Robin Pengc2b5ca92021-02-23 20:00:28 +0800270 std::string vendorFunctions = getVendorFunctions();
271
272 if (vendorFunctions == "dm") {
273 ALOGI("enable usbradio debug functions");
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800274 if ((functions & GadgetFunction::RNDIS) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800275 if (linkFunction("acm.gs6", i++))
276 return Status::ERROR;
277 if (linkFunction("dm.gs7", i++))
278 return Status::ERROR;
279 } else {
280 if (linkFunction("dm.gs7", i++))
281 return Status::ERROR;
282 if (linkFunction("acm.gs6", i++))
283 return Status::ERROR;
284 }
285 } else if (vendorFunctions == "etr_miu") {
286 ALOGI("enable etr_miu functions");
287 if (linkFunction("etr_miu.gs11", i++))
288 return Status::ERROR;
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800289 } else if (vendorFunctions == "uwb_acm") {
290 ALOGI("enable uwb acm function");
291 if (linkFunction("acm.uwb0", i++))
292 return Status::ERROR;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800293 }
294
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800295 if ((functions & GadgetFunction::ADB) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800296 ffsEnabled = true;
297 if (addAdb(&monitorFfs, &i) != Status::SUCCESS)
298 return Status::ERROR;
299 }
300
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800301 if ((functions & GadgetFunction::NCM) != 0) {
302 ALOGI("setCurrentUsbFunctions ncm");
303 if (linkFunction("ncm.gs9", i++))
Robin Pengc2b5ca92021-02-23 20:00:28 +0800304 return Status::ERROR;
305 }
306
307 // Pull up the gadget right away when there are no ffs functions.
308 if (!ffsEnabled) {
309 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
310 return Status::ERROR;
311 mCurrentUsbFunctionsApplied = true;
312 if (callback)
313 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
314 return Status::SUCCESS;
315 }
316
317 monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
318 // Monitors the ffs paths to pull up the gadget when descriptors are written.
319 // Also takes of the pulling up the gadget again if the userspace process
320 // dies and restarts.
321 monitorFfs.startMonitor();
322
323 if (kDebug)
324 ALOGI("Mainthread in Cv");
325
326 if (callback) {
327 bool pullup = monitorFfs.waitForPullUp(timeout);
328 Return<void> ret = callback->setCurrentUsbFunctionsCb(
329 functions, pullup ? Status::SUCCESS : Status::ERROR);
330 if (!ret.isOk())
331 ALOGE("setCurrentUsbFunctionsCb error %s", ret.description().c_str());
332 }
333
334 return Status::SUCCESS;
335}
336
337Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions,
338 const sp<V1_0::IUsbGadgetCallback> &callback,
339 uint64_t timeout) {
340 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
341
342 mCurrentUsbFunctions = functions;
343 mCurrentUsbFunctionsApplied = false;
344
345 // Unlink the gadget and stop the monitor if running.
346 V1_0::Status status = tearDownGadget();
347 if (status != Status::SUCCESS) {
348 goto error;
349 }
350
351 ALOGI("Returned from tearDown gadget");
352
353 // Leave the gadget pulled down to give time for the host to sense disconnect.
354 usleep(kDisconnectWaitUs);
355
356 if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
357 if (callback == NULL)
358 return Void();
359 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS);
360 if (!ret.isOk())
361 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
362 return Void();
363 }
364
365 status = validateAndSetVidPid(functions);
366
367 if (status != Status::SUCCESS) {
368 goto error;
369 }
370
371 status = setupFunctions(functions, callback, timeout);
372 if (status != Status::SUCCESS) {
373 goto error;
374 }
375
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700376 if (functions & GadgetFunction::NCM) {
377 SetProperty("vendor.usb.dwc3_irq", "big");
378 } else {
379 SetProperty("vendor.usb.dwc3_irq", "medium");
380 }
381
Robin Pengc2b5ca92021-02-23 20:00:28 +0800382 ALOGI("Usb Gadget setcurrent functions called successfully");
383 return Void();
384
385error:
386 ALOGI("Usb Gadget setcurrent functions failed");
387 if (callback == NULL)
388 return Void();
389 Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
390 if (!ret.isOk())
391 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
392 return Void();
393}
394} // namespace implementation
395} // namespace V1_2
396} // namespace gadget
397} // namespace usb
398} // namespace hardware
399} // namespace android