From 8a38826989baf3559268711f31d0fc2bcc4e46ed Mon Sep 17 00:00:00 2001 From: Tim Zimmermann Date: Wed, 21 Feb 2024 17:17:02 +0100 Subject: [PATCH] aidl: Import gs201 usb gadget HAL * From device/google/gs201 @ android-14.0.0_r27 Change-Id: I3ec3b17d676c68ce6c85aa84ffe969ec19635772 --- aidl/usb/gadget/Android.bp | 49 ++ aidl/usb/gadget/UsbGadget.cpp | 596 ++++++++++++++++++ aidl/usb/gadget/UsbGadget.h | 133 ++++ .../android.hardware.usb.gadget-service.rc | 19 + .../android.hardware.usb.gadget-service.xml | 10 + aidl/usb/gadget/service_gadget.cpp | 42 ++ 6 files changed, 849 insertions(+) create mode 100644 aidl/usb/gadget/Android.bp create mode 100644 aidl/usb/gadget/UsbGadget.cpp create mode 100644 aidl/usb/gadget/UsbGadget.h create mode 100644 aidl/usb/gadget/android.hardware.usb.gadget-service.rc create mode 100644 aidl/usb/gadget/android.hardware.usb.gadget-service.xml create mode 100644 aidl/usb/gadget/service_gadget.cpp diff --git a/aidl/usb/gadget/Android.bp b/aidl/usb/gadget/Android.bp new file mode 100644 index 0000000..518a735 --- /dev/null +++ b/aidl/usb/gadget/Android.bp @@ -0,0 +1,49 @@ +// +// Copyright (C) 2021 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "device_google_gs201_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["device_google_gs201_license"], +} + +cc_binary { + name: "android.hardware.usb.gadget-service", + relative_install_path: "hw", + init_rc: ["android.hardware.usb.gadget-service.rc"], + vintf_fragments: [ + "android.hardware.usb.gadget-service.xml", + ], + vendor: true, + srcs: ["service_gadget.cpp", "UsbGadget.cpp"], + cflags: ["-Wall", "-Werror"], + shared_libs: [ + "libbase", + "liblog", + "libutils", + "android.frameworks.stats-V1-ndk", + "android.hardware.usb.gadget-V1-ndk", + "libcutils", + "libbinder_ndk", + ], + static_libs: ["libpixelusb-aidl"], + proprietary: true, + export_shared_lib_headers: [ + "android.frameworks.stats-V1-ndk", + ], +} diff --git a/aidl/usb/gadget/UsbGadget.cpp b/aidl/usb/gadget/UsbGadget.cpp new file mode 100644 index 0000000..d3bd8f3 --- /dev/null +++ b/aidl/usb/gadget/UsbGadget.cpp @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.usb.gadget.aidl-service" + +#include "UsbGadget.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace usb { +namespace gadget { + +using ::android::base::GetBoolProperty; +using ::android::hardware::google::pixel::usb::kUvcEnabled; + +string enabledPath; +constexpr char kHsi2cPath[] = "/sys/devices/platform/10d60000.hsi2c"; +constexpr char kI2CPath[] = "/sys/devices/platform/10d60000.hsi2c/i2c-"; +constexpr char kAccessoryLimitCurrent[] = "i2c-max77759tcpc/usb_limit_accessory_current"; +constexpr char kAccessoryLimitCurrentEnable[] = "i2c-max77759tcpc/usb_limit_accessory_enable"; +constexpr char kUpdateSdpEnumTimeout[] = "i2c-max77759tcpc/update_sdp_enum_timeout"; + +Status getI2cBusHelper(string *name) { + DIR *dp; + + dp = opendir(kHsi2cPath); + if (dp != NULL) { + struct dirent *ep; + + while ((ep = readdir(dp))) { + if (ep->d_type == DT_DIR) { + if (string::npos != string(ep->d_name).find("i2c-")) { + std::strtok(ep->d_name, "-"); + *name = std::strtok(NULL, "-"); + } + } + } + closedir(dp); + return Status::SUCCESS; + } + + ALOGE("Failed to open %s", kHsi2cPath); + return Status::ERROR; +} + +UsbGadget::UsbGadget() : mGadgetIrqPath("") { + if (access(OS_DESC_PATH, R_OK) != 0) { + ALOGE("configfs setup not done yet"); + abort(); + } +} + +Status UsbGadget::getUsbGadgetIrqPath() { + std::string irqs; + size_t read_pos = 0; + size_t found_pos = 0; + + if (!ReadFileToString(kProcInterruptsPath, &irqs)) { + ALOGE("cannot read all interrupts"); + return Status::ERROR; + } + + while (true) { + found_pos = irqs.find_first_of("\n", read_pos); + if (found_pos == std::string::npos) { + ALOGI("the string of all interrupts is unexpected"); + return Status::ERROR; + } + + std::string single_irq = irqs.substr(read_pos, found_pos - read_pos); + + if (single_irq.find("dwc3", 0) != std::string::npos) { + unsigned int dwc3_irq_number; + size_t dwc3_pos = single_irq.find_first_of(":"); + if (!ParseUint(single_irq.substr(0, dwc3_pos), &dwc3_irq_number)) { + ALOGI("unknown IRQ strings"); + return Status::ERROR; + } + + mGadgetIrqPath = kProcIrqPath + single_irq.substr(0, dwc3_pos) + kSmpAffinityList; + break; + } + + if (found_pos == irqs.npos) { + ALOGI("USB gadget doesn't start"); + return Status::ERROR; + } + + read_pos = found_pos + 1; + } + + return Status::SUCCESS; +} + +void currentFunctionsAppliedCallback(bool functionsApplied, void *payload) { + UsbGadget *gadget = (UsbGadget *)payload; + gadget->mCurrentUsbFunctionsApplied = functionsApplied; + gadget->updateSdpEnumTimeout(); +} + +ScopedAStatus UsbGadget::getCurrentUsbFunctions(const shared_ptr &callback, + int64_t in_transactionId) { + ScopedAStatus ret = callback->getCurrentUsbFunctionsCb( + mCurrentUsbFunctions, + mCurrentUsbFunctionsApplied ? Status::FUNCTIONS_APPLIED : Status::FUNCTIONS_NOT_APPLIED, + in_transactionId); + if (!ret.isOk()) + ALOGE("Call to getCurrentUsbFunctionsCb failed %s", ret.getDescription().c_str()); + + return ScopedAStatus::ok(); +} + +ScopedAStatus UsbGadget::getUsbSpeed(const shared_ptr &callback, + int64_t in_transactionId) { + std::string current_speed; + if (ReadFileToString(SPEED_PATH, ¤t_speed)) { + current_speed = Trim(current_speed); + ALOGI("current USB speed is %s", current_speed.c_str()); + if (current_speed == "low-speed") + mUsbSpeed = UsbSpeed::LOWSPEED; + else if (current_speed == "full-speed") + mUsbSpeed = UsbSpeed::FULLSPEED; + else if (current_speed == "high-speed") + mUsbSpeed = UsbSpeed::HIGHSPEED; + else if (current_speed == "super-speed") + mUsbSpeed = UsbSpeed::SUPERSPEED; + else if (current_speed == "super-speed-plus") + mUsbSpeed = UsbSpeed::SUPERSPEED_10Gb; + else if (current_speed == "UNKNOWN") + mUsbSpeed = UsbSpeed::UNKNOWN; + else + mUsbSpeed = UsbSpeed::UNKNOWN; + } else { + ALOGE("Fail to read current speed"); + mUsbSpeed = UsbSpeed::UNKNOWN; + } + + if (callback) { + ScopedAStatus ret = callback->getUsbSpeedCb(mUsbSpeed, in_transactionId); + + if (!ret.isOk()) + ALOGE("Call to getUsbSpeedCb failed %s", ret.getDescription().c_str()); + } + + return ScopedAStatus::ok(); +} + +Status UsbGadget::tearDownGadget() { + if (Status(resetGadget()) != Status::SUCCESS){ + return Status::ERROR; + } + + if (monitorFfs.isMonitorRunning()) { + monitorFfs.reset(); + } else { + ALOGI("mMonitor not running"); + } + return Status::SUCCESS; +} + +static Status validateAndSetVidPid(uint64_t functions) { + Status ret = Status::SUCCESS; + std::string vendorFunctions = getVendorFunctions(); + + switch (functions) { + case GadgetFunction::MTP: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee1")); + } + break; + case GadgetFunction::ADB | + GadgetFunction::MTP: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee2")); + } + break; + case GadgetFunction::RNDIS: + case GadgetFunction::RNDIS | + GadgetFunction::NCM: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee3")); + } + break; + case GadgetFunction::ADB | + GadgetFunction::RNDIS: + case GadgetFunction::ADB | + GadgetFunction::RNDIS | + GadgetFunction::NCM: + if (vendorFunctions == "dm") { + ret = Status(setVidPid("0x04e8", "0x6862")); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee4")); + } + } + break; + case GadgetFunction::PTP: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee5")); + } + break; + case GadgetFunction::ADB | + GadgetFunction::PTP: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee6")); + } + break; + case GadgetFunction::ADB: + if (vendorFunctions == "dm") { + ret = Status(setVidPid("0x04e8", "0x6862")); + } else if (vendorFunctions == "etr_miu") { + ret = Status(setVidPid("0x18d1", "0x4ee2")); + } else if (vendorFunctions == "uwb_acm"){ + ret = Status(setVidPid("0x18d1", "0x4ee2")); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee7")); + } + } + break; + case GadgetFunction::MIDI: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee8")); + } + break; + case GadgetFunction::ADB | + GadgetFunction::MIDI: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4ee9")); + } + break; + case GadgetFunction::ACCESSORY: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d00")); + break; + case GadgetFunction::ADB | + GadgetFunction::ACCESSORY: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d01")); + break; + case GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d02")); + break; + case GadgetFunction::ADB | + GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d03")); + break; + case GadgetFunction::ACCESSORY | + GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d04")); + break; + case GadgetFunction::ADB | + GadgetFunction::ACCESSORY | + GadgetFunction::AUDIO_SOURCE: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x2d05")); + break; + case GadgetFunction::NCM: + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x4eeb")); + break; + case GadgetFunction::ADB | + GadgetFunction::NCM: + if (vendorFunctions == "dm") { + ret = Status(setVidPid("0x04e8", "0x6862")); + } else { + if (!(vendorFunctions == "user" || vendorFunctions == "")) + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status(setVidPid("0x18d1", "0x4eec")); + } + break; + case GadgetFunction::UVC: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else if (!GetBoolProperty(kUvcEnabled, false)) { + ALOGE("UVC function not enabled by config"); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4eed")); + } + break; + case GadgetFunction::ADB | GadgetFunction::UVC: + if (!(vendorFunctions == "user" || vendorFunctions == "")) { + ALOGE("Invalid vendorFunctions set: %s", vendorFunctions.c_str()); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else if (!GetBoolProperty(kUvcEnabled, false)) { + ALOGE("UVC function not enabled by config"); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } else { + ret = Status(setVidPid("0x18d1", "0x4eee")); + } + break; + default: + ALOGE("Combination not supported"); + ret = Status::CONFIGURATION_NOT_SUPPORTED; + } + return ret; +} + +ScopedAStatus UsbGadget::reset(const shared_ptr &callback, + int64_t in_transactionId) { + ALOGI("USB Gadget reset"); + + if (!WriteStringToFile("none", PULLUP_PATH)) { + ALOGI("Gadget cannot be pulled down"); + if (callback) + callback->resetCb(Status::ERROR, in_transactionId); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "Gadget cannot be pulled down"); + } + + usleep(kDisconnectWaitUs); + + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) { + ALOGI("Gadget cannot be pulled up"); + if (callback) + callback->resetCb(Status::ERROR, in_transactionId); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "Gadget cannot be pulled up"); + } + if (callback) + callback->resetCb(Status::SUCCESS, in_transactionId); + + return ScopedAStatus::ok(); +} + +void UsbGadget::updateSdpEnumTimeout() { + string i2c_node, update_sdp_enum_timeout_path; + + Status status = getI2cBusHelper(&i2c_node); + if (status != Status::SUCCESS) { + ALOGE("%s: Unable to locate i2c bus node", __func__); + } + + update_sdp_enum_timeout_path = kI2CPath + i2c_node + "/" + kUpdateSdpEnumTimeout; + if (!WriteStringToFile("1", update_sdp_enum_timeout_path)) { + ALOGE("%s: Unable to write to %s.", __func__, update_sdp_enum_timeout_path.c_str()); + } else { + ALOGI("%s: Updated SDP enumeration timeout value.", __func__); + } +} + +Status UsbGadget::setupFunctions(long functions, + const shared_ptr &callback, uint64_t timeout, + int64_t in_transactionId) { + bool ffsEnabled = false; + int i = 0; + + if (Status(addGenericAndroidFunctions(&monitorFfs, functions, &ffsEnabled, &i)) != + Status::SUCCESS) + return Status::ERROR; + + std::string vendorFunctions = getVendorFunctions(); + + if (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions != "dm")) { + if (linkFunction("ncm.gs9", i++)) + return Status::ERROR; + } + + if (vendorFunctions == "dm") { + ALOGI("enable usbradio debug functions"); + if ((functions & GadgetFunction::RNDIS) != 0) { + if (linkFunction("acm.gs6", i++)) + return Status::ERROR; + if (linkFunction("dm.gs7", i++)) + return Status::ERROR; + } else { + if (linkFunction("dm.gs7", i++)) + return Status::ERROR; + if (linkFunction("acm.gs6", i++)) + return Status::ERROR; + } + } else if (vendorFunctions == "etr_miu") { + ALOGI("enable etr_miu functions"); + if (linkFunction("etr_miu.gs11", i++)) + return Status::ERROR; + } else if (vendorFunctions == "uwb_acm") { + ALOGI("enable uwb acm function"); + if (linkFunction("acm.uwb0", i++)) + return Status::ERROR; + } + + if ((functions & GadgetFunction::ADB) != 0) { + ffsEnabled = true; + if (Status(addAdb(&monitorFfs, &i)) != Status::SUCCESS) + return Status::ERROR; + } + + if (((functions & GadgetFunction::NCM) != 0) && (vendorFunctions == "dm")) { + if (linkFunction("ncm.gs9", i++)) + return Status::ERROR; + } + + // Pull up the gadget right away when there are no ffs functions. + if (!ffsEnabled) { + if (!WriteStringToFile(kGadgetName, PULLUP_PATH)) + return Status::ERROR; + mCurrentUsbFunctionsApplied = true; + if (callback) + callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId); + updateSdpEnumTimeout(); + return Status::SUCCESS; + } + + monitorFfs.registerFunctionsAppliedCallback(¤tFunctionsAppliedCallback, this); + // Monitors the ffs paths to pull up the gadget when descriptors are written. + // Also takes of the pulling up the gadget again if the userspace process + // dies and restarts. + monitorFfs.startMonitor(); + + if (kDebug) + ALOGI("Mainthread in Cv"); + + if (callback) { + bool pullup = monitorFfs.waitForPullUp(timeout); + ScopedAStatus ret = callback->setCurrentUsbFunctionsCb( + functions, pullup ? Status::SUCCESS : Status::ERROR, in_transactionId); + if (!ret.isOk()) { + ALOGE("setCurrentUsbFunctionsCb error %s", ret.getDescription().c_str()); + return Status::ERROR; + } + } + return Status::SUCCESS; +} + +ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions, + const shared_ptr &callback, + int64_t timeout, + int64_t in_transactionId) { + std::unique_lock lk(mLockSetCurrentFunction); + std::string current_usb_power_operation_mode, current_usb_type; + std::string usb_limit_sink_enable; + + string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path; + + mCurrentUsbFunctions = functions; + mCurrentUsbFunctionsApplied = false; + + getI2cBusHelper(&path); + accessoryCurrentLimitPath = kI2CPath + path + "/" + kAccessoryLimitCurrent; + accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + kAccessoryLimitCurrentEnable; + + // Get the gadget IRQ number before tearDownGadget() + if (mGadgetIrqPath.empty()) + getUsbGadgetIrqPath(); + + // Unlink the gadget and stop the monitor if running. + Status status = tearDownGadget(); + if (status != Status::SUCCESS) { + goto error; + } + + ALOGI("Returned from tearDown gadget"); + + // Leave the gadget pulled down to give time for the host to sense disconnect. + usleep(kDisconnectWaitUs); + + if (functions == GadgetFunction::NONE) { + if (callback == NULL) + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "callback == NULL"); + ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str()); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "Error while calling setCurrentUsbFunctionsCb"); + } + + status = validateAndSetVidPid(functions); + + if (status != Status::SUCCESS) { + goto error; + } + + status = setupFunctions(functions, callback, timeout, in_transactionId); + if (status != Status::SUCCESS) { + goto error; + } + + if (functions & GadgetFunction::NCM) { + if (!mGadgetIrqPath.empty()) { + if (!WriteStringToFile(BIG_CORE, mGadgetIrqPath)) + ALOGI("Cannot move gadget IRQ to big core, path:%s", mGadgetIrqPath.c_str()); + } + } else { + if (!mGadgetIrqPath.empty()) { + if (!WriteStringToFile(MEDIUM_CORE, mGadgetIrqPath)) + ALOGI("Cannot move gadget IRQ to medium core, path:%s", mGadgetIrqPath.c_str()); + } + } + + if (ReadFileToString(CURRENT_USB_TYPE_PATH, ¤t_usb_type)) + current_usb_type = Trim(current_usb_type); + + if (ReadFileToString(CURRENT_USB_POWER_OPERATION_MODE_PATH, ¤t_usb_power_operation_mode)) + current_usb_power_operation_mode = Trim(current_usb_power_operation_mode); + + if (functions & GadgetFunction::ACCESSORY && + current_usb_type == "Unknown SDP [CDP] DCP" && + (current_usb_power_operation_mode == "default" || + current_usb_power_operation_mode == "1.5A")) { + if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) { + ALOGI("Write 1.3A to limit current fail"); + } else { + if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) { + ALOGI("Enable limit current fail"); + } + } + } else { + if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath)) + ALOGI("unvote accessory limit current failed"); + } + + ALOGI("Usb Gadget setcurrent functions called successfully"); + return ScopedAStatus::ok(); + +error: + ALOGI("Usb Gadget setcurrent functions failed"); + if (callback == NULL) + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "Usb Gadget setcurrent functions failed"); + ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId); + if (!ret.isOk()) + ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str()); + return ScopedAStatus::fromServiceSpecificErrorWithMessage( + -1, "Error while calling setCurrentUsbFunctionsCb"); +} +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/aidl/usb/gadget/UsbGadget.h b/aidl/usb/gadget/UsbGadget.h new file mode 100644 index 0000000..3433081 --- /dev/null +++ b/aidl/usb/gadget/UsbGadget.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace usb { +namespace gadget { + +using ::aidl::android::hardware::usb::gadget::GadgetFunction; +using ::aidl::android::hardware::usb::gadget::IUsbGadgetCallback; +using ::aidl::android::hardware::usb::gadget::IUsbGadget; +using ::aidl::android::hardware::usb::gadget::Status; +using ::aidl::android::hardware::usb::gadget::UsbSpeed; +using ::android::base::GetProperty; +using ::android::base::SetProperty; +using ::android::base::ParseUint; +using ::android::base::unique_fd; +using ::android::base::ReadFileToString; +using ::android::base::Trim; +using ::android::base::WriteStringToFile; +using ::android::hardware::google::pixel::usb::addAdb; +using ::android::hardware::google::pixel::usb::addEpollFd; +using ::android::hardware::google::pixel::usb::getVendorFunctions; +using ::android::hardware::google::pixel::usb::kDebug; +using ::android::hardware::google::pixel::usb::kDisconnectWaitUs; +using ::android::hardware::google::pixel::usb::linkFunction; +using ::android::hardware::google::pixel::usb::MonitorFfs; +using ::android::hardware::google::pixel::usb::resetGadget; +using ::android::hardware::google::pixel::usb::setVidPid; +using ::android::hardware::google::pixel::usb::unlinkFunctions; +using ::ndk::ScopedAStatus; +using ::std::shared_ptr; +using ::std::string; + +constexpr char kGadgetName[] = "11210000.dwc3"; +constexpr char kProcInterruptsPath[] = "/proc/interrupts"; +constexpr char kProcIrqPath[] = "/proc/irq/"; +constexpr char kSmpAffinityList[] = "/smp_affinity_list"; +#ifndef UDC_PATH +#define UDC_PATH "/sys/class/udc/11210000.dwc3/" +#endif +static MonitorFfs monitorFfs(kGadgetName); + +#define SPEED_PATH UDC_PATH "current_speed" + +#define BIG_CORE "6" +#define MEDIUM_CORE "4" + +#define POWER_SUPPLY_PATH "/sys/class/power_supply/usb/" +#define USB_PORT0_PATH "/sys/class/typec/port0/" + +#define CURRENT_MAX_PATH POWER_SUPPLY_PATH "current_max" +#define CURRENT_USB_TYPE_PATH POWER_SUPPLY_PATH "usb_type" +#define CURRENT_USB_POWER_OPERATION_MODE_PATH USB_PORT0_PATH "power_operation_mode" + +struct UsbGadget : public BnUsbGadget { + UsbGadget(); + + // Makes sure that only one request is processed at a time. + std::mutex mLockSetCurrentFunction; + std::string mGadgetIrqPath; + long mCurrentUsbFunctions; + bool mCurrentUsbFunctionsApplied; + UsbSpeed mUsbSpeed; + + ScopedAStatus setCurrentUsbFunctions(long functions, + const shared_ptr &callback, + int64_t timeout, int64_t in_transactionId) override; + + ScopedAStatus getCurrentUsbFunctions(const shared_ptr &callback, + int64_t in_transactionId) override; + + ScopedAStatus reset(const shared_ptr &callback, + int64_t in_transactionId) override; + + ScopedAStatus getUsbSpeed(const shared_ptr &callback, + int64_t in_transactionId) override; + + ScopedAStatus setVidPid(const char *vid,const char *pid); + + // Indicates to the kernel that the gadget service is ready and the kernel can + // set SDP timeout to a lower value. + void updateSdpEnumTimeout(); + + private: + Status tearDownGadget(); + Status getUsbGadgetIrqPath(); + Status setupFunctions(long functions, const shared_ptr &callback, + uint64_t timeout, int64_t in_transactionId); +}; + +} // namespace gadget +} // namespace usb +} // namespace hardware +} // namespace android +} // aidl diff --git a/aidl/usb/gadget/android.hardware.usb.gadget-service.rc b/aidl/usb/gadget/android.hardware.usb.gadget-service.rc new file mode 100644 index 0000000..68fd3ae --- /dev/null +++ b/aidl/usb/gadget/android.hardware.usb.gadget-service.rc @@ -0,0 +1,19 @@ +service vendor.usb-gadget-hal /vendor/bin/hw/android.hardware.usb.gadget-service + class hal + user system + group system shell mtp + +on post-fs + chown root system /sys/class/typec/port0/power_role + chown root system /sys/class/typec/port0/data_role + chown root system /sys/class/typec/port0/port_type + chown root system /sys/devices/platform/10d60000.hsi2c/i2c-2/i2c-max77759tcpc/contaminant_detection + chown root system /sys/devices/platform/11210000.usb/dwc3_exynos_otg_b_sess + chown root system /sys/devices/platform/11210000.usb/dwc3_exynos_otg_id + chown root system /sys/devices/platform/11210000.usb/usb_data_enabled + chmod 664 /sys/class/typec/port0/power_role + chmod 664 /sys/class/typec/port0/data_role + chmod 664 /sys/class/typec/port0/port_type + chmod 664 /sys/devices/platform/11210000.usb/dwc3_exynos_otg_b_sess + chmod 664 /sys/devices/platform/11210000.usb/dwc3_exynos_otg_id + chmod 664 /sys/devices/platform/11210000.usb/usb_data_enabled diff --git a/aidl/usb/gadget/android.hardware.usb.gadget-service.xml b/aidl/usb/gadget/android.hardware.usb.gadget-service.xml new file mode 100644 index 0000000..e7eebc3 --- /dev/null +++ b/aidl/usb/gadget/android.hardware.usb.gadget-service.xml @@ -0,0 +1,10 @@ + + + android.hardware.usb.gadget + 1 + + IUsbGadget + default + + + diff --git a/aidl/usb/gadget/service_gadget.cpp b/aidl/usb/gadget/service_gadget.cpp new file mode 100644 index 0000000..3634b5d --- /dev/null +++ b/aidl/usb/gadget/service_gadget.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "android.hardware.usb.gadget-service" + +#include +#include +#include +#include +#include "UsbGadget.h" + +using android::OK; +using android::sp; +using android::status_t; + +using aidl::android::hardware::usb::gadget::UsbGadget; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr usbgadget = ndk::SharedRefBase::make(); + + const std::string instance = std::string() + UsbGadget::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(usbgadget->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ALOGV("AIDL USB Gadget HAL about to start"); + ABinderProcess_joinThreadPool(); + return -1; // Should never be reached +} -- 2.20.1