blob: 9b68e2c428a5deb315cb2677fdba0f7f3cd207c5 [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
Avichal Rakesheafdae62023-01-06 02:47:19 -080029#include <android-base/properties.h>
30
Ricky Niud6d0b7d2022-07-06 20:57:02 +080031#include <aidl/android/frameworks/stats/IStats.h>
32
33namespace aidl {
Robin Pengc2b5ca92021-02-23 20:00:28 +080034namespace android {
35namespace hardware {
36namespace usb {
37namespace gadget {
Robin Pengc2b5ca92021-02-23 20:00:28 +080038
Ricky Niuebd7fca2022-05-09 10:14:20 +080039string enabledPath;
40constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c";
41constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-";
42constexpr char kAccessoryLimitCurrent[] = "i2c-max77759tcpc/usb_limit_accessory_current";
43constexpr char kAccessoryLimitCurrentEnable[] = "i2c-max77759tcpc/usb_limit_accessory_enable";
Amit Sunil Dhamneed622852023-09-12 17:53:45 -070044constexpr char kUpdateSdpEnumTimeout[] = "i2c-max77759tcpc/update_sdp_enum_timeout";
Ricky Niuebd7fca2022-05-09 10:14:20 +080045
Avichal Rakesheafdae62023-01-06 02:47:19 -080046using ::android::base::GetBoolProperty;
47using ::android::hardware::google::pixel::usb::kUvcEnabled;
48
Amit Sunil Dhamneed622852023-09-12 17:53:45 -070049Status getI2cBusHelper(string *name) {
50 DIR *dp;
51
52 dp = opendir(kHsi2cPath);
53 if (dp != NULL) {
54 struct dirent *ep;
55
56 while ((ep = readdir(dp))) {
57 if (ep->d_type == DT_DIR) {
58 if (string::npos != string(ep->d_name).find("i2c-")) {
59 std::strtok(ep->d_name, "-");
60 *name = std::strtok(NULL, "-");
61 }
62 }
63 }
64 closedir(dp);
65 return Status::SUCCESS;
66 }
67
68 ALOGE("Failed to open %s", kHsi2cPath);
69 return Status::ERROR;
70}
71
Ray Chiba3dc9b2022-03-01 21:57:03 +080072UsbGadget::UsbGadget() : mGadgetIrqPath("") {
Robin Pengc2b5ca92021-02-23 20:00:28 +080073 if (access(OS_DESC_PATH, R_OK) != 0) {
74 ALOGE("configfs setup not done yet");
75 abort();
76 }
77}
78
Ricky Niud6d0b7d2022-07-06 20:57:02 +080079Status UsbGadget::getUsbGadgetIrqPath() {
Ray Chiba3dc9b2022-03-01 21:57:03 +080080 std::string irqs;
81 size_t read_pos = 0;
82 size_t found_pos = 0;
83
84 if (!ReadFileToString(kProcInterruptsPath, &irqs)) {
85 ALOGE("cannot read all interrupts");
86 return Status::ERROR;
87 }
88
89 while (true) {
90 found_pos = irqs.find_first_of("\n", read_pos);
91 if (found_pos == std::string::npos) {
92 ALOGI("the string of all interrupts is unexpected");
93 return Status::ERROR;
94 }
95
96 std::string single_irq = irqs.substr(read_pos, found_pos - read_pos);
97
98 if (single_irq.find("dwc3", 0) != std::string::npos) {
99 unsigned int dwc3_irq_number;
100 size_t dwc3_pos = single_irq.find_first_of(":");
101 if (!ParseUint(single_irq.substr(0, dwc3_pos), &dwc3_irq_number)) {
102 ALOGI("unknown IRQ strings");
103 return Status::ERROR;
104 }
105
106 mGadgetIrqPath = kProcIrqPath + single_irq.substr(0, dwc3_pos) + kSmpAffinityList;
107 break;
108 }
109
110 if (found_pos == irqs.npos) {
111 ALOGI("USB gadget doesn't start");
112 return Status::ERROR;
113 }
114
115 read_pos = found_pos + 1;
116 }
117
118 return Status::SUCCESS;
119}
120
Robin Pengc2b5ca92021-02-23 20:00:28 +0800121void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
122 UsbGadget *gadget = (UsbGadget *)payload;
123 gadget->mCurrentUsbFunctionsApplied = functionsApplied;
Amit Sunil Dhamneed622852023-09-12 17:53:45 -0700124 gadget->updateSdpEnumTimeout();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800125}
126
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800127ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> &callback,
128 int64_t in_transactionId) {
129 ScopedAStatus ret = callback->getCurrentUsbFunctionsCb(
Robin Pengc2b5ca92021-02-23 20:00:28 +0800130 mCurrentUsbFunctions,
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800131 mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED,
132 in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800133 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800134 ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str());
Robin Pengc2b5ca92021-02-23 20:00:28 +0800135
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800136 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800137}
138
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800139ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
140 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800141 std::string current_speed;
142 if (ReadFileToString(SPEED_PATH, &current_speed)) {
143 current_speed = Trim(current_speed);
144 ALOGI("current USB speed is %s", current_speed.c_str());
145 if (current_speed == "low-speed")
146 mUsbSpeed = UsbSpeed::LOWSPEED;
147 else if (current_speed == "full-speed")
148 mUsbSpeed = UsbSpeed::FULLSPEED;
149 else if (current_speed == "high-speed")
150 mUsbSpeed = UsbSpeed::HIGHSPEED;
151 else if (current_speed == "super-speed")
152 mUsbSpeed = UsbSpeed::SUPERSPEED;
153 else if (current_speed == "super-speed-plus")
154 mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
155 else if (current_speed == "UNKNOWN")
156 mUsbSpeed = UsbSpeed::UNKNOWN;
157 else
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800158 mUsbSpeed = UsbSpeed::UNKNOWN;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800159 } else {
160 ALOGE("Fail to read current speed");
161 mUsbSpeed = UsbSpeed::UNKNOWN;
162 }
163
164 if (callback) {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800165 ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800166
167 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800168 ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str());
Robin Pengc2b5ca92021-02-23 20:00:28 +0800169 }
170
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800171 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800172}
173
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800174Status UsbGadget::tearDownGadget() {
175 if (Status(resetGadget()) != Status::SUCCESS){
Robin Pengc2b5ca92021-02-23 20:00:28 +0800176 return Status::ERROR;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800177 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800178
179 if (monitorFfs.isMonitorRunning()) {
180 monitorFfs.reset();
181 } else {
182 ALOGI("mMonitor not running");
183 }
184 return Status::SUCCESS;
185}
186
Avichal Rakesheafdae62023-01-06 02:47:19 -0800187static Status validateAndSetVidPid(int64_t functions) {
188 Status ret;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800189 std::string vendorFunctions = getVendorFunctions();
190
191 switch (functions) {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800192 case GadgetFunction::MTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800193 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
194 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
195 ret = Status::CONFIGURATION_NOT_SUPPORTED;
196 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800197 ret = Status(setVidPid("0x18d1", "0x4ee1"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800198 }
199 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800200 case GadgetFunction::ADB |
201 GadgetFunction::MTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800202 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
203 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
204 ret = Status::CONFIGURATION_NOT_SUPPORTED;
205 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800206 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800207 }
208 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800209 case GadgetFunction::RNDIS:
210 case GadgetFunction::RNDIS |
211 GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800212 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
213 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
214 ret = Status::CONFIGURATION_NOT_SUPPORTED;
215 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800216 ret = Status(setVidPid("0x18d1", "0x4ee3"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800217 }
218 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800219 case GadgetFunction::ADB |
220 GadgetFunction::RNDIS:
221 case GadgetFunction::ADB |
222 GadgetFunction::RNDIS |
223 GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800224 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800225 ret = Status(setVidPid("0x04e8", "0x6862"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800226 } else {
227 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
228 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
229 ret = Status::CONFIGURATION_NOT_SUPPORTED;
230 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800231 ret = Status(setVidPid("0x18d1", "0x4ee4"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800232 }
233 }
234 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800235 case GadgetFunction::PTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800236 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
237 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
238 ret = Status::CONFIGURATION_NOT_SUPPORTED;
239 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800240 ret = Status(setVidPid("0x18d1", "0x4ee5"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800241 }
242 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800243 case GadgetFunction::ADB |
244 GadgetFunction::PTP:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800245 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
246 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
247 ret = Status::CONFIGURATION_NOT_SUPPORTED;
248 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800249 ret = Status(setVidPid("0x18d1", "0x4ee6"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800250 }
251 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800252 case GadgetFunction::ADB:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800253 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800254 ret = Status(setVidPid("0x04e8", "0x6862"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800255 } else if (vendorFunctions == "etr_miu") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800256 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800257 } else if (vendorFunctions == "uwb_acm"){
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800258 ret = Status(setVidPid("0x18d1", "0x4ee2"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800259 } else {
260 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
261 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
262 ret = Status::CONFIGURATION_NOT_SUPPORTED;
263 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800264 ret = Status(setVidPid("0x18d1", "0x4ee7"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800265 }
266 }
267 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800268 case GadgetFunction::MIDI:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800269 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
270 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
271 ret = Status::CONFIGURATION_NOT_SUPPORTED;
272 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800273 ret = Status(setVidPid("0x18d1", "0x4ee8"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800274 }
275 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800276 case GadgetFunction::ADB |
277 GadgetFunction::MIDI:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800278 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
279 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
280 ret = Status::CONFIGURATION_NOT_SUPPORTED;
281 } else {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800282 ret = Status(setVidPid("0x18d1", "0x4ee9"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800283 }
284 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800285 case GadgetFunction::ACCESSORY:
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", "0x2d00"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800289 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800290 case GadgetFunction::ADB |
291 GadgetFunction::ACCESSORY:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800292 if (!(vendorFunctions == "user" || vendorFunctions == ""))
293 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800294 ret = Status(setVidPid("0x18d1", "0x2d01"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800295 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800296 case GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800297 if (!(vendorFunctions == "user" || vendorFunctions == ""))
298 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800299 ret = Status(setVidPid("0x18d1", "0x2d02"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800300 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800301 case GadgetFunction::ADB |
302 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800303 if (!(vendorFunctions == "user" || vendorFunctions == ""))
304 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800305 ret = Status(setVidPid("0x18d1", "0x2d03"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800306 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800307 case GadgetFunction::ACCESSORY |
308 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800309 if (!(vendorFunctions == "user" || vendorFunctions == ""))
310 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800311 ret = Status(setVidPid("0x18d1", "0x2d04"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800312 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800313 case GadgetFunction::ADB |
314 GadgetFunction::ACCESSORY |
315 GadgetFunction::AUDIO_SOURCE:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800316 if (!(vendorFunctions == "user" || vendorFunctions == ""))
317 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800318 ret = Status(setVidPid("0x18d1", "0x2d05"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800319 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800320 case GadgetFunction::NCM:
Robin Pengc2b5ca92021-02-23 20:00:28 +0800321 if (!(vendorFunctions == "user" || vendorFunctions == ""))
322 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800323 ret = Status(setVidPid("0x18d1", "0x4eeb"));
Robin Pengc2b5ca92021-02-23 20:00:28 +0800324 break;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800325 case GadgetFunction::ADB |
326 GadgetFunction::NCM:
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800327 if (vendorFunctions == "dm") {
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800328 ret = Status(setVidPid("0x04e8", "0x6862"));
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800329 } else {
330 if (!(vendorFunctions == "user" || vendorFunctions == ""))
331 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800332 ret = Status(setVidPid("0x18d1", "0x4eec"));
Ricky Niu48b3e5d2021-11-24 17:26:38 +0800333 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800334 break;
Avichal Rakesheafdae62023-01-06 02:47:19 -0800335 case GadgetFunction::UVC:
336 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
337 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
338 ret = Status::CONFIGURATION_NOT_SUPPORTED;
339 } else if (!GetBoolProperty(kUvcEnabled, false)) {
340 ALOGE("UVC function not enabled by config");
341 ret = Status::CONFIGURATION_NOT_SUPPORTED;
342 } else {
343 ret = Status(setVidPid("0x18d1", "0x4eed"));
344 }
345 break;
346 case GadgetFunction::ADB | GadgetFunction::UVC:
347 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
348 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
349 ret = Status::CONFIGURATION_NOT_SUPPORTED;
350 } else if (!GetBoolProperty(kUvcEnabled, false)) {
351 ALOGE("UVC function not enabled by config");
352 ret = Status::CONFIGURATION_NOT_SUPPORTED;
353 } else {
354 ret = Status(setVidPid("0x18d1", "0x4eee"));
355 }
356 break;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800357 default:
358 ALOGE("Combination not supported");
359 ret = Status::CONFIGURATION_NOT_SUPPORTED;
360 }
361 return ret;
362}
363
Ricky Niu744f2142023-01-31 18:01:06 +0800364ScopedAStatus UsbGadget::reset(const shared_ptr<IUsbGadgetCallback> &callback,
365 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800366 ALOGI("USB Gadget reset");
367
368 if (!WriteStringToFile("none", PULLUP_PATH)) {
369 ALOGI("Gadget cannot be pulled down");
Ricky Niu744f2142023-01-31 18:01:06 +0800370 if (callback)
371 callback->resetCb(Status::ERROR, in_transactionId);
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800372 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
373 -1, "Gadget cannot be pulled down");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800374 }
375
376 usleep(kDisconnectWaitUs);
377
378 if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
379 ALOGI("Gadget cannot be pulled up");
Ricky Niu744f2142023-01-31 18:01:06 +0800380 if (callback)
381 callback->resetCb(Status::ERROR, in_transactionId);
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800382 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
383 -1, "Gadget cannot be pulled up");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800384 }
Ricky Niu744f2142023-01-31 18:01:06 +0800385 if (callback)
386 callback->resetCb(Status::SUCCESS, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800387
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800388 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800389}
390
Amit Sunil Dhamneed622852023-09-12 17:53:45 -0700391void UsbGadget::updateSdpEnumTimeout() {
392 string i2c_node, update_sdp_enum_timeout_path;
393
394 Status status = getI2cBusHelper(&i2c_node);
395 if (status != Status::SUCCESS) {
396 ALOGE("%s: Unable to locate i2c bus node", __func__);
397 }
398
399 update_sdp_enum_timeout_path = kI2CPath + i2c_node + "/" + kUpdateSdpEnumTimeout;
400 if (!WriteStringToFile("1", update_sdp_enum_timeout_path)) {
401 ALOGE("%s: Unable to write to %s.", __func__, update_sdp_enum_timeout_path.c_str());
402 } else {
403 ALOGI("%s: Updated SDP enumeration timeout value.", __func__);
404 }
405}
406
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800407Status UsbGadget::setupFunctions(long functions,
408 const shared_ptr<IUsbGadgetCallback> &callback, uint64_t timeout,
409 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800410 bool ffsEnabled = false;
411 int i = 0;
412
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800413 if (Status(addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i)) !=
Robin Pengc2b5ca92021-02-23 20:00:28 +0800414 Status::SUCCESS)
415 return Status::ERROR;
416
Robin Pengc2b5ca92021-02-23 20:00:28 +0800417 std::string vendorFunctions = getVendorFunctions();
418
419 if (vendorFunctions == "dm") {
420 ALOGI("enable usbradio debug functions");
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800421 if ((functions & GadgetFunction::RNDIS) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800422 if (linkFunction("acm.gs6", i++))
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800423 return Status::ERROR;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800424 if (linkFunction("dm.gs7", i++))
425 return Status::ERROR;
426 } else {
427 if (linkFunction("dm.gs7", i++))
428 return Status::ERROR;
429 if (linkFunction("acm.gs6", i++))
430 return Status::ERROR;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800431 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800432 } else if (vendorFunctions == "etr_miu") {
433 ALOGI("enable etr_miu functions");
434 if (linkFunction("etr_miu.gs11", i++))
435 return Status::ERROR;
Puma Hsufbcb7ad2021-08-19 19:36:51 +0800436 } else if (vendorFunctions == "uwb_acm") {
437 ALOGI("enable uwb acm function");
438 if (linkFunction("acm.uwb0", i++))
439 return Status::ERROR;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800440 }
441
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800442 if ((functions & GadgetFunction::ADB) != 0) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800443 ffsEnabled = true;
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800444 if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS)
Robin Pengc2b5ca92021-02-23 20:00:28 +0800445 return Status::ERROR;
446 }
447
Maciej Żenczykowskie0ccd8f2020-12-27 19:58:32 -0800448 if ((functions & GadgetFunction::NCM) != 0) {
449 ALOGI("setCurrentUsbFunctions ncm");
450 if (linkFunction("ncm.gs9", i++))
Robin Pengc2b5ca92021-02-23 20:00:28 +0800451 return Status::ERROR;
452 }
453
454 // Pull up the gadget right away when there are no ffs functions.
455 if (!ffsEnabled) {
456 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
457 return Status::ERROR;
458 mCurrentUsbFunctionsApplied = true;
459 if (callback)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800460 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
Amit Sunil Dhamneed622852023-09-12 17:53:45 -0700461 updateSdpEnumTimeout();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800462 return Status::SUCCESS;
463 }
464
465 monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
466 // Monitors the ffs paths to pull up the gadget when descriptors are written.
467 // Also takes of the pulling up the gadget again if the userspace process
468 // dies and restarts.
469 monitorFfs.startMonitor();
470
471 if (kDebug)
472 ALOGI("Mainthread in Cv");
473
474 if (callback) {
475 bool pullup = monitorFfs.waitForPullUp(timeout);
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800476 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(
477 functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId);
478 if (!ret.isOk()) {
479 ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str());
480 return Status::ERROR;
481 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800482 }
Robin Pengc2b5ca92021-02-23 20:00:28 +0800483 return Status::SUCCESS;
484}
485
Ricky Niuebd7fca2022-05-09 10:14:20 +0800486
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800487ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions,
488 const shared_ptr<IUsbGadgetCallback> &callback,
489 int64_t timeout,
490 int64_t in_transactionId) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800491 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
Ricky Niuebd7fca2022-05-09 10:14:20 +0800492 std::string current_usb_power_operation_mode, current_usb_type;
493 std::string usb_limit_sink_enable;
494
495 string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path;
Robin Pengc2b5ca92021-02-23 20:00:28 +0800496
497 mCurrentUsbFunctions = functions;
498 mCurrentUsbFunctionsApplied = false;
499
Ricky Niuebd7fca2022-05-09 10:14:20 +0800500 getI2cBusHelper(&path);
501 accessoryCurrentLimitPath = kI2CPath + path + "/" + kAccessoryLimitCurrent;
502 accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + kAccessoryLimitCurrentEnable;
503
Ray Chiba3dc9b2022-03-01 21:57:03 +0800504 // Get the gadget IRQ number before tearDownGadget()
505 if (mGadgetIrqPath.empty())
506 getUsbGadgetIrqPath();
507
Robin Pengc2b5ca92021-02-23 20:00:28 +0800508 // Unlink the gadget and stop the monitor if running.
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800509 Status status = tearDownGadget();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800510 if (status != Status::SUCCESS) {
511 goto error;
512 }
513
514 ALOGI("Returned from tearDown gadget");
515
516 // Leave the gadget pulled down to give time for the host to sense disconnect.
517 usleep(kDisconnectWaitUs);
518
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800519 if (functions == GadgetFunction::NONE) {
Robin Pengc2b5ca92021-02-23 20:00:28 +0800520 if (callback == NULL)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800521 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
522 -1, "callback == NULL");
523 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800524 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800525 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
526 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
527 -1, "Error while calling setCurrentUsbFunctionsCb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800528 }
529
530 status = validateAndSetVidPid(functions);
531
532 if (status != Status::SUCCESS) {
533 goto error;
534 }
535
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800536 status = setupFunctions(functions, callback, timeout, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800537 if (status != Status::SUCCESS) {
538 goto error;
539 }
540
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700541 if (functions & GadgetFunction::NCM) {
Ray Chiba3dc9b2022-03-01 21:57:03 +0800542 if (!mGadgetIrqPath.empty()) {
543 if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
544 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
545 }
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700546 } else {
Ray Chiba3dc9b2022-03-01 21:57:03 +0800547 if (!mGadgetIrqPath.empty()) {
548 if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
549 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
550 }
Maciej Żenczykowskia24469c2021-06-25 11:42:01 -0700551 }
552
Ricky Niuebd7fca2022-05-09 10:14:20 +0800553 if (ReadFileToString(CURRENT_USB_TYPE_PATH, &current_usb_type))
554 current_usb_type = Trim(current_usb_type);
555
556 if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, &current_usb_power_operation_mode))
557 current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
558
559 if (functions & GadgetFunction::ACCESSORY &&
560 current_usb_type == "Unknown SDP [CDP] DCP" &&
561 (current_usb_power_operation_mode == "default" ||
562 current_usb_power_operation_mode == "1.5A")) {
563 if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
564 ALOGI("Write 1.3A to limit current fail");
565 } else {
566 if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
567 ALOGI("Enable limit current fail");
568 }
569 }
570 } else {
571 if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath))
572 ALOGI("unvote accessory limit current failed");
573 }
574
Robin Pengc2b5ca92021-02-23 20:00:28 +0800575 ALOGI("Usb Gadget setcurrent functions called successfully");
Ricky Niub77191c2023-02-01 19:40:22 +0800576 return ScopedAStatus::ok();
Robin Pengc2b5ca92021-02-23 20:00:28 +0800577
578error:
579 ALOGI("Usb Gadget setcurrent functions failed");
580 if (callback == NULL)
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800581 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
582 -1, "Usb Gadget setcurrent functions failed");
583 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
Robin Pengc2b5ca92021-02-23 20:00:28 +0800584 if (!ret.isOk())
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800585 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
586 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
587 -1, "Error while calling setCurrentUsbFunctionsCb");
Robin Pengc2b5ca92021-02-23 20:00:28 +0800588}
Robin Pengc2b5ca92021-02-23 20:00:28 +0800589} // namespace gadget
590} // namespace usb
591} // namespace hardware
592} // namespace android
Ricky Niud6d0b7d2022-07-06 20:57:02 +0800593} // aidl