sm8450-common: udfps: Defer extCmd until fod ui is ready
This does not work with xiaomi's original display driver,
since partial reads from it are broken and it rejects all
reads whose size is insufficient to get the whole response.
However, the size is not known in prior, so we actually
want to read the header first to determine the actual size
and continue reading then. This requires a kernel side fix
like [1].
To make this work with the stock kernel driver instead,
adjust the parseDispEvent method to read with a larger
buffer directly and decrease the size of the data
according to the header later.
[1]: b80cb5a028
Change-Id: Id8f9ac8ef32462dd00832af12ff60a3610103e2a
This commit is contained in:
parent
abee51ea08
commit
1198676eff
1 changed files with 69 additions and 2 deletions
|
@ -60,6 +60,27 @@ static bool readBool(int fd) {
|
|||
return c != '0';
|
||||
}
|
||||
|
||||
static disp_event_resp* parseDispEvent(int fd) {
|
||||
disp_event header;
|
||||
ssize_t headerSize = read(fd, &header, sizeof(header));
|
||||
if (headerSize < sizeof(header)) {
|
||||
LOG(ERROR) << "unexpected display event header size: " << headerSize;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
struct disp_event_resp* response =
|
||||
reinterpret_cast<struct disp_event_resp*>(malloc(header.length));
|
||||
response->base = header;
|
||||
int dataLength = response->base.length - sizeof(response->base);
|
||||
ssize_t dataSize = read(fd, &response->data, dataLength);
|
||||
if (dataSize < dataLength) {
|
||||
LOG(ERROR) << "unexpected display event data size: " << dataSize;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class XiaomiSm8450UdfpsHander : public UdfpsHandler {
|
||||
|
@ -103,6 +124,54 @@ class XiaomiSm8450UdfpsHander : public UdfpsHandler {
|
|||
ioctl(disp_fd_.get(), MI_DISP_IOCTL_SET_LOCAL_HBM, &req);
|
||||
}
|
||||
}).detach();
|
||||
|
||||
// Thread to listen for fod ui changes
|
||||
std::thread([this]() {
|
||||
int fd = open(DISP_FEATURE_PATH, O_RDWR);
|
||||
if (fd < 0) {
|
||||
LOG(ERROR) << "failed to open " << DISP_FEATURE_PATH << " , err: " << fd;
|
||||
return;
|
||||
}
|
||||
|
||||
// Register for FOD events
|
||||
disp_event_req req;
|
||||
req.base.flag = 0;
|
||||
req.base.disp_id = MI_DISP_PRIMARY;
|
||||
req.type = MI_DISP_EVENT_FOD;
|
||||
ioctl(fd, MI_DISP_IOCTL_REGISTER_EVENT, &req);
|
||||
|
||||
struct pollfd dispEventPoll = {
|
||||
.fd = fd,
|
||||
.events = POLLIN,
|
||||
.revents = 0,
|
||||
};
|
||||
|
||||
while (true) {
|
||||
int rc = poll(&dispEventPoll, 1, -1);
|
||||
if (rc < 0) {
|
||||
LOG(ERROR) << "failed to poll " << FOD_PRESS_STATUS_PATH << ", err: " << rc;
|
||||
continue;
|
||||
}
|
||||
|
||||
struct disp_event_resp* response = parseDispEvent(fd);
|
||||
if (response == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (response->base.type != MI_DISP_EVENT_FOD) {
|
||||
LOG(ERROR) << "unexpected display event: " << response->base.type;
|
||||
continue;
|
||||
}
|
||||
|
||||
int value = response->data[0];
|
||||
LOG(DEBUG) << "received data: " << std::bitset<8>(value);
|
||||
|
||||
bool localHbmUiReady = value & LOCAL_HBM_UI_READY;
|
||||
|
||||
mDevice->extCmd(mDevice, COMMAND_NIT,
|
||||
localHbmUiReady ? PARAM_NIT_FOD : PARAM_NIT_NONE);
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
void onFingerDown(uint32_t /*x*/, uint32_t /*y*/, float /*minor*/, float /*major*/) {
|
||||
|
@ -171,8 +240,6 @@ class XiaomiSm8450UdfpsHander : public UdfpsHandler {
|
|||
}
|
||||
|
||||
void setFingerDown(bool pressed) {
|
||||
mDevice->extCmd(mDevice, COMMAND_NIT, pressed ? PARAM_NIT_FOD : PARAM_NIT_NONE);
|
||||
|
||||
int buf[MAX_BUF_SIZE] = {MI_DISP_PRIMARY, THP_FOD_DOWNUP_CTL, pressed ? 1 : 0};
|
||||
ioctl(touch_fd_.get(), TOUCH_IOC_SET_CUR_VALUE, &buf);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue