Merge "usb: reattempt to enter displayport alt mode if driver entry process fails" into main

This commit is contained in:
RD Babiera 2023-11-17 22:12:05 +00:00 committed by Android (Google) Code Review
commit 637426c6a8
2 changed files with 75 additions and 3 deletions

View file

@ -550,6 +550,11 @@ Usb::Usb()
ALOGE("mDisplayPortDebounceTimer timerfd failed: %s", strerror(errno)); ALOGE("mDisplayPortDebounceTimer timerfd failed: %s", strerror(errno));
abort(); abort();
} }
mDisplayPortActivateTimer = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
if (mDisplayPortActivateTimer == -1) {
ALOGE("mDisplayPortActivateTimer timerfd failed: %s", strerror(errno));
abort();
}
} }
ScopedAStatus Usb::switchRole(const string& in_portName, const PortRole& in_role, ScopedAStatus Usb::switchRole(const string& in_portName, const PortRole& in_role,
@ -1496,6 +1501,10 @@ static int displayPortPollOpenFileHelper(const char *file, int flags) {
return fd; return fd;
} }
/*
* armTimerFdHelper - Sets timerfd (fd) to trigger after (ms) milliseconds.
* Setting ms to 0 disarms the timer.
*/
static int armTimerFdHelper(int fd, int ms) { static int armTimerFdHelper(int fd, int ms) {
struct itimerspec ts; struct itimerspec ts;
@ -1508,23 +1517,31 @@ static int armTimerFdHelper(int fd, int ms) {
} }
void *displayPortPollWork(void *param) { void *displayPortPollWork(void *param) {
/* USB Payload */
::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param;
/* Epoll fields */
int epoll_fd; int epoll_fd;
struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link, ev_debounce; struct epoll_event ev_hpd, ev_pin, ev_orientation, ev_eventfd, ev_link, ev_debounce;
struct epoll_event ev_activate;
int nevents = 0; int nevents = 0;
int hpd_fd, pin_fd, orientation_fd, link_training_status_fd; int hpd_fd, pin_fd, orientation_fd, link_training_status_fd;
int file_flags = O_RDONLY; int file_flags = O_RDONLY;
int epoll_flags; int epoll_flags;
/* DisplayPort link statuses */
bool orientationSet = false; bool orientationSet = false;
bool pinSet = false; bool pinSet = false;
int activateRetryCount = 0;
unsigned long res; unsigned long res;
int ret = 0; int ret = 0;
/* File paths */
string displayPortUsbPath, irqHpdCountPath, hpdPath, pinAssignmentPath, orientationPath; string displayPortUsbPath, irqHpdCountPath, hpdPath, pinAssignmentPath, orientationPath;
string tcpcI2cBus, linkPath; string tcpcI2cBus, linkPath, partnerActivePath, portActivePath;
::aidl::android::hardware::usb::Usb *usb = (::aidl::android::hardware::usb::Usb *)param;
usb->mDisplayPortPollRunning = true; usb->mDisplayPortPollRunning = true;
usb->mDisplayPortPollStarting = false; usb->mDisplayPortPollStarting = false;
/*---------- Setup ----------*/
if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) { if (usb->getDisplayPortUsbPathHelper(&displayPortUsbPath) == Status::ERROR) {
ALOGE("usbdp: worker: could not locate usb displayport directory"); ALOGE("usbdp: worker: could not locate usb displayport directory");
goto usb_path_error; goto usb_path_error;
@ -1536,6 +1553,9 @@ void *displayPortPollWork(void *param) {
orientationPath = "/sys/class/typec/port0/orientation"; orientationPath = "/sys/class/typec/port0/orientation";
linkPath = string(kDisplayPortDrmPath) + "link_status"; linkPath = string(kDisplayPortDrmPath) + "link_status";
partnerActivePath = displayPortUsbPath + "../mode1/active";
portActivePath = "/sys/class/typec/port0/port0.0/mode1/active";
getI2cBusHelper(&tcpcI2cBus); getI2cBusHelper(&tcpcI2cBus);
irqHpdCountPath = kI2CPath + tcpcI2cBus + "/" + tcpcI2cBus + kIrqHpdCounPath; irqHpdCountPath = kI2CPath + tcpcI2cBus + "/" + tcpcI2cBus + kIrqHpdCounPath;
ALOGI("usbdp: worker: irqHpdCountPath:%s", irqHpdCountPath.c_str()); ALOGI("usbdp: worker: irqHpdCountPath:%s", irqHpdCountPath.c_str());
@ -1568,12 +1588,15 @@ void *displayPortPollWork(void *param) {
ev_eventfd.events = epoll_flags; ev_eventfd.events = epoll_flags;
ev_link.events = epoll_flags; ev_link.events = epoll_flags;
ev_debounce.events = epoll_flags; ev_debounce.events = epoll_flags;
ev_activate.events = epoll_flags;
ev_hpd.data.fd = hpd_fd; ev_hpd.data.fd = hpd_fd;
ev_pin.data.fd = pin_fd; ev_pin.data.fd = pin_fd;
ev_orientation.data.fd = orientation_fd; ev_orientation.data.fd = orientation_fd;
ev_eventfd.data.fd = usb->mDisplayPortEventPipe; ev_eventfd.data.fd = usb->mDisplayPortEventPipe;
ev_link.data.fd = link_training_status_fd; ev_link.data.fd = link_training_status_fd;
ev_debounce.data.fd = usb->mDisplayPortDebounceTimer; ev_debounce.data.fd = usb->mDisplayPortDebounceTimer;
ev_activate.data.fd = usb->mDisplayPortActivateTimer;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) { if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, hpd_fd, &ev_hpd) == -1) {
ALOGE("usbdp: worker: epoll_ctl failed to add hpd; errno=%d", errno); ALOGE("usbdp: worker: epoll_ctl failed to add hpd; errno=%d", errno);
@ -1592,7 +1615,11 @@ void *displayPortPollWork(void *param) {
goto error; goto error;
} }
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortDebounceTimer, &ev_debounce) == -1) { if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortDebounceTimer, &ev_debounce) == -1) {
ALOGE("usbdp: worker: epoll_ctl failed to add debounce; errno=%d", errno); ALOGE("usbdp: worker: epoll_ctl failed to add framework update debounce; errno=%d", errno);
goto error;
}
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortActivateTimer, &ev_activate) == -1) {
ALOGE("usbdp: worker: epoll_ctl failed to add activate debounce; errno=%d", errno);
goto error; goto error;
} }
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortEventPipe, &ev_eventfd) == -1) { if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, usb->mDisplayPortEventPipe, &ev_eventfd) == -1) {
@ -1600,6 +1627,9 @@ void *displayPortPollWork(void *param) {
goto error; goto error;
} }
/* Arm timer to see if DisplayPort Alt Mode Activates */
armTimerFdHelper(usb->mDisplayPortActivateTimer, DISPLAYPORT_ACTIVATE_DEBOUNCE_MS);
while (!destroyDisplayPortThread) { while (!destroyDisplayPortThread) {
struct epoll_event events[64]; struct epoll_event events[64];
@ -1649,6 +1679,33 @@ void *displayPortPollWork(void *param) {
if (ret < 0) if (ret < 0)
ALOGE("usbdp: debounce read errno:%d", errno); ALOGE("usbdp: debounce read errno:%d", errno);
queryVersionHelper(usb, &currentPortStatus); queryVersionHelper(usb, &currentPortStatus);
} else if (events[n].data.fd == usb->mDisplayPortActivateTimer) {
string activePartner, activePort;
if (ReadFileToString(partnerActivePath.c_str(), &activePartner) &&
ReadFileToString(portActivePath.c_str(), &activePort)) {
// Retry activate signal when DisplayPort Alt Mode is active on port but not
// partner.
if (!strncmp(activePartner.c_str(), "no", strlen("no")) &&
!strncmp(activePort.c_str(), "yes", strlen("yes")) &&
activateRetryCount < DISPLAYPORT_ACTIVATE_MAX_RETRIES) {
if (!WriteStringToFile("1", partnerActivePath)) {
ALOGE("usbdp: Failed to activate port partner Alt Mode");
} else {
ALOGI("usbdp: Attempting to activate port partner Alt Mode");
}
activateRetryCount++;
armTimerFdHelper(usb->mDisplayPortActivateTimer,
DISPLAYPORT_ACTIVATE_DEBOUNCE_MS);
} else {
ALOGI("usbdp: DisplayPort Alt Mode is active, or disabled on port");
}
} else {
activateRetryCount++;
armTimerFdHelper(usb->mDisplayPortActivateTimer,
DISPLAYPORT_ACTIVATE_DEBOUNCE_MS);
ALOGE("usbdp: Failed to read active state from port or partner");
}
} else if (events[n].data.fd == usb->mDisplayPortEventPipe) { } else if (events[n].data.fd == usb->mDisplayPortEventPipe) {
uint64_t flag = 0; uint64_t flag = 0;
if (!read(usb->mDisplayPortEventPipe, &flag, sizeof(flag))) { if (!read(usb->mDisplayPortEventPipe, &flag, sizeof(flag))) {
@ -1670,6 +1727,8 @@ void *displayPortPollWork(void *param) {
} }
error: error:
/* Need to disarm so new threads don't get old event */
armTimerFdHelper(usb->mDisplayPortActivateTimer, 0);
close(link_training_status_fd); close(link_training_status_fd);
link_training_status_fd_error: link_training_status_fd_error:
close(orientation_fd); close(orientation_fd);
@ -1679,6 +1738,7 @@ pin_fd_error:
close(hpd_fd); close(hpd_fd);
hpd_fd_error: hpd_fd_error:
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortDebounceTimer, &ev_debounce); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortDebounceTimer, &ev_debounce);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortActivateTimer, &ev_activate);
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortEventPipe, &ev_eventfd); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, usb->mDisplayPortEventPipe, &ev_eventfd);
close(epoll_fd); close(epoll_fd);
epoll_fd_error: epoll_fd_error:

