summaryrefslogtreecommitdiff
path: root/usb/usb/Usb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'usb/usb/Usb.cpp')
-rw-r--r--usb/usb/Usb.cpp214
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, &currentPortStatus);
+}
+
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);