diff --git a/usb/gadget/UsbGadget.cpp b/usb/gadget/UsbGadget.cpp index 9b68e2c4..64fd17b0 100644 --- a/usb/gadget/UsbGadget.cpp +++ b/usb/gadget/UsbGadget.cpp @@ -38,38 +38,18 @@ namespace gadget { string enabledPath; constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c"; -constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.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"; +constexpr char kMax77759TcpcDevName[] = "i2c-max77759tcpc"; +constexpr unsigned int kMax77759TcpcClientId = 0x25; +constexpr char kAccessoryLimitCurrent[] = "usb_limit_accessory_current"; +constexpr char kAccessoryLimitCurrentEnable[] = "usb_limit_accessory_enable"; +constexpr char kUpdateSdpEnumTimeout[] = "update_sdp_enum_timeout"; using ::android::base::GetBoolProperty; using ::android::hardware::google::pixel::usb::kUvcEnabled; -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("") { +UsbGadget::UsbGadget() : mGadgetIrqPath(""), + mI2cBusNumber(-1), + mI2cClientPath("") { if (access(OS_DESC_PATH, R_OK) != 0) { ALOGE("configfs setup not done yet"); abort(); @@ -389,14 +369,16 @@ ScopedAStatus UsbGadget::reset(const shared_ptr &callback, } void UsbGadget::updateSdpEnumTimeout() { - string i2c_node, update_sdp_enum_timeout_path; + string update_sdp_enum_timeout_path; + std::string_view i2cPath; - Status status = getI2cBusHelper(&i2c_node); - if (status != Status::SUCCESS) { + i2cPath = getI2cClientPath(); + if (i2cPath.empty()) { ALOGE("%s: Unable to locate i2c bus node", __func__); + return; } - update_sdp_enum_timeout_path = kI2CPath + i2c_node + "/" + kUpdateSdpEnumTimeout; + update_sdp_enum_timeout_path = std::string{i2cPath} + "/" + 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 { @@ -483,6 +465,75 @@ Status UsbGadget::setupFunctions(long functions, return Status::SUCCESS; } +int UsbGadget::getI2cBusNumber() { + DIR *dp; + unsigned int busNumber; + + // Since the i2c bus number doesn't change after boot, we only need to get + // it once. + if (mI2cBusNumber >= 0) { + return mI2cBusNumber; + } + + dp = opendir(kHsi2cPath); + if (dp != NULL) { + struct dirent *ep; + + while ((ep = readdir(dp))) { + if (ep->d_type == DT_DIR) { + if (sscanf(ep->d_name, "i2c-%u", &busNumber) == 1) { + mI2cBusNumber = busNumber; + break; + } + } + } + closedir(dp); + } + + if (mI2cBusNumber < 0) { + ALOGE("Failed to open %s", kHsi2cPath); + } + return mI2cBusNumber; +} + +std::string_view UsbGadget::getI2cClientPath() { + DIR *dp; + char i2cClientPathLabeled[PATH_MAX]; + char i2cClientPathUnLabeled[PATH_MAX]; + + // Since the I2C client path doesn't change after boot, we only need to get + // it once. + if (!mI2cClientPath.empty()) { + return mI2cClientPath; + } + + if (getI2cBusNumber() < 0) { + return std::string_view{""}; + } + + snprintf(i2cClientPathLabeled, sizeof(i2cClientPathLabeled), + "%s/i2c-%d/%s", kHsi2cPath, mI2cBusNumber, kMax77759TcpcDevName); + snprintf(i2cClientPathUnLabeled, sizeof(i2cClientPathUnLabeled), + "%s/i2c-%d/%d-%04x", kHsi2cPath, mI2cBusNumber, mI2cBusNumber, + kMax77759TcpcClientId); + + dp = opendir(i2cClientPathLabeled); + if (dp != NULL) { + mI2cClientPath.assign(i2cClientPathLabeled); + closedir(dp); + return mI2cClientPath; + } + + dp = opendir(i2cClientPathUnLabeled); + if (dp != NULL) { + mI2cClientPath.assign(i2cClientPathUnLabeled); + closedir(dp); + return mI2cClientPath; + } + + ALOGE("Failed to find the i2c client path under %s", kHsi2cPath); + return std::string_view{""}; +} ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions, const shared_ptr &callback, @@ -492,14 +543,19 @@ ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions, std::string current_usb_power_operation_mode, current_usb_type; std::string usb_limit_sink_enable; - string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath, path; + string accessoryCurrentLimitEnablePath, accessoryCurrentLimitPath; + std::string_view i2cPath; mCurrentUsbFunctions = functions; mCurrentUsbFunctionsApplied = false; - getI2cBusHelper(&path); - accessoryCurrentLimitPath = kI2CPath + path + "/" + kAccessoryLimitCurrent; - accessoryCurrentLimitEnablePath = kI2CPath + path + "/" + kAccessoryLimitCurrentEnable; + i2cPath = getI2cClientPath(); + if (!i2cPath.empty()) { + accessoryCurrentLimitPath = std::string{i2cPath} + "/" + kAccessoryLimitCurrent; + accessoryCurrentLimitEnablePath = std::string{i2cPath} + "/" + kAccessoryLimitCurrentEnable; + } else { + ALOGE("%s: Unable to locate i2c bus node", __func__); + } // Get the gadget IRQ number before tearDownGadget() if (mGadgetIrqPath.empty()) @@ -560,15 +616,17 @@ ScopedAStatus UsbGadget::setCurrentUsbFunctions(long functions, current_usb_type == "Unknown SDP [CDP] DCP" && (current_usb_power_operation_mode == "default" || current_usb_power_operation_mode == "1.5A")) { - if (!WriteStringToFile("1300000", accessoryCurrentLimitPath)) { + if (accessoryCurrentLimitPath.empty() || !WriteStringToFile("1300000", accessoryCurrentLimitPath)) { ALOGI("Write 1.3A to limit current fail"); } else { - if (!WriteStringToFile("1", accessoryCurrentLimitEnablePath)) { + if (accessoryCurrentLimitEnablePath.empty() || + !WriteStringToFile("1", accessoryCurrentLimitEnablePath)) { ALOGI("Enable limit current fail"); } } } else { - if (!WriteStringToFile("0", accessoryCurrentLimitEnablePath)) + if (accessoryCurrentLimitEnablePath.empty() || + !WriteStringToFile("0", accessoryCurrentLimitEnablePath)) ALOGI("unvote accessory limit current failed"); } diff --git a/usb/gadget/UsbGadget.h b/usb/gadget/UsbGadget.h index a6b63bdb..e483a912 100644 --- a/usb/gadget/UsbGadget.h +++ b/usb/gadget/UsbGadget.h @@ -119,7 +119,12 @@ struct UsbGadget : public BnUsbGadget { // set SDP timeout to a lower value. void updateSdpEnumTimeout(); + int getI2cBusNumber(); + std::string_view getI2cClientPath(); + private: + int mI2cBusNumber; + std::string mI2cClientPath; Status tearDownGadget(); Status getUsbGadgetIrqPath(); Status setupFunctions(long functions, const shared_ptr &callback, diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index c2f15c72..6ad737c1 100644 --- a/usb/usb/Usb.cpp +++ b/usb/usb/Usb.cpp @@ -59,17 +59,18 @@ volatile bool destroyThread; string enabledPath; constexpr char kHsi2cPath[] = "/sys/devices/platform/10d50000.hsi2c"; -constexpr char kI2CPath[] = "/sys/devices/platform/10d50000.hsi2c/i2c-"; constexpr char kComplianceWarningsPath[] = "device/non_compliant_reasons"; constexpr char kComplianceWarningBC12[] = "bc12"; constexpr char kComplianceWarningDebugAccessory[] = "debug-accessory"; constexpr char kComplianceWarningMissingRp[] = "missing_rp"; constexpr char kComplianceWarningOther[] = "other"; -constexpr char kContaminantDetectionPath[] = "i2c-max77759tcpc/contaminant_detection"; -constexpr char kStatusPath[] = "i2c-max77759tcpc/contaminant_detection_status"; -constexpr char kSinkLimitEnable[] = "i2c-max77759tcpc/usb_limit_sink_enable"; -constexpr char kSourceLimitEnable[] = "i2c-max77759tcpc/usb_limit_source_enable"; -constexpr char kSinkLimitCurrent[] = "i2c-max77759tcpc/usb_limit_sink_current"; +constexpr char kMax77759TcpcDevName[] = "i2c-max77759tcpc"; +constexpr unsigned int kMax77759TcpcClientId = 0x25; +constexpr char kContaminantDetectionPath[] = "contaminant_detection"; +constexpr char kStatusPath[] = "contaminant_detection_status"; +constexpr char kSinkLimitEnable[] = "usb_limit_sink_enable"; +constexpr char kSourceLimitEnable[] = "usb_limit_source_enable"; +constexpr char kSinkLimitCurrent[] = "usb_limit_sink_current"; constexpr char kTypecPath[] = "/sys/class/typec"; constexpr char kDisableContatminantDetection[] = "vendor.usb.contaminantdisable"; constexpr char kOverheatStatsPath[] = "/sys/devices/platform/google,usbc_port_cooling_dev/"; @@ -220,8 +221,15 @@ ScopedAStatus Usb::resetUsbPort(const std::string& in_portName, int64_t in_trans return ::ndk::ScopedAStatus::ok(); } -Status getI2cBusHelper(string *name) { +int Usb::getI2cBusNumber() { DIR *dp; + unsigned int busNumber; + + // Since the i2c bus number doesn't change after boot, we only need to get + // it once. + if (mI2cBusNumber >= 0) { + return mI2cBusNumber; + } dp = opendir(kHsi2cPath); if (dp != NULL) { @@ -229,22 +237,65 @@ Status getI2cBusHelper(string *name) { 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, "-"); + if (sscanf(ep->d_name, "i2c-%u", &busNumber) == 1) { + mI2cBusNumber = busNumber; + break; } } } closedir(dp); - return Status::SUCCESS; } - ALOGE("Failed to open %s", kHsi2cPath); - return Status::ERROR; + if (mI2cBusNumber < 0) { + ALOGE("Failed to open %s", kHsi2cPath); + } + return mI2cBusNumber; } -Status queryMoistureDetectionStatus(std::vector *currentPortStatus) { - string enabled, status, path, DetectedPath; +std::string_view Usb::getI2cClientPath() { + DIR *dp; + char i2cClientPathLabeled[PATH_MAX]; + char i2cClientPathUnLabeled[PATH_MAX]; + + // Since the I2C client path doesn't change after boot, we only need to get + // it once. + if (!mI2cClientPath.empty()) { + return mI2cClientPath; + } + + if (getI2cBusNumber() < 0) { + return std::string_view{""}; + } + + snprintf(i2cClientPathLabeled, sizeof(i2cClientPathLabeled), + "%s/i2c-%d/%s", kHsi2cPath, mI2cBusNumber, kMax77759TcpcDevName); + snprintf(i2cClientPathUnLabeled, sizeof(i2cClientPathUnLabeled), + "%s/i2c-%d/%d-%04x", kHsi2cPath, mI2cBusNumber, mI2cBusNumber, + kMax77759TcpcClientId); + + dp = opendir(i2cClientPathLabeled); + if (dp != NULL) { + mI2cClientPath.assign(i2cClientPathLabeled); + closedir(dp); + return mI2cClientPath; + } + + dp = opendir(i2cClientPathUnLabeled); + if (dp != NULL) { + mI2cClientPath.assign(i2cClientPathUnLabeled); + closedir(dp); + return mI2cClientPath; + } + + ALOGE("Failed to find the i2c client path under %s", kHsi2cPath); + return std::string_view{""}; +} + +Status queryMoistureDetectionStatus(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus) +{ + string enabled, status, DetectedPath; + std::string_view i2cPath; (*currentPortStatus)[0].supportedContaminantProtectionModes .push_back(ContaminantProtectionMode::FORCE_DISABLE); @@ -253,8 +304,12 @@ Status queryMoistureDetectionStatus(std::vector *currentPortStatus) (*currentPortStatus)[0].supportsEnableContaminantPresenceDetection = true; (*currentPortStatus)[0].supportsEnableContaminantPresenceProtection = false; - getI2cBusHelper(&path); - enabledPath = kI2CPath + path + "/" + kContaminantDetectionPath; + i2cPath = usb->getI2cClientPath(); + if (i2cPath.empty()) { + ALOGE("%s: Unable to locate i2c bus node", __func__); + return Status::ERROR; + } + enabledPath = std::string{i2cPath} + "/" + kContaminantDetectionPath; if (!ReadFileToString(enabledPath, &enabled)) { ALOGE("Failed to open moisture_detection_enabled"); return Status::ERROR; @@ -262,7 +317,7 @@ Status queryMoistureDetectionStatus(std::vector *currentPortStatus) enabled = Trim(enabled); if (enabled == "1") { - DetectedPath = kI2CPath + path + "/" + kStatusPath; + DetectedPath = std::string{i2cPath} + "/" + kStatusPath; if (!ReadFileToString(DetectedPath, &status)) { ALOGE("Failed to open moisture_detected"); return Status::ERROR; @@ -460,7 +515,9 @@ Usb::Usb() ThrottlingSeverity::NONE), ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary2, ThrottlingSeverity::NONE)}, kSamplingIntervalSec), - mUsbDataEnabled(true) { + mUsbDataEnabled(true), + mI2cBusNumber(-1), + mI2cClientPath("") { pthread_condattr_t attr; if (pthread_condattr_init(&attr)) { ALOGE("pthread_condattr_init failed: %s", strerror(errno)); @@ -539,32 +596,38 @@ ScopedAStatus Usb::limitPowerTransfer(const string& in_portName, bool in_limit, int64_t in_transactionId) { bool sessionFail = false, success; std::vector currentPortStatus; - string path, sinkLimitEnablePath, currentLimitPath, sourceLimitEnablePath; - - getI2cBusHelper(&path); - sinkLimitEnablePath = kI2CPath + path + "/" + kSinkLimitEnable; - sourceLimitEnablePath = kI2CPath + path + "/" + kSourceLimitEnable; - currentLimitPath = kI2CPath + path + "/" + kSinkLimitCurrent; + string sinkLimitEnablePath, currentLimitPath, sourceLimitEnablePath; + std::string_view i2cPath; pthread_mutex_lock(&mLock); - if (in_limit) { - success = WriteStringToFile("0", currentLimitPath); + i2cPath = getI2cClientPath(); + if (!i2cPath.empty()) { + sinkLimitEnablePath = std::string{i2cPath} + "/" + kSinkLimitEnable; + sourceLimitEnablePath = std::string{i2cPath} + "/" + kSourceLimitEnable; + currentLimitPath = std::string{i2cPath} + "/" + kSinkLimitCurrent; + + if (in_limit) { + success = WriteStringToFile("0", currentLimitPath); + if (!success) { + ALOGE("Failed to set sink current limit"); + sessionFail = true; + } + } + success = WriteStringToFile(in_limit ? "1" : "0", sinkLimitEnablePath); if (!success) { - ALOGE("Failed to set sink current limit"); + ALOGE("Failed to %s sink current limit: %s", in_limit ? "enable" : "disable", + sinkLimitEnablePath.c_str()); sessionFail = true; } - } - success = WriteStringToFile(in_limit ? "1" : "0", sinkLimitEnablePath); - if (!success) { - ALOGE("Failed to %s sink current limit: %s", in_limit ? "enable" : "disable", - sinkLimitEnablePath.c_str()); + success = WriteStringToFile(in_limit ? "1" : "0", sourceLimitEnablePath); + if (!success) { + ALOGE("Failed to %s source current limit: %s", in_limit ? "enable" : "disable", + sourceLimitEnablePath.c_str()); + sessionFail = true; + } + } else { sessionFail = true; - } - success = WriteStringToFile(in_limit ? "1" : "0", sourceLimitEnablePath); - if (!success) { - ALOGE("Failed to %s source current limit: %s", in_limit ? "enable" : "disable", - sourceLimitEnablePath.c_str()); - sessionFail = true; + ALOGE("%s: Unable to locate i2c bus node", __func__); } ALOGI("limitPowerTransfer limit:%c opId:%ld", in_limit ? 'y' : 'n', in_transactionId); if (mCallback != NULL && in_transactionId >= 0) { @@ -583,11 +646,17 @@ ScopedAStatus Usb::limitPowerTransfer(const string& in_portName, bool in_limit, return ScopedAStatus::ok(); } -Status queryPowerTransferStatus(std::vector *currentPortStatus) { - string limitedPath, enabled, path; +Status queryPowerTransferStatus(android::hardware::usb::Usb *usb, + std::vector *currentPortStatus) { + string limitedPath, enabled; + std::string_view i2cPath; - getI2cBusHelper(&path); - limitedPath = kI2CPath + path + "/" + kSinkLimitEnable; + i2cPath = usb->getI2cClientPath(); + if (i2cPath.empty()) { + ALOGE("%s: Unable to locate i2c bus node", __func__); + return Status::ERROR; + } + limitedPath = std::string{i2cPath} + "/" + kSinkLimitEnable; if (!ReadFileToString(limitedPath, &enabled)) { ALOGE("Failed to open limit_sink_enable"); return Status::ERROR; @@ -823,8 +892,8 @@ void queryVersionHelper(android::hardware::usb::Usb *usb, Status status; pthread_mutex_lock(&usb->mLock); status = getPortStatusHelper(usb, currentPortStatus); - queryMoistureDetectionStatus(currentPortStatus); - queryPowerTransferStatus(currentPortStatus); + queryMoistureDetectionStatus(usb, currentPortStatus); + queryPowerTransferStatus(usb, currentPortStatus); queryNonCompliantChargerStatus(currentPortStatus); if (usb->mCallback != NULL) { ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus, diff --git a/usb/usb/Usb.h b/usb/usb/Usb.h index aa8a1499..409d6a09 100644 --- a/usb/usb/Usb.h +++ b/usb/usb/Usb.h @@ -111,9 +111,13 @@ struct Usb : public BnUsb { std::function cb; }; std::map mEpollEntries; + int getI2cBusNumber(); + std::string_view getI2cClientPath(); private: pthread_t mPoll; + int mI2cBusNumber; + std::string mI2cClientPath; }; } // namespace usb