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, ¤t_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(¤tFunctionsAppliedCallback, 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, ¤t_usb_type))
557 current_usb_type = Trim(current_usb_type);
558
559 if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, ¤t_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