blob: 93138635da07be335a93a321cc9a879da2d390c3 [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
Ricky Niud6d0b7d2022-07-06 20:57:02 +080017#define LOG_TAG "android.hardware.usb.gadget.aidl-service"
Robin Pengc2b5ca92021-02-23 20:00:28 +080018
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
Ricky Niud6d0b7d2022-07-06 20:57:02 +080029#include <aidl/android/frameworks/stats/IStats.h>
30
31namespace aidl {
Robin Pengc2b5ca92021-02-23 20:00:28 +080032namespace android {
33namespace hardware {
34namespace usb {
35namespace gadget {
Robin Pengc2b5ca92021-02-23 20:00:28 +080036
Ricky Niuebd7fca2022-05-09 10:14:20 +080037string enabledPath;
38constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c";
39constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-";
40constexpr char kAccessoryLimitCurrent[] = "i2c-max77759tcpc/usb_limit_accessory_current";
41constexpr char kAccessoryLimitCurrentEnable[] = "i2c-max77759tcpc/usb_limit_accessory_enable";
42
Ray Chiba3dc9b2022-03-01 21:57:03 +080043UsbGadget::UsbGadget() : mGadgetIrqPath("") {
Robin Pengc2b5ca92021-02-23 20:00:28 +080044 if (access(OS_DESC_PATH, R_OK) != 0) {
45 ALOGE("configfs setup not done yet");
46 abort();
47 }
48}
49
Ricky Niud6d0b7d2022-07-06 20:57:02 +080050Status UsbGadget::getUsbGadgetIrqPath() {
Ray Chiba3dc9b2022-03-01 21:57:03 +080051 std::string irqs;
52 size_t read_pos = 0;
53 size_t found_pos = 0;
54
55 if (!ReadFileToString(kProcInterruptsPath, &irqs)) {
56 ALOGE("cannot read all interrupts");
57 return Status::ERROR;
58 }
59
60 while (true) {
61 found_pos = irqs.find_first_of("\n", read_pos);
62 if (found_pos == std::string::npos) {
63 ALOGI("the string of all interrupts is unexpected");
64 return Status::ERROR;
65 }
66
67 std::string single_irq = irqs.substr(read_pos, found_pos - read_pos);
68
69 if (single_irq.find("dwc3", 0) != std::string::npos) {
70 unsigned int dwc3_irq_number;
71 size_t dwc3_pos = single_irq.find_first_of(":");
72 if (!ParseUint(single_irq.substr(0, dwc3_pos), &dwc3_irq_number)) {
73 ALOGI("unknown IRQ strings");
74 return Status::ERROR;
75 }
76
77 mGadgetIrqPath = kProcIrqPath + single_irq.substr(0, dwc3_pos) + kSmpAffinityList;
78 break;
79 }
80
81 if (found_pos == irqs.npos) {
82 ALOGI("USB gadget doesn't start");
83 return Status::ERROR;
84 }
85
86 read_pos = found_pos + 1;
87 }
88
89 return Status::SUCCESS;
90}
91
Robin Pengc2b5ca92021-02-23 20:00:28 +080092void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
93 UsbGadget *gadget = (UsbGadget *)payload;
94 gadget->mCurrentUsbFunctionsApplied = functionsApplied;
95}
96
Ricky Niud6d0b7d2022-07-06 20:57:02 +080097ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> &callback,
98 int64_t in_transactionId) {
99 ScopedAStatus ret = callback->getCurrentUsbFunctionsCb(
Robin Pengc2b5ca92021-02-23 20:00:28 +0800100 mCurrentUsbFunctions,
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800101 mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED,
102 in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800103 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800104 ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str());
Robin Pengc2b5ca92021-02-23 20:00:28 +0800105
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800106 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800107}
108
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800109ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
110 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800111 std::string current_speed;
112 if (ReadFileToString(SPEED_PATH, &current_speed)) {
113 current_speed = Trim(current_speed);
114 ALOGI("current USB speed is %s", current_speed.c_str());
115 if (current_speed == "low-speed")
116 mUsbSpeed = UsbSpeed::LOWSPEED;
117 else if (current_speed == "full-speed")
118 mUsbSpeed = UsbSpeed::FULLSPEED;
119 else if (current_speed == "high-speed")
120 mUsbSpeed = UsbSpeed::HIGHSPEED;
121 else if (current_speed == "super-speed")
122 mUsbSpeed = UsbSpeed::SUPERSPEED;
123 else if (current_speed == "super-speed-plus")
124 mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
125 else if (current_speed == "UNKNOWN")
126 mUsbSpeed = UsbSpeed::UNKNOWN;
127 else
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800128 mUsbSpeed = UsbSpeed::UNKNOWN;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800129 } else {
130 ALOGE("Fail to read current speed");
131 mUsbSpeed = UsbSpeed::UNKNOWN;
132 }
133
134 if (callback) {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800135 ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800136
137 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800138 ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str());
Robin Pengc2b5ca92021-02-23 20:00:28 +0800139 }
140
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800141 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800142}
143
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800144Status UsbGadget::tearDownGadget() {
145 if (Status(resetGadget()) != Status::SUCCESS){
Robin Pengc2b5ca92021-02-23 20:00:28 +0800146 return Status::ERROR;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800147 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800148
149 if (monitorFfs.isMonitorRunning()) {
150 monitorFfs.reset();
151 } else {
152 ALOGI("mMonitor not running");
153 }
154 return Status::SUCCESS;
155}
156
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800157static Status validateAndSetVidPid(uint64_t functions) {
158 Status ret = Status::SUCCESS;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800159 std::string vendorFunctions = getVendorFunctions();
160
161 switch (functions) {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800162 case GadgetFunction::MTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800163 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
164 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
165 ret = Status::CONFIGURATION_NOT_SUPPORTED;
166 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800167 ret = Status(setVidPid("0x18d1", "0x4ee1"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800168 }
169 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800170 case GadgetFunction::ADB |
171 GadgetFunction::MTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800172 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
173 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
174 ret = Status::CONFIGURATION_NOT_SUPPORTED;
175 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800176 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800177 }
178 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800179 case GadgetFunction::RNDIS:
180 case GadgetFunction::RNDIS |
181 GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800182 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
183 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
184 ret = Status::CONFIGURATION_NOT_SUPPORTED;
185 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800186 ret = Status(setVidPid("0x18d1", "0x4ee3"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800187 }
188 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800189 case GadgetFunction::ADB |
190 GadgetFunction::RNDIS:
191 case GadgetFunction::ADB |
192 GadgetFunction::RNDIS |
193 GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800194 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800195 ret = Status(setVidPid("0x04e8", "0x6862"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800196 } else {
197 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
198 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
199 ret = Status::CONFIGURATION_NOT_SUPPORTED;
200 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800201 ret = Status(setVidPid("0x18d1", "0x4ee4"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800202 }
203 }
204 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800205 case GadgetFunction::PTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800206 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
207 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
208 ret = Status::CONFIGURATION_NOT_SUPPORTED;
209 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800210 ret = Status(setVidPid("0x18d1", "0x4ee5"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800211 }
212 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800213 case GadgetFunction::ADB |
214 GadgetFunction::PTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800215 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
216 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
217 ret = Status::CONFIGURATION_NOT_SUPPORTED;
218 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800219 ret = Status(setVidPid("0x18d1", "0x4ee6"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800220 }
221 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800222 case GadgetFunction::ADB:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800223 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800224 ret = Status(setVidPid("0x04e8", "0x6862"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800225 } else if (vendorFunctions == "etr_miu") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800226 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800227 } else if (vendorFunctions == "uwb_acm"){
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800228 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800229 } else {
230 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
231 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
232 ret = Status::CONFIGURATION_NOT_SUPPORTED;
233 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800234 ret = Status(setVidPid("0x18d1", "0x4ee7"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800235 }
236 }
237 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800238 case GadgetFunction::MIDI:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800239 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
240 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
241 ret = Status::CONFIGURATION_NOT_SUPPORTED;
242 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800243 ret = Status(setVidPid("0x18d1", "0x4ee8"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800244 }
245 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800246 case GadgetFunction::ADB |
247 GadgetFunction::MIDI:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800248 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
249 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
250 ret = Status::CONFIGURATION_NOT_SUPPORTED;
251 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800252 ret = Status(setVidPid("0x18d1", "0x4ee9"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800253 }
254 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800255 case GadgetFunction::ACCESSORY:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800256 if (!(vendorFunctions == "user" || vendorFunctions == ""))
257 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800258 ret = Status(setVidPid("0x18d1", "0x2d00"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800259 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800260 case GadgetFunction::ADB |
261 GadgetFunction::ACCESSORY:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800262 if (!(vendorFunctions == "user" || vendorFunctions == ""))
263 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800264 ret = Status(setVidPid("0x18d1", "0x2d01"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800265 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800266 case GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800267 if (!(vendorFunctions == "user" || vendorFunctions == ""))
268 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800269 ret = Status(setVidPid("0x18d1", "0x2d02"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800270 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800271 case GadgetFunction::ADB |
272 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800273 if (!(vendorFunctions == "user" || vendorFunctions == ""))
274 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800275 ret = Status(setVidPid("0x18d1", "0x2d03"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800276 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800277 case GadgetFunction::ACCESSORY |
278 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800279 if (!(vendorFunctions == "user" || vendorFunctions == ""))
280 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800281 ret = Status(setVidPid("0x18d1", "0x2d04"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800282 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800283 case GadgetFunction::ADB |
284 GadgetFunction::ACCESSORY |
285 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800286 if (!(vendorFunctions == "user" || vendorFunctions == ""))
287 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800288 ret = Status(setVidPid("0x18d1", "0x2d05"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800289 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800290 case GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800291 if (!(vendorFunctions == "user" || vendorFunctions == ""))
292 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800293 ret = Status(setVidPid("0x18d1", "0x4eeb"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800294 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800295 case GadgetFunction::ADB |
296 GadgetFunction::NCM:
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800297 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800298 ret = Status(setVidPid("0x04e8", "0x6862"));
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800299 } else {
300 if (!(vendorFunctions == "user" || vendorFunctions == ""))
301 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800302 ret = Status(setVidPid("0x18d1", "0x4eec"));
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800303 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800304 break;
305 default:
306 ALOGE("Combination not supported");
307 ret = Status::CONFIGURATION_NOT_SUPPORTED;
308 }
309 return ret;
310}
311
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800312ScopedAStatus UsbGadget::reset() {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800313 ALOGI("USB Gadget reset");
314
315 if (!WriteStringToFile("none", PULLUP_PATH)) {
316 ALOGI("Gadget cannot be pulled down");
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800317 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
318 -1, "Gadget cannot be pulled down");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800319 }
320
321 usleep(kDisconnectWaitUs);
322
323 if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
324 ALOGI("Gadget cannot be pulled up");
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800325 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
326 -1, "Gadget cannot be pulled up");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800327 }
328
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800329 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800330}
331
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800332Status UsbGadget::setupFunctions(long functions,
333 const shared_ptr<IUsbGadgetCallback> &callback, uint64_t timeout,
334 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800335 bool ffsEnabled = false;
336 int i = 0;
337
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800338 if (Status(addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i)) !=
Robin Pengc2b5ca92021-02-23 20:00:28 +0800339 Status::SUCCESS)
340 return Status::ERROR;
341
Robin Pengc2b5ca92021-02-23 20:00:28 +0800342 std::string vendorFunctions = getVendorFunctions();
343
344 if (vendorFunctions == "dm") {
345 ALOGI("enable usbradio debug functions");
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800346 if ((functions & GadgetFunction::RNDIS) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800347 if (linkFunction("acm.gs6", i++))
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800348 return Status::ERROR;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800349 if (linkFunction("dm.gs7", i++))
350 return Status::ERROR;
351 } else {
352 if (linkFunction("dm.gs7", i++))
353 return Status::ERROR;
354 if (linkFunction("acm.gs6", i++))
355 return Status::ERROR;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800356 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800357 } else if (vendorFunctions == "etr_miu") {
358 ALOGI("enable etr_miu functions");
359 if (linkFunction("etr_miu.gs11", i++))
360 return Status::ERROR;
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800361 } else if (vendorFunctions == "uwb_acm") {
362 ALOGI("enable uwb acm function");
363 if (linkFunction("acm.uwb0", i++))
364 return Status::ERROR;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800365 }
366
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800367 if ((functions & GadgetFunction::ADB) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800368 ffsEnabled = true;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800369 if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS)
Robin Pengc2b5ca92021-02-23 20:00:28 +0800370 return Status::ERROR;
371 }
372
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800373 if ((functions & GadgetFunction::NCM) != 0) {
374 ALOGI("setCurrentUsbFunctions ncm");
375 if (linkFunction("ncm.gs9", i++))
Robin Pengc2b5ca92021-02-23 20:00:28 +0800376 return Status::ERROR;
377 }
378
379 // Pull up the gadget right away when there are no ffs functions.
380 if (!ffsEnabled) {
381 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
382 return Status::ERROR;
383 mCurrentUsbFunctionsApplied = true;
384 if (callback)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800385 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800386 return Status::SUCCESS;
387 }
388
389 monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
390 // Monitors the ffs paths to pull up the gadget when descriptors are written.
391 // Also takes of the pulling up the gadget again if the userspace process
392 // dies and restarts.
393 monitorFfs.startMonitor();
394
395 if (kDebug)
396 ALOGI("Mainthread in Cv");
397
398 if (callback) {
399 bool pullup = monitorFfs.waitForPullUp(timeout);
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800400 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(
401 functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId);
402 if (!ret.isOk()) {
403 ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str());
404 return Status::ERROR;
405 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800406 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800407 return Status::SUCCESS;
408}
409
Ricky Niuebd7fca2022-05-09 10:14:20 +0800410Status getI2cBusHelper(string *name) {
411 DIR *dp;
412
413 dp = opendir(kHsi2cPath);
414 if (dp != NULL) {
415 struct dirent *ep;
416
417 while ((ep = readdir(dp))) {
418 if (ep->d_type == DT_DIR) {
419 if (string::npos != string(ep->d_name).find("i2c-")) {
420 std::strtok(ep->d_name, "-");
421 *name = std::strtok(NULL, "-");
422 }
423 }
424 }
425 closedir(dp);
426 return Status::SUCCESS;
427 }
428
429 ALOGE("Failed to open %s", kHsi2cPath);
430 return Status::ERROR;
431}
432
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800433ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions,
434 const shared_ptr<IUsbGadgetCallback> &callback,
435 int64_t timeout,
436 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800437 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
Ricky Niuebd7fca2022-05-09 10:14:20 +0800438 std::string current_usb_power_operation_mode, current_usb_type;
439 std::string usb_limit_sink_enable;
440
441 string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800442
443 mCurrentUsbFunctions = functions;
444 mCurrentUsbFunctionsApplied = false;
445
Ricky Niuebd7fca2022-05-09 10:14:20 +0800446 getI2cBusHelper(&path);
447 accessoryCurrentLimitPath = kI2CPath + path + "/" + kAccessoryLimitCurrent;
448 accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + kAccessoryLimitCurrentEnable;
449
Ray Chiba3dc9b2022-03-01 21:57:03 +0800450 // Get the gadget IRQ number before tearDownGadget()
451 if (mGadgetIrqPath.empty())
452 getUsbGadgetIrqPath();
453
Robin Pengc2b5ca92021-02-23 20:00:28 +0800454 // Unlink the gadget and stop the monitor if running.
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800455 Status status = tearDownGadget();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800456 if (status != Status::SUCCESS) {
457 goto error;
458 }
459
460 ALOGI("Returned from tearDown gadget");
461
462 // Leave the gadget pulled down to give time for the host to sense disconnect.
463 usleep(kDisconnectWaitUs);
464
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800465 if (functions == GadgetFunction::NONE) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800466 if (callback == NULL)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800467 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
468 -1, "callback == NULL");
469 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800470 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800471 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
472 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
473 -1, "Error while calling setCurrentUsbFunctionsCb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800474 }
475
476 status = validateAndSetVidPid(functions);
477
478 if (status != Status::SUCCESS) {
479 goto error;
480 }
481
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800482 status = setupFunctions(functions, callback, timeout, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800483 if (status != Status::SUCCESS) {
484 goto error;
485 }
486
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700487 if (functions & GadgetFunction::NCM) {
Ray Chiba3dc9b2022-03-01 21:57:03 +0800488 if (!mGadgetIrqPath.empty()) {
489 if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
490 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
491 }
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700492 } else {
Ray Chiba3dc9b2022-03-01 21:57:03 +0800493 if (!mGadgetIrqPath.empty()) {
494 if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
495 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
496 }
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700497 }
498
Ricky Niuebd7fca2022-05-09 10:14:20 +0800499 if (ReadFileToString(CURRENT_USB_TYPE_PATH, &current_usb_type))
500 current_usb_type = Trim(current_usb_type);
501
502 if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, &current_usb_power_operation_mode))
503 current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
504
505 if (functions & GadgetFunction::ACCESSORY &&
506 current_usb_type == "Unknown SDP [CDP] DCP" &&
507 (current_usb_power_operation_mode == "default" ||
508 current_usb_power_operation_mode == "1.5A")) {
509 if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
510 ALOGI("Write 1.3A to limit current fail");
511 } else {
512 if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
513 ALOGI("Enable limit current fail");
514 }
515 }
516 } else {
517 if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath))
518 ALOGI("unvote accessory limit current failed");
519 }
520
Robin Pengc2b5ca92021-02-23 20:00:28 +0800521 ALOGI("Usb Gadget setcurrent functions called successfully");
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800522 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
523 -1, "Usb Gadget setcurrent functions called successfully");
524
Robin Pengc2b5ca92021-02-23 20:00:28 +0800525
526error:
527 ALOGI("Usb Gadget setcurrent functions failed");
528 if (callback == NULL)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800529 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
530 -1, "Usb Gadget setcurrent functions failed");
531 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800532 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800533 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
534 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
535 -1, "Error while calling setCurrentUsbFunctionsCb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800536}
Robin Pengc2b5ca92021-02-23 20:00:28 +0800537} // namespace gadget
538} // namespace usb
539} // namespace hardware
540} // namespace android
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800541} // aidl