1 /*
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.aidl-service"
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 #include <android-base/properties.h>
30
31 #include <aidl/android/frameworks/stats/IStats.h>
32
33 namespace aidl {
34 namespace android {
35 namespace hardware {
36 namespace usb {
37 namespace gadget {
38
39 string enabledPath;
40 constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c";
41 constexpr char kMax77759TcpcDevName[] = "i2c-max77759tcpc";
42 constexpr unsigned int kMax77759TcpcClientId = 0x25;
43 constexpr char kAccessoryLimitCurrent[] = "usb_limit_accessory_current";
44 constexpr char kAccessoryLimitCurrentEnable[] = "usb_limit_accessory_enable";
45 constexpr char kUpdateSdpEnumTimeout[] = "update_sdp_enum_timeout";
46
47 using ::android::base::GetBoolProperty;
48 using ::android::hardware::google::pixel::usb::kUvcEnabled;
49
UsbGadget()50 UsbGadget::UsbGadget() : mGadgetIrqPath(""),
51 mI2cBusNumber(-1),
52 mI2cClientPath("") {
53 if (access(OS_DESC_PATH, R_OK) != 0) {
54 ALOGE("configfs setup not done yet");
55 abort();
56 }
57 }
58
getUsbGadgetIrqPath()59 Status UsbGadget::getUsbGadgetIrqPath() {
60 std::string irqs;
61 size_t read_pos = 0;
62 size_t found_pos = 0;
63
64 if (!ReadFileToString(kProcInterruptsPath, &irqs)) {
65 ALOGE("cannot read all interrupts");
66 return Status::ERROR;
67 }
68
69 while (true) {
70 found_pos = irqs.find_first_of("\n", read_pos);
71 if (found_pos == std::string::npos) {
72 ALOGI("the string of all interrupts is unexpected");
73 return Status::ERROR;
74 }
75
76 std::string single_irq = irqs.substr(read_pos, found_pos - read_pos);
77
78 if (single_irq.find("dwc3", 0) != std::string::npos) {
79 unsigned int dwc3_irq_number;
80 size_t dwc3_pos = single_irq.find_first_of(":");
81 if (!ParseUint(single_irq.substr(0, dwc3_pos), &dwc3_irq_number)) {
82 ALOGI("unknown IRQ strings");
83 return Status::ERROR;
84 }
85
86 mGadgetIrqPath = kProcIrqPath + single_irq.substr(0, dwc3_pos) + kSmpAffinityList;
87 break;
88 }
89
90 if (found_pos == irqs.npos) {
91 ALOGI("USB gadget doesn't start");
92 return Status::ERROR;
93 }
94
95 read_pos = found_pos + 1;
96 }
97
98 return Status::SUCCESS;
99 }
100
currentFunctionsAppliedCallback(bool functionsApplied,void * payload)101 void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
102 UsbGadget *gadget = (UsbGadget *)payload;
103 gadget->mCurrentUsbFunctionsApplied = functionsApplied;
104 gadget->updateSdpEnumTimeout();
105 }
106
getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)107 ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> &callback,
108 int64_t in_transactionId) {
109 ScopedAStatus ret = callback->getCurrentUsbFunctionsCb(
110 mCurrentUsbFunctions,
111 mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED,
112 in_transactionId);
113 if (!ret.isOk())
114 ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str());
115
116 return ScopedAStatus::ok();
117 }
118
getUsbSpeed(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)119 ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
120 int64_t in_transactionId) {
121 std::string current_speed;
122 if (ReadFileToString(SPEED_PATH, ¤t_speed)) {
123 current_speed = Trim(current_speed);
124 ALOGI("current USB speed is %s", current_speed.c_str());
125 if (current_speed == "low-speed")
126 mUsbSpeed = UsbSpeed::LOWSPEED;
127 else if (current_speed == "full-speed")
128 mUsbSpeed = UsbSpeed::FULLSPEED;
129 else if (current_speed == "high-speed")
130 mUsbSpeed = UsbSpeed::HIGHSPEED;
131 else if (current_speed == "super-speed")
132 mUsbSpeed = UsbSpeed::SUPERSPEED;
133 else if (current_speed == "super-speed-plus")
134 mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb;
135 else if (current_speed == "UNKNOWN")
136 mUsbSpeed = UsbSpeed::UNKNOWN;
137 else
138 mUsbSpeed = UsbSpeed::UNKNOWN;
139 } else {
140 ALOGE("Fail to read current speed");
141 mUsbSpeed = UsbSpeed::UNKNOWN;
142 }
143
144 if (callback) {
145 ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId);
146
147 if (!ret.isOk())
148 ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str());
149 }
150
151 return ScopedAStatus::ok();
152 }
153
tearDownGadget()154 Status UsbGadget::tearDownGadget() {
155 if (Status(resetGadget()) != Status::SUCCESS){
156 return Status::ERROR;
157 }
158
159 if (monitorFfs.isMonitorRunning()) {
160 monitorFfs.reset();
161 } else {
162 ALOGI("mMonitor not running");
163 }
164 return Status::SUCCESS;
165 }
166
validateAndSetVidPid(int64_t functions)167 static Status validateAndSetVidPid(int64_t functions) {
168 Status ret;
169 std::string vendorFunctions = getVendorFunctions();
170
171 switch (functions) {
172 case GadgetFunction::MTP:
173 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
174 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
175 ret = Status::CONFIGURATION_NOT_SUPPORTED;
176 } else {
177 ret = Status(setVidPid("0x18d1", "0x4ee1"));
178 }
179 break;
180 case GadgetFunction::ADB |
181 GadgetFunction::MTP:
182 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
183 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
184 ret = Status::CONFIGURATION_NOT_SUPPORTED;
185 } else {
186 ret = Status(setVidPid("0x18d1", "0x4ee2"));
187 }
188 break;
189 case GadgetFunction::RNDIS:
190 case GadgetFunction::RNDIS |
191 GadgetFunction::NCM:
192 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
193 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
194 ret = Status::CONFIGURATION_NOT_SUPPORTED;
195 } else {
196 ret = Status(setVidPid("0x18d1", "0x4ee3"));
197 }
198 break;
199 case GadgetFunction::ADB |
200 GadgetFunction::RNDIS:
201 case GadgetFunction::ADB |
202 GadgetFunction::RNDIS |
203 GadgetFunction::NCM:
204 if (vendorFunctions == "dm") {
205 ret = Status(setVidPid("0x04e8", "0x6862"));
206 } else {
207 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
208 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
209 ret = Status::CONFIGURATION_NOT_SUPPORTED;
210 } else {
211 ret = Status(setVidPid("0x18d1", "0x4ee4"));
212 }
213 }
214 break;
215 case GadgetFunction::PTP:
216 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
217 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
218 ret = Status::CONFIGURATION_NOT_SUPPORTED;
219 } else {
220 ret = Status(setVidPid("0x18d1", "0x4ee5"));
221 }
222 break;
223 case GadgetFunction::ADB |
224 GadgetFunction::PTP:
225 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
226 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
227 ret = Status::CONFIGURATION_NOT_SUPPORTED;
228 } else {
229 ret = Status(setVidPid("0x18d1", "0x4ee6"));
230 }
231 break;
232 case GadgetFunction::ADB:
233 if (vendorFunctions == "dm") {
234 ret = Status(setVidPid("0x04e8", "0x6862"));
235 } else if (vendorFunctions == "etr_miu") {
236 ret = Status(setVidPid("0x18d1", "0x4ee2"));
237 } else if (vendorFunctions == "uwb_acm"){
238 ret = Status(setVidPid("0x18d1", "0x4ee2"));
239 } else {
240 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
241 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
242 ret = Status::CONFIGURATION_NOT_SUPPORTED;
243 } else {
244 ret = Status(setVidPid("0x18d1", "0x4ee7"));
245 }
246 }
247 break;
248 case GadgetFunction::MIDI:
249 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
250 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
251 ret = Status::CONFIGURATION_NOT_SUPPORTED;
252 } else {
253 ret = Status(setVidPid("0x18d1", "0x4ee8"));
254 }
255 break;
256 case GadgetFunction::ADB |
257 GadgetFunction::MIDI:
258 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
259 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
260 ret = Status::CONFIGURATION_NOT_SUPPORTED;
261 } else {
262 ret = Status(setVidPid("0x18d1", "0x4ee9"));
263 }
264 break;
265 case GadgetFunction::ACCESSORY:
266 if (!(vendorFunctions == "user" || vendorFunctions == ""))
267 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
268 ret = Status(setVidPid("0x18d1", "0x2d00"));
269 break;
270 case GadgetFunction::ADB |
271 GadgetFunction::ACCESSORY:
272 if (!(vendorFunctions == "user" || vendorFunctions == ""))
273 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
274 ret = Status(setVidPid("0x18d1", "0x2d01"));
275 break;
276 case GadgetFunction::AUDIO_SOURCE:
277 if (!(vendorFunctions == "user" || vendorFunctions == ""))
278 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
279 ret = Status(setVidPid("0x18d1", "0x2d02"));
280 break;
281 case GadgetFunction::ADB |
282 GadgetFunction::AUDIO_SOURCE:
283 if (!(vendorFunctions == "user" || vendorFunctions == ""))
284 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
285 ret = Status(setVidPid("0x18d1", "0x2d03"));
286 break;
287 case GadgetFunction::ACCESSORY |
288 GadgetFunction::AUDIO_SOURCE:
289 if (!(vendorFunctions == "user" || vendorFunctions == ""))
290 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
291 ret = Status(setVidPid("0x18d1", "0x2d04"));
292 break;
293 case GadgetFunction::ADB |
294 GadgetFunction::ACCESSORY |
295 GadgetFunction::AUDIO_SOURCE:
296 if (!(vendorFunctions == "user" || vendorFunctions == ""))
297 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
298 ret = Status(setVidPid("0x18d1", "0x2d05"));
299 break;
300 case GadgetFunction::NCM:
301 if (!(vendorFunctions == "user" || vendorFunctions == ""))
302 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
303 ret = Status(setVidPid("0x18d1", "0x4eeb"));
304 break;
305 case GadgetFunction::ADB |
306 GadgetFunction::NCM:
307 if (vendorFunctions == "dm") {
308 ret = Status(setVidPid("0x04e8", "0x6862"));
309 } else {
310 if (!(vendorFunctions == "user" || vendorFunctions == ""))
311 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
312 ret = Status(setVidPid("0x18d1", "0x4eec"));
313 }
314 break;
315 case GadgetFunction::UVC:
316 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
317 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
318 ret = Status::CONFIGURATION_NOT_SUPPORTED;
319 } else if (!GetBoolProperty(kUvcEnabled, false)) {
320 ALOGE("UVC function not enabled by config");
321 ret = Status::CONFIGURATION_NOT_SUPPORTED;
322 } else {
323 ret = Status(setVidPid("0x18d1", "0x4eed"));
324 }
325 break;
326 case GadgetFunction::ADB | GadgetFunction::UVC:
327 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
328 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
329 ret = Status::CONFIGURATION_NOT_SUPPORTED;
330 } else if (!GetBoolProperty(kUvcEnabled, false)) {
331 ALOGE("UVC function not enabled by config");
332 ret = Status::CONFIGURATION_NOT_SUPPORTED;
333 } else {
334 ret = Status(setVidPid("0x18d1", "0x4eee"));
335 }
336 break;
337 default:
338 ALOGE("Combination not supported");
339 ret = Status::CONFIGURATION_NOT_SUPPORTED;
340 }
341 return ret;
342 }
343
reset(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)344 ScopedAStatus UsbGadget::reset(const shared_ptr<IUsbGadgetCallback> &callback,
345 int64_t in_transactionId) {
346 ALOGI("USB Gadget reset");
347
348 if (!WriteStringToFile("none", PULLUP_PATH)) {
349 ALOGI("Gadget cannot be pulled down");
350 if (callback)
351 callback->resetCb(Status::ERROR, in_transactionId);
352 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
353 -1, "Gadget cannot be pulled down");
354 }
355
356 usleep(kDisconnectWaitUs);
357
358 if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
359 ALOGI("Gadget cannot be pulled up");
360 if (callback)
361 callback->resetCb(Status::ERROR, in_transactionId);
362 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
363 -1, "Gadget cannot be pulled up");
364 }
365 if (callback)
366 callback->resetCb(Status::SUCCESS, in_transactionId);
367
368 return ScopedAStatus::ok();
369 }
370
updateSdpEnumTimeout()371 void UsbGadget::updateSdpEnumTimeout() {
372 string update_sdp_enum_timeout_path;
373 std::string_view i2cPath;
374
375 i2cPath = getI2cClientPath();
376 if (i2cPath.empty()) {
377 ALOGE("%s: Unable to locate i2c bus node", __func__);
378 return;
379 }
380
381 update_sdp_enum_timeout_path = std::string{i2cPath} + "/" + kUpdateSdpEnumTimeout;
382 if (!WriteStringToFile("1", update_sdp_enum_timeout_path)) {
383 ALOGE("%s: Unable to write to %s.", __func__, update_sdp_enum_timeout_path.c_str());
384 } else {
385 ALOGI("%s: Updated SDP enumeration timeout value.", __func__);
386 }
387 }
388
setupFunctions(long functions,const shared_ptr<IUsbGadgetCallback> & callback,uint64_t timeout,int64_t in_transactionId)389 Status UsbGadget::setupFunctions(long functions,
390 const shared_ptr<IUsbGadgetCallback> &callback, uint64_t timeout,
391 int64_t in_transactionId) {
392 bool ffsEnabled = false;
393 int i = 0;
394
395 if (Status(addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i)) !=
396 Status::SUCCESS)
397 return Status::ERROR;
398
399 std::string vendorFunctions = getVendorFunctions();
400
401 if (vendorFunctions == "dm") {
402 ALOGI("enable usbradio debug functions");
403 if ((functions & GadgetFunction::RNDIS) != 0) {
404 if (linkFunction("acm.gs6", i++))
405 return Status::ERROR;
406 if (linkFunction("dm.gs7", i++))
407 return Status::ERROR;
408 } else {
409 if (linkFunction("dm.gs7", i++))
410 return Status::ERROR;
411 if (linkFunction("acm.gs6", i++))
412 return Status::ERROR;
413 }
414 } else if (vendorFunctions == "etr_miu") {
415 ALOGI("enable etr_miu functions");
416 if (linkFunction("etr_miu.gs11", i++))
417 return Status::ERROR;
418 } else if (vendorFunctions == "uwb_acm") {
419 ALOGI("enable uwb acm function");
420 if (linkFunction("acm.uwb0", i++))
421 return Status::ERROR;
422 }
423
424 if ((functions & GadgetFunction::ADB) != 0) {
425 ffsEnabled = true;
426 if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS)
427 return Status::ERROR;
428 }
429
430 if ((functions & GadgetFunction::NCM) != 0) {
431 ALOGI("setCurrentUsbFunctions ncm");
432 if (linkFunction("ncm.gs9", i++))
433 return Status::ERROR;
434 }
435
436 // Pull up the gadget right away when there are no ffs functions.
437 if (!ffsEnabled) {
438 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
439 return Status::ERROR;
440 mCurrentUsbFunctionsApplied = true;
441 if (callback)
442 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
443 updateSdpEnumTimeout();
444 return Status::SUCCESS;
445 }
446
447 monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this);
448 // Monitors the ffs paths to pull up the gadget when descriptors are written.
449 // Also takes of the pulling up the gadget again if the userspace process
450 // dies and restarts.
451 monitorFfs.startMonitor();
452
453 if (kDebug)
454 ALOGI("Mainthread in Cv");
455
456 if (callback) {
457 bool pullup = monitorFfs.waitForPullUp(timeout);
458 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(
459 functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId);
460 if (!ret.isOk()) {
461 ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str());
462 return Status::ERROR;
463 }
464 }
465 return Status::SUCCESS;
466 }
467
getI2cBusNumber()468 int UsbGadget::getI2cBusNumber() {
469 DIR *dp;
470 unsigned int busNumber;
471
472 // Since the i2c bus number doesn't change after boot, we only need to get
473 // it once.
474 if (mI2cBusNumber >= 0) {
475 return mI2cBusNumber;
476 }
477
478 dp = opendir(kHsi2cPath);
479 if (dp != NULL) {
480 struct dirent *ep;
481
482 while ((ep = readdir(dp))) {
483 if (ep->d_type == DT_DIR) {
484 if (sscanf(ep->d_name, "i2c-%u", &busNumber) == 1) {
485 mI2cBusNumber = busNumber;
486 break;
487 }
488 }
489 }
490 closedir(dp);
491 }
492
493 if (mI2cBusNumber < 0) {
494 ALOGE("Failed to open %s", kHsi2cPath);
495 }
496 return mI2cBusNumber;
497 }
498
getI2cClientPath()499 std::string_view UsbGadget::getI2cClientPath() {
500 DIR *dp;
501 char i2cClientPathLabeled[PATH_MAX];
502 char i2cClientPathUnLabeled[PATH_MAX];
503
504 // Since the I2C client path doesn't change after boot, we only need to get
505 // it once.
506 if (!mI2cClientPath.empty()) {
507 return mI2cClientPath;
508 }
509
510 if (getI2cBusNumber() < 0) {
511 return std::string_view{""};
512 }
513
514 snprintf(i2cClientPathLabeled, sizeof(i2cClientPathLabeled),
515 "%s/i2c-%d/%s", kHsi2cPath, mI2cBusNumber, kMax77759TcpcDevName);
516 snprintf(i2cClientPathUnLabeled, sizeof(i2cClientPathUnLabeled),
517 "%s/i2c-%d/%d-%04x", kHsi2cPath, mI2cBusNumber, mI2cBusNumber,
518 kMax77759TcpcClientId);
519
520 dp = opendir(i2cClientPathLabeled);
521 if (dp != NULL) {
522 mI2cClientPath.assign(i2cClientPathLabeled);
523 closedir(dp);
524 return mI2cClientPath;
525 }
526
527 dp = opendir(i2cClientPathUnLabeled);
528 if (dp != NULL) {
529 mI2cClientPath.assign(i2cClientPathUnLabeled);
530 closedir(dp);
531 return mI2cClientPath;
532 }
533
534 ALOGE("Failed to find the i2c client path under %s", kHsi2cPath);
535 return std::string_view{""};
536 }
537
setCurrentUsbFunctions(long functions,const shared_ptr<IUsbGadgetCallback> & callback,int64_t timeout,int64_t in_transactionId)538 ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions,
539 const shared_ptr<IUsbGadgetCallback> &callback,
540 int64_t timeout,
541 int64_t in_transactionId) {
542 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
543 std::string current_usb_power_operation_mode, current_usb_type;
544 std::string usb_limit_sink_enable;
545
546 string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath;
547 std::string_view i2cPath;
548
549 mCurrentUsbFunctions = functions;
550 mCurrentUsbFunctionsApplied = false;
551
552 i2cPath = getI2cClientPath();
553 if (!i2cPath.empty()) {
554 accessoryCurrentLimitPath = std::string{i2cPath} + "/" + kAccessoryLimitCurrent;
555 accessoryCurrentLimitEnablePath = std::string{i2cPath} + "/" + kAccessoryLimitCurrentEnable;
556 } else {
557 ALOGE("%s: Unable to locate i2c bus node", __func__);
558 }
559
560 // Get the gadget IRQ number before tearDownGadget()
561 if (mGadgetIrqPath.empty())
562 getUsbGadgetIrqPath();
563
564 // Unlink the gadget and stop the monitor if running.
565 Status status = tearDownGadget();
566 if (status != Status::SUCCESS) {
567 goto error;
568 }
569
570 ALOGI("Returned from tearDown gadget");
571
572 // Leave the gadget pulled down to give time for the host to sense disconnect.
573 usleep(kDisconnectWaitUs);
574
575 if (functions == GadgetFunction::NONE) {
576 if (callback == NULL)
577 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
578 -1, "callback == NULL");
579 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
580 if (!ret.isOk())
581 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
582 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
583 -1, "Error while calling setCurrentUsbFunctionsCb");
584 }
585
586 status = validateAndSetVidPid(functions);
587
588 if (status != Status::SUCCESS) {
589 goto error;
590 }
591
592 status = setupFunctions(functions, callback, timeout, in_transactionId);
593 if (status != Status::SUCCESS) {
594 goto error;
595 }
596
597 if (functions & GadgetFunction::NCM) {
598 if (!mGadgetIrqPath.empty()) {
599 if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
600 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
601 }
602 } else {
603 if (!mGadgetIrqPath.empty()) {
604 if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
605 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
606 }
607 }
608
609 if (ReadFileToString(CURRENT_USB_TYPE_PATH, ¤t_usb_type))
610 current_usb_type = Trim(current_usb_type);
611
612 if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, ¤t_usb_power_operation_mode))
613 current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
614
615 if (functions & GadgetFunction::ACCESSORY &&
616 current_usb_type == "Unknown SDP [CDP] DCP" &&
617 (current_usb_power_operation_mode == "default" ||
618 current_usb_power_operation_mode == "1.5A")) {
619 if (accessoryCurrentLimitPath.empty() || !WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
620 ALOGI("Write 1.3A to limit current fail");
621 } else {
622 if (accessoryCurrentLimitEnablePath.empty() ||
623 !WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
624 ALOGI("Enable limit current fail");
625 }
626 }
627 } else {
628 if (accessoryCurrentLimitEnablePath.empty() ||
629 !WriteStringToFile("0", accessoryCurrentLimitEnablePath))
630 ALOGI("unvote accessory limit current failed");
631 }
632
633 ALOGI("Usb Gadget setcurrent functions called successfully");
634 return ScopedAStatus::ok();
635
636 error:
637 ALOGI("Usb Gadget setcurrent functions failed");
638 if (callback == NULL)
639 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
640 -1, "Usb Gadget setcurrent functions failed");
641 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
642 if (!ret.isOk())
643 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
644 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
645 -1, "Error while calling setCurrentUsbFunctionsCb");
646 }
647 } // namespace gadget
648 } // namespace usb
649 } // namespace hardware
650 } // namespace android
651 } // aidl
652