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 using ::android::base::GetBoolProperty;
40 using ::android::hardware::google::pixel::usb::kUvcEnabled;
41 
42 string enabledPath;
43 constexpr char kHsi2cPath[] = "/sys/devices/platform/10cb0000.hsi2c";
44 constexpr char kI2CPath[] = "/sys/devices/platform/10cb0000.hsi2c/i2c-";
45 constexpr char kAccessoryLimitCurrent[] = "-0025/usb_limit_accessory_current";
46 constexpr char kAccessoryLimitCurrentEnable[] = "-0025/usb_limit_accessory_enable";
47 constexpr char kUpdateSdpEnumTimeout[] = "-0025/update_sdp_enum_timeout";
48 
getI2cBusHelper(string * name)49 Status 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 
UsbGadget()72 UsbGadget::UsbGadget() : mGadgetIrqPath("") {
73     if (access(OS_DESC_PATH, R_OK) != 0) {
74         ALOGE("configfs setup not done yet");
75         abort();
76     }
77 }
78 
getUsbGadgetIrqPath()79 Status UsbGadget::getUsbGadgetIrqPath() {
80     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 
currentFunctionsAppliedCallback(bool functionsApplied,void * payload)121 void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) {
122     UsbGadget *gadget = (UsbGadget *)payload;
123     gadget->mCurrentUsbFunctionsApplied = functionsApplied;
124     gadget->updateSdpEnumTimeout();
125 }
126 
getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)127 ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr<IUsbGadgetCallback> &callback,
128         int64_t in_transactionId) {
129     ScopedAStatus ret = callback->getCurrentUsbFunctionsCb(
130         mCurrentUsbFunctions,
131         mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED,
132         in_transactionId);
133     if (!ret.isOk())
134         ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str());
135 
136     return ScopedAStatus::ok();
137 }
138 
getUsbSpeed(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)139 ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr<IUsbGadgetCallback> &callback,
140         int64_t in_transactionId) {
141     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
158             mUsbSpeed = UsbSpeed::UNKNOWN;
159     } else {
160         ALOGE("Fail to read current speed");
161         mUsbSpeed = UsbSpeed::UNKNOWN;
162     }
163 
164     if (callback) {
165         ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId);
166 
167         if (!ret.isOk())
168             ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str());
169     }
170 
171     return ScopedAStatus::ok();
172 }
173 
tearDownGadget()174 Status UsbGadget::tearDownGadget() {
175     if (Status(resetGadget()) != Status::SUCCESS){
176         return Status::ERROR;
177     }
178 
179     if (monitorFfs.isMonitorRunning()) {
180         monitorFfs.reset();
181     } else {
182         ALOGI("mMonitor not running");
183     }
184     return Status::SUCCESS;
185 }
186 
validateAndSetVidPid(uint64_t functions)187 static Status validateAndSetVidPid(uint64_t functions) {
188     Status ret = Status::SUCCESS;
189     std::string vendorFunctions = getVendorFunctions();
190 
191     switch (functions) {
192         case GadgetFunction::MTP:
193             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
194                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
195                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
196             } else {
197                 ret = Status(setVidPid("0x18d1", "0x4ee1"));
198             }
199             break;
200         case GadgetFunction::ADB |
201                 GadgetFunction::MTP:
202             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
203                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
204                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
205             } else {
206                 ret = Status(setVidPid("0x18d1", "0x4ee2"));
207             }
208             break;
209         case GadgetFunction::RNDIS:
210         case GadgetFunction::RNDIS |
211                 GadgetFunction::NCM:
212             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
213                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
214                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
215             } else {
216                 ret = Status(setVidPid("0x18d1", "0x4ee3"));
217             }
218             break;
219         case GadgetFunction::ADB |
220                 GadgetFunction::RNDIS:
221         case GadgetFunction::ADB |
222                 GadgetFunction::RNDIS |
223                 GadgetFunction::NCM:
224             if (vendorFunctions == "dm") {
225                 ret = Status(setVidPid("0x04e8", "0x6862"));
226             } else {
227                 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
228                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
229                     ret = Status::CONFIGURATION_NOT_SUPPORTED;
230                 } else {
231                     ret = Status(setVidPid("0x18d1", "0x4ee4"));
232                 }
233             }
234             break;
235         case GadgetFunction::PTP:
236             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
237                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
238                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
239             } else {
240                 ret = Status(setVidPid("0x18d1", "0x4ee5"));
241             }
242             break;
243         case GadgetFunction::ADB |
244                 GadgetFunction::PTP:
245             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
246                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
247                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
248             } else {
249                 ret = Status(setVidPid("0x18d1", "0x4ee6"));
250             }
251             break;
252         case GadgetFunction::ADB:
253             if (vendorFunctions == "dm") {
254                 ret = Status(setVidPid("0x04e8", "0x6862"));
255             } else if (vendorFunctions == "etr_miu") {
256                 ret = Status(setVidPid("0x18d1", "0x4ee2"));
257             } else if (vendorFunctions == "uwb_acm"){
258                 ret = Status(setVidPid("0x18d1", "0x4ee2"));
259             } else {
260                 if (!(vendorFunctions == "user" || vendorFunctions == "")) {
261                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
262                     ret = Status::CONFIGURATION_NOT_SUPPORTED;
263                 } else {
264                     ret = Status(setVidPid("0x18d1", "0x4ee7"));
265                 }
266             }
267             break;
268         case GadgetFunction::MIDI:
269             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
270                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
271                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
272             } else {
273                 ret = Status(setVidPid("0x18d1", "0x4ee8"));
274             }
275             break;
276         case GadgetFunction::ADB |
277                 GadgetFunction::MIDI:
278             if (!(vendorFunctions == "user" || vendorFunctions == "")) {
279                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
280                 ret = Status::CONFIGURATION_NOT_SUPPORTED;
281             } else {
282                 ret = Status(setVidPid("0x18d1", "0x4ee9"));
283             }
284             break;
285         case GadgetFunction::ACCESSORY:
286             if (!(vendorFunctions == "user" || vendorFunctions == ""))
287                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
288             ret = Status(setVidPid("0x18d1", "0x2d00"));
289             break;
290         case GadgetFunction::ADB |
291                  GadgetFunction::ACCESSORY:
292             if (!(vendorFunctions == "user" || vendorFunctions == ""))
293                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
294             ret = Status(setVidPid("0x18d1", "0x2d01"));
295             break;
296         case GadgetFunction::AUDIO_SOURCE:
297             if (!(vendorFunctions == "user" || vendorFunctions == ""))
298                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
299             ret = Status(setVidPid("0x18d1", "0x2d02"));
300             break;
301         case GadgetFunction::ADB |
302                 GadgetFunction::AUDIO_SOURCE:
303             if (!(vendorFunctions == "user" || vendorFunctions == ""))
304                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
305             ret = Status(setVidPid("0x18d1", "0x2d03"));
306             break;
307         case GadgetFunction::ACCESSORY |
308                 GadgetFunction::AUDIO_SOURCE:
309             if (!(vendorFunctions == "user" || vendorFunctions == ""))
310                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
311             ret = Status(setVidPid("0x18d1", "0x2d04"));
312             break;
313         case GadgetFunction::ADB |
314                 GadgetFunction::ACCESSORY |
315                 GadgetFunction::AUDIO_SOURCE:
316             if (!(vendorFunctions == "user" || vendorFunctions == ""))
317                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
318             ret = Status(setVidPid("0x18d1", "0x2d05"));
319             break;
320         case GadgetFunction::NCM:
321             if (!(vendorFunctions == "user" || vendorFunctions == ""))
322                 ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
323             ret = Status(setVidPid("0x18d1", "0x4eeb"));
324             break;
325         case GadgetFunction::ADB |
326                 GadgetFunction::NCM:
327             if (vendorFunctions == "dm") {
328                 ret = Status(setVidPid("0x04e8", "0x6862"));
329             } else {
330                 if (!(vendorFunctions == "user" || vendorFunctions == ""))
331                     ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str());
332                 ret = Status(setVidPid("0x18d1", "0x4eec"));
333             }
334             break;
335         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;
357         default:
358             ALOGE("Combination not supported");
359             ret = Status::CONFIGURATION_NOT_SUPPORTED;
360     }
361     return ret;
362 }
363 
reset(const shared_ptr<IUsbGadgetCallback> & callback,int64_t in_transactionId)364 ScopedAStatus UsbGadget::reset(const shared_ptr<IUsbGadgetCallback> &callback,
365         int64_t in_transactionId) {
366     ALOGI("USB Gadget reset");
367 
368     if (!WriteStringToFile("none", PULLUP_PATH)) {
369         ALOGI("Gadget cannot be pulled down");
370         if (callback)
371             callback->resetCb(Status::ERROR, in_transactionId);
372         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
373                 -1, "Gadget cannot be pulled down");
374     }
375 
376     usleep(kDisconnectWaitUs);
377 
378     if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) {
379         ALOGI("Gadget cannot be pulled up");
380         if (callback)
381             callback->resetCb(Status::ERROR, in_transactionId);
382         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
383                 -1, "Gadget cannot be pulled up");
384     }
385     if (callback)
386         callback->resetCb(Status::SUCCESS, in_transactionId);
387 
388     return ScopedAStatus::ok();
389 }
390 
updateSdpEnumTimeout()391 void 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 + "/" + 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 
setupFunctions(long functions,const shared_ptr<IUsbGadgetCallback> & callback,uint64_t timeout,int64_t in_transactionId)407 Status UsbGadget::setupFunctions(long functions,
408         const shared_ptr<IUsbGadgetCallback> &callback, uint64_t timeout,
409         int64_t in_transactionId) {
410     bool ffsEnabled = false;
411     int i = 0;
412 
413     if (Status(addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i)) !=
414         Status::SUCCESS)
415         return Status::ERROR;
416 
417     std::string vendorFunctions = getVendorFunctions();
418 
419     if (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions != "dm")) {
420         if (linkFunction("ncm.gs9", i++))
421             return Status::ERROR;
422     }
423 
424     if (vendorFunctions == "dm") {
425         ALOGI("enable usbradio debug functions");
426         if ((functions & GadgetFunction::RNDIS) != 0) {
427             if (linkFunction("acm.gs6", i++))
428                 return Status::ERROR;
429             if (linkFunction("dm.gs7", i++))
430                 return Status::ERROR;
431         } else {
432             if (linkFunction("dm.gs7", i++))
433                 return Status::ERROR;
434             if (linkFunction("acm.gs6", i++))
435                 return Status::ERROR;
436         }
437     } else if (vendorFunctions == "etr_miu") {
438         ALOGI("enable etr_miu functions");
439         if (linkFunction("etr_miu.gs11", i++))
440             return Status::ERROR;
441     } else if (vendorFunctions == "uwb_acm") {
442         ALOGI("enable uwb acm function");
443         if (linkFunction("acm.uwb0", i++))
444             return Status::ERROR;
445     }
446 
447     if ((functions & GadgetFunction::ADB) != 0) {
448         ffsEnabled = true;
449         if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS)
450             return Status::ERROR;
451     }
452 
453     if (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions == "dm")) {
454         if (linkFunction("ncm.gs9", i++))
455             return Status::ERROR;
456     }
457 
458     // Pull up the gadget right away when there are no ffs functions.
459     if (!ffsEnabled) {
460         if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
461             return Status::ERROR;
462         mCurrentUsbFunctionsApplied = true;
463         if (callback)
464             callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
465         updateSdpEnumTimeout();
466         return Status::SUCCESS;
467     }
468 
469     monitorFfs.registerFunctionsAppliedCallback(&currentFunctionsAppliedCallback, this);
470     // Monitors the ffs paths to pull up the gadget when descriptors are written.
471     // Also takes of the pulling up the gadget again if the userspace process
472     // dies and restarts.
473     monitorFfs.startMonitor();
474 
475     if (kDebug)
476         ALOGI("Mainthread in Cv");
477 
478     if (callback) {
479         bool pullup = monitorFfs.waitForPullUp(timeout);
480         ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(
481             functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId);
482         if (!ret.isOk()) {
483             ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str());
484             return Status::ERROR;
485         }
486     }
487     return Status::SUCCESS;
488 }
489 
setCurrentUsbFunctions(long functions,const shared_ptr<IUsbGadgetCallback> & callback,int64_t timeout,int64_t in_transactionId)490 ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions,
491                                                const shared_ptr<IUsbGadgetCallback> &callback,
492                                                int64_t timeout,
493                                                int64_t in_transactionId) {
494     std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
495     std::string current_usb_power_operation_mode, current_usb_type;
496     std::string usb_limit_sink_enable;
497 
498     string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path;
499 
500     mCurrentUsbFunctions = functions;
501     mCurrentUsbFunctionsApplied = false;
502 
503     getI2cBusHelper(&path);
504     accessoryCurrentLimitPath = kI2CPath + path + "/" + path + kAccessoryLimitCurrent;
505     accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + path + kAccessoryLimitCurrentEnable;
506 
507     // Get the gadget IRQ number before tearDownGadget()
508     if (mGadgetIrqPath.empty())
509         getUsbGadgetIrqPath();
510 
511     // Unlink the gadget and stop the monitor if running.
512     Status status = tearDownGadget();
513     if (status != Status::SUCCESS) {
514         goto error;
515     }
516 
517     ALOGI("Returned from tearDown gadget");
518 
519     // Leave the gadget pulled down to give time for the host to sense disconnect.
520     usleep(kDisconnectWaitUs);
521 
522     if (functions == GadgetFunction::NONE) {
523         if (callback == NULL)
524             return ScopedAStatus::fromServiceSpecificErrorWithMessage(
525                 -1, "callback == NULL");
526         ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
527         if (!ret.isOk())
528             ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
529         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
530                 -1, "Error while calling setCurrentUsbFunctionsCb");
531     }
532 
533     status = validateAndSetVidPid(functions);
534 
535     if (status != Status::SUCCESS) {
536         goto error;
537     }
538 
539     status = setupFunctions(functions, callback, timeout, in_transactionId);
540     if (status != Status::SUCCESS) {
541         goto error;
542     }
543 
544     if (functions & GadgetFunction::NCM) {
545         if (!mGadgetIrqPath.empty()) {
546             if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
547                 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
548         }
549     } else {
550         if (!mGadgetIrqPath.empty()) {
551             if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
552                 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
553         }
554     }
555 
556     if (ReadFileToString(CURRENT_USB_TYPE_PATH, &current_usb_type))
557         current_usb_type = Trim(current_usb_type);
558 
559     if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, &current_usb_power_operation_mode))
560         current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
561 
562     if (functions & GadgetFunction::ACCESSORY &&
563         current_usb_type == "Unknown SDP [CDP] DCP" &&
564         (current_usb_power_operation_mode == "default" ||
565         current_usb_power_operation_mode == "1.5A")) {
566         if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
567             ALOGI("Write 1.3A to limit current fail");
568         } else {
569             if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
570                 ALOGI("Enable limit current fail");
571             }
572         }
573     } else {
574         if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath))
575             ALOGI("unvote accessory limit current failed");
576     }
577 
578     ALOGI("Usb Gadget setcurrent functions called successfully");
579     return ScopedAStatus::ok();
580 
581 error:
582     ALOGI("Usb Gadget setcurrent functions failed");
583     if (callback == NULL)
584         return ScopedAStatus::fromServiceSpecificErrorWithMessage(
585                 -1, "Usb Gadget setcurrent functions failed");
586     ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
587     if (!ret.isOk())
588         ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
589     return ScopedAStatus::fromServiceSpecificErrorWithMessage(
590                 -1, "Error while calling setCurrentUsbFunctionsCb");
591 }
592 }  // namespace gadget
593 }  // namespace usb
594 }  // namespace hardware
595 }  // namespace android
596 }  // aidl
597