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 <fcntl.h>
21 #include <stdio.h>
22 #include <sys/inotify.h>
23 #include <sys/mount.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <android-base/properties.h>
29
30 #include <aidl/android/frameworks/stats/IStats.h>
31 #include <pixelusb/I2cHelper.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::getI2cClientPath;
41 using ::android::hardware::google::pixel::usb::kUvcEnabled;
42
43 string enabledPath;
44 constexpr char kHsi2cPath[] = "/sys/devices/platform/10d60000.hsi2c";
45 constexpr char kTcpcDevName[] = "i2c-max77759tcpc";
46 constexpr char kI2cClientId[] = "0025";
47 constexpr char kAccessoryLimitCurrent[] = "usb_limit_accessory_current";
48 constexpr char kAccessoryLimitCurrentEnable[] = "usb_limit_accessory_enable";
49 constexpr char kUpdateSdpEnumTimeout[] = "update_sdp_enum_timeout";
50
UsbGadget()51 UsbGadget::UsbGadget() : mGadgetIrqPath(""),
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(uint64_t functions)167 static Status validateAndSetVidPid(uint64_t functions) {
168 Status ret = Status::SUCCESS;
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
374 if (mI2cClientPath.empty()) {
375 mI2cClientPath = getI2cClientPath(kHsi2cPath, kTcpcDevName, kI2cClientId);
376 if (mI2cClientPath.empty()) {
377 ALOGE("%s: Unable to locate i2c bus node", __func__);
378 }
379 }
380
381 update_sdp_enum_timeout_path = mI2cClientPath + 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 (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions != "dm")) {
402 if (linkFunction("ncm.gs9", i++))
403 return Status::ERROR;
404 }
405
406 if (vendorFunctions == "dm") {
407 ALOGI("enable usbradio debug functions");
408 if ((functions & GadgetFunction::RNDIS) != 0) {
409 if (linkFunction("acm.gs6", i++))
410 return Status::ERROR;
411 if (linkFunction("dm.gs7", i++))
412 return Status::ERROR;
413 } else {
414 if (linkFunction("dm.gs7", i++))
415 return Status::ERROR;
416 if (linkFunction("acm.gs6", i++))
417 return Status::ERROR;
418 }
419 } else if (vendorFunctions == "etr_miu") {
420 ALOGI("enable etr_miu functions");
421 if (linkFunction("etr_miu.gs11", i++))
422 return Status::ERROR;
423 } else if (vendorFunctions == "uwb_acm") {
424 ALOGI("enable uwb acm function");
425 if (linkFunction("acm.uwb0", i++))
426 return Status::ERROR;
427 }
428
429 if ((functions & GadgetFunction::ADB) != 0) {
430 ffsEnabled = true;
431 if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS)
432 return Status::ERROR;
433 }
434
435 if (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions == "dm")) {
436 if (linkFunction("ncm.gs9", i++))
437 return Status::ERROR;
438 }
439
440 // Pull up the gadget right away when there are no ffs functions.
441 if (!ffsEnabled) {
442 if (!WriteStringToFile(kGadgetName, PULLUP_PATH))
443 return Status::ERROR;
444 mCurrentUsbFunctionsApplied = true;
445 if (callback)
446 callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
447 updateSdpEnumTimeout();
448 return Status::SUCCESS;
449 }
450
451 monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this);
452 // Monitors the ffs paths to pull up the gadget when descriptors are written.
453 // Also takes of the pulling up the gadget again if the userspace process
454 // dies and restarts.
455 monitorFfs.startMonitor();
456
457 if (kDebug)
458 ALOGI("Mainthread in Cv");
459
460 if (callback) {
461 bool pullup = monitorFfs.waitForPullUp(timeout);
462 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(
463 functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId);
464 if (!ret.isOk()) {
465 ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str());
466 return Status::ERROR;
467 }
468 }
469 return Status::SUCCESS;
470 }
471
setCurrentUsbFunctions(long functions,const shared_ptr<IUsbGadgetCallback> & callback,int64_t timeout,int64_t in_transactionId)472 ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions,
473 const shared_ptr<IUsbGadgetCallback> &callback,
474 int64_t timeout,
475 int64_t in_transactionId) {
476 std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
477 std::string current_usb_power_operation_mode, current_usb_type;
478 std::string usb_limit_sink_enable;
479 std::string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath;
480
481 mCurrentUsbFunctions = functions;
482 mCurrentUsbFunctionsApplied = false;
483
484 if (mI2cClientPath.empty()) {
485 mI2cClientPath = getI2cClientPath(kHsi2cPath, kTcpcDevName, kI2cClientId);
486 if (mI2cClientPath.empty()) {
487 ALOGE("%s: Unable to locate i2c bus node", __func__);
488 }
489 }
490
491 accessoryCurrentLimitPath = mI2cClientPath + kAccessoryLimitCurrent;
492 accessoryCurrentLimitEnablePath = mI2cClientPath + kAccessoryLimitCurrentEnable;
493
494 // Get the gadget IRQ number before tearDownGadget()
495 if (mGadgetIrqPath.empty())
496 getUsbGadgetIrqPath();
497
498 // Unlink the gadget and stop the monitor if running.
499 Status status = tearDownGadget();
500 if (status != Status::SUCCESS) {
501 goto error;
502 }
503
504 ALOGI("Returned from tearDown gadget");
505
506 // Leave the gadget pulled down to give time for the host to sense disconnect.
507 usleep(kDisconnectWaitUs);
508
509 if (functions == GadgetFunction::NONE) {
510 if (callback == NULL)
511 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
512 -1, "callback == NULL");
513 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId);
514 if (!ret.isOk())
515 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
516 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
517 -1, "Error while calling setCurrentUsbFunctionsCb");
518 }
519
520 status = validateAndSetVidPid(functions);
521
522 if (status != Status::SUCCESS) {
523 goto error;
524 }
525
526 status = setupFunctions(functions, callback, timeout, in_transactionId);
527 if (status != Status::SUCCESS) {
528 goto error;
529 }
530
531 if (functions & GadgetFunction::NCM) {
532 if (!mGadgetIrqPath.empty()) {
533 if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath))
534 ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str());
535 }
536 } else {
537 if (!mGadgetIrqPath.empty()) {
538 if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath))
539 ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str());
540 }
541 }
542
543 if (ReadFileToString(CURRENT_USB_TYPE_PATH, ¤t_usb_type))
544 current_usb_type = Trim(current_usb_type);
545
546 if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, ¤t_usb_power_operation_mode))
547 current_usb_power_operation_mode = Trim(current_usb_power_operation_mode);
548
549 if (functions & GadgetFunction::ACCESSORY &&
550 current_usb_type == "Unknown SDP [CDP] DCP" &&
551 (current_usb_power_operation_mode == "default" ||
552 current_usb_power_operation_mode == "1.5A")) {
553 if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) {
554 ALOGI("Write 1.3A to limit current fail");
555 } else {
556 if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) {
557 ALOGI("Enable limit current fail");
558 }
559 }
560 } else {
561 if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath))
562 ALOGI("unvote accessory limit current failed");
563 }
564
565 ALOGI("Usb Gadget setcurrent functions called successfully");
566 return ScopedAStatus::ok();
567
568 error:
569 ALOGI("Usb Gadget setcurrent functions failed");
570 if (callback == NULL)
571 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
572 -1, "Usb Gadget setcurrent functions failed");
573 ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
574 if (!ret.isOk())
575 ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
576 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
577 -1, "Error while calling setCurrentUsbFunctionsCb");
578 }
579 } // namespace gadget
580 } // namespace usb
581 } // namespace hardware
582 } // namespace android
583 } // aidl
584