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, &current_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(&currentFunctionsAppliedCallback, 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, &current_usb_type))
610         current_usb_type = Trim(current_usb_type);
611 
612     if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, &current_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