View file

@ -31,6 +31,13 @@
#define PORT_TYPE_TIMEOUT 8 #define PORT_TYPE_TIMEOUT 8
#define DISPLAYPORT_CAPABILITIES_RECEPTACLE_BIT 6 #define DISPLAYPORT_CAPABILITIES_RECEPTACLE_BIT 6
#define DISPLAYPORT_STATUS_DEBOUNCE_MS 2000 #define DISPLAYPORT_STATUS_DEBOUNCE_MS 2000
/*
* Type-C HAL should wait 2 seconds to reattempt DisplayPort Alt Mode entry to
* allow the port and port partner to settle Role Swaps.
*/
#define DISPLAYPORT_ACTIVATE_DEBOUNCE_MS 2000
// Number of times the HAL should reattempt to enter DisplayPort Alt Mode
#define DISPLAYPORT_ACTIVATE_MAX_RETRIES 2
namespace aidl { namespace aidl {
namespace android { namespace android {
@ -142,6 +149,11 @@ struct Usb : public BnUsb {
* sending notifications to the frameworks layer. * sending notifications to the frameworks layer.
*/ */
int mDisplayPortDebounceTimer; int mDisplayPortDebounceTimer;
/*
* eventfd to monitor whether a connection results in DisplayPort Alt Mode activating.
*/
int mDisplayPortActivateTimer;
private: private:
pthread_t mPoll; pthread_t mPoll;
pthread_t mDisplayPortPoll; pthread_t mDisplayPortPoll;