diff options
Diffstat (limited to 'usb/usb/Usb.cpp')
-rw-r--r-- | usb/usb/Usb.cpp | 214 |
1 files changed, 165 insertions, 49 deletions
diff --git a/usb/usb/Usb.cpp b/usb/usb/Usb.cpp index 7a148887..a898b053 100644 --- a/usb/usb/Usb.cpp +++ b/usb/usb/Usb.cpp @@ -26,7 +26,6 @@ #include <stdio.h> #include <sys/types.h> #include <unistd.h> -#include <chrono> #include <regex> #include <thread> #include <unordered_map> @@ -39,9 +38,12 @@ #include "Usb.h" #include <aidl/android/frameworks/stats/IStats.h> +#include <android_hardware_usb_flags.h> #include <pixelusb/UsbGadgetCommon.h> #include <pixelstats/StatsHelper.h> +namespace usb_flags = android::hardware::usb::flags; + using aidl::android::frameworks::stats::IStats; using android::base::GetProperty; using android::base::Tokenize; @@ -59,17 +61,19 @@ 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 kComplianceWarningInputPowerLimited[] = "input_power_limited"; +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/"; @@ -81,6 +85,17 @@ constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm"; constexpr char kPogoUsbActive[] = "/sys/devices/platform/google,pogo/pogo_usb_active"; constexpr char KPogoMoveDataToUsb[] = "/sys/devices/platform/google,pogo/move_data_to_usb"; constexpr char kPowerSupplyUsbType[] = "/sys/class/power_supply/usb/usb_type"; +constexpr char kUdcUeventRegex[] = + "/devices/platform/11110000.usb/11110000.dwc3/udc/11110000.dwc3"; +constexpr char kUdcStatePath[] = + "/sys/devices/platform/11110000.usb/11110000.dwc3/udc/11110000.dwc3/state"; +constexpr char kHost1UeventRegex[] = + "/devices/platform/11110000.usb/11110000.dwc3/xhci-hcd-exynos.[0-9].auto/usb2/2-0:1.0"; +constexpr char kHost1StatePath[] = "/sys/bus/usb/devices/usb2/2-0:1.0/usb2-port1/state"; +constexpr char kHost2UeventRegex[] = + "/devices/platform/11110000.usb/11110000.dwc3/xhci-hcd-exynos.[0-9].auto/usb3/3-0:1.0"; +constexpr char kHost2StatePath[] = "/sys/bus/usb/devices/usb3/3-0:1.0/usb3-port1/state"; +constexpr char kDataRolePath[] = "/sys/devices/platform/11110000.usb/new_data_role"; constexpr int kSamplingIntervalSec = 5; void queryVersionHelper(android::hardware::usb::Usb *usb, std::vector<PortStatus> *currentPortStatus); @@ -215,8 +230,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) { @@ -224,22 +246,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; +} + +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(std::vector<PortStatus> *currentPortStatus) { - string enabled, status, path, DetectedPath; +Status queryMoistureDetectionStatus(android::hardware::usb::Usb *usb, + std::vector<PortStatus> *currentPortStatus) +{ + string enabled, status, DetectedPath; + std::string_view i2cPath; (*currentPortStatus)[0].supportedContaminantProtectionModes .push_back(ContaminantProtectionMode::FORCE_DISABLE); @@ -248,8 +313,12 @@ Status queryMoistureDetectionStatus(std::vector<PortStatus> *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; @@ -257,7 +326,7 @@ Status queryMoistureDetectionStatus(std::vector<PortStatus> *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; @@ -307,9 +376,20 @@ Status queryNonCompliantChargerStatus(std::vector<PortStatus> *currentPortStatus continue; } if (!strncmp(reason.c_str(), kComplianceWarningOther, - strlen(kComplianceWarningOther))) { - (*currentPortStatus)[i].complianceWarnings.push_back(ComplianceWarning::OTHER); - continue; + strlen(kComplianceWarningOther)) || + !strncmp(reason.c_str(), kComplianceWarningInputPowerLimited, + strlen(kComplianceWarningInputPowerLimited))) { + if (usb_flags::enable_usb_data_compliance_warning() && + usb_flags::enable_input_power_limited_warning()) { + ALOGI("Report through INPUT_POWER_LIMITED warning"); + (*currentPortStatus)[i].complianceWarnings.push_back( + ComplianceWarning::INPUT_POWER_LIMITED); + continue; + } else { + (*currentPortStatus)[i].complianceWarnings.push_back( + ComplianceWarning::OTHER); + continue; + } } } if ((*currentPortStatus)[i].complianceWarnings.size() > 0 && @@ -442,11 +522,20 @@ bool switchMode(const string &portName, const PortRole &in_role, struct Usb *usb return roleSwitch; } +void updatePortStatus(android::hardware::usb::Usb *usb) { + std::vector<PortStatus> currentPortStatus; + + queryVersionHelper(usb, ¤tPortStatus); +} + Usb::Usb() : mLock(PTHREAD_MUTEX_INITIALIZER), mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER), mPartnerLock(PTHREAD_MUTEX_INITIALIZER), mPartnerUp(false), + mUsbDataSessionMonitor(kUdcUeventRegex, kUdcStatePath, kHost1UeventRegex, kHost1StatePath, + kHost2UeventRegex, kHost2StatePath, kDataRolePath, + std::bind(&updatePortStatus, this)), mOverheat(ZoneInfo(TemperatureType::USB_PORT, kThermalZoneForTrip, ThrottlingSeverity::CRITICAL), {ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadPrimary, @@ -455,7 +544,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)); @@ -534,32 +625,38 @@ ScopedAStatus Usb::limitPowerTransfer(const string& in_portName, bool in_limit, int64_t in_transactionId) { bool sessionFail = false, success; std::vector<PortStatus> 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) { @@ -578,11 +675,17 @@ ScopedAStatus Usb::limitPowerTransfer(const string& in_portName, bool in_limit, return ScopedAStatus::ok(); } -Status queryPowerTransferStatus(std::vector<PortStatus> *currentPortStatus) { - string limitedPath, enabled, path; +Status queryPowerTransferStatus(android::hardware::usb::Usb *usb, + std::vector<PortStatus> *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; @@ -813,14 +916,27 @@ done: return Status::ERROR; } +void queryUsbDataSession(android::hardware::usb::Usb *usb, + std::vector<PortStatus> *currentPortStatus) { + std::vector<ComplianceWarning> warnings; + + usb->mUsbDataSessionMonitor.getComplianceWarnings( + (*currentPortStatus)[0].currentDataRole, &warnings); + (*currentPortStatus)[0].complianceWarnings.insert( + (*currentPortStatus)[0].complianceWarnings.end(), + warnings.begin(), + warnings.end()); +} + void queryVersionHelper(android::hardware::usb::Usb *usb, std::vector<PortStatus> *currentPortStatus) { Status status; pthread_mutex_lock(&usb->mLock); status = getPortStatusHelper(usb, currentPortStatus); - queryMoistureDetectionStatus(currentPortStatus); - queryPowerTransferStatus(currentPortStatus); + queryMoistureDetectionStatus(usb, currentPortStatus); + queryPowerTransferStatus(usb, currentPortStatus); queryNonCompliantChargerStatus(currentPortStatus); + queryUsbDataSession(usb, currentPortStatus); if (usb->mCallback != NULL) { ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus, status); |