diff --git a/Android.bp b/Android.bp index c0ed453..d87505e 100644 --- a/Android.bp +++ b/Android.bp @@ -7,6 +7,7 @@ soong_namespace { imports: [ "hardware/qcom-caf/bootctrl", + "hardware/xiaomi", "vendor/qcom/opensource/commonsys-intf/display", ], } diff --git a/common.mk b/common.mk index 1963d70..e34d83f 100644 --- a/common.mk +++ b/common.mk @@ -154,6 +154,10 @@ PRODUCT_PACKAGES += \ android.hardware.dumpstate@1.1.vendor # Fingerprint +PRODUCT_PACKAGES += \ + android.hardware.biometrics.fingerprint@2.3-service.xiaomi \ + libudfpshandler + PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml @@ -370,7 +374,8 @@ PRODUCT_PACKAGES += \ # Soong namespaces PRODUCT_SOONG_NAMESPACES += \ - $(LOCAL_PATH) + $(LOCAL_PATH) \ + hardware/xiaomi # Telephony PRODUCT_PACKAGES += \ diff --git a/udfps/Android.bp b/udfps/Android.bp new file mode 100644 index 0000000..41adbf2 --- /dev/null +++ b/udfps/Android.bp @@ -0,0 +1,17 @@ +// +// Copyright (C) 2022 The LineageOS Project +// +// SPDX-License-Identifier: Apache-2.0 +// + +cc_library { + name: "libudfpshandler", + vendor: true, + srcs: ["UdfpsHandler.cpp"], + shared_libs: [ + "libbase", + ], + header_libs: [ + "//hardware/xiaomi:xiaomifingerprint_headers", + ], +} diff --git a/udfps/UdfpsHandler.cpp b/udfps/UdfpsHandler.cpp new file mode 100644 index 0000000..9895c7f --- /dev/null +++ b/udfps/UdfpsHandler.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2022 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_TAG "UdfpsHandler.xiaomi_sm8450" + +#include +#include + +#include +#include +#include +#include + +#include "UdfpsHandler.h" +#include "xiaomi_touch.h" + +#define COMMAND_NIT 10 +#define PARAM_NIT_FOD 1 +#define PARAM_NIT_NONE 0 + +#define COMMAND_FOD_PRESS_STATUS 1 +#define PARAM_FOD_PRESSED 1 +#define PARAM_FOD_RELEASED 0 + +#define FOD_STATUS_OFF 0 +#define FOD_STATUS_ON 1 + +#define TOUCH_DEV_PATH "/dev/xiaomi-touch" +#define TOUCH_ID 0 +#define TOUCH_MAGIC 'T' +#define TOUCH_IOC_SET_CUR_VALUE _IO(TOUCH_MAGIC, SET_CUR_VALUE) +#define TOUCH_IOC_GET_CUR_VALUE _IO(TOUCH_MAGIC, GET_CUR_VALUE) + +#define DISP_PARAM_PATH "sys/devices/virtual/mi_display/disp_feature/disp-DSI-0/disp_param" +#define DISP_PARAM_LOCAL_HBM_MODE "9" +#define DISP_PARAM_LOCAL_HBM_OFF "0" +#define DISP_PARAM_LOCAL_HBM_ON "1" + +#define FOD_PRESS_STATUS_PATH "/sys/class/touch/touch_dev/fod_press_status" + +namespace { + +template +static void set(const std::string& path, const T& value) { + std::ofstream file(path); + file << value; +} + +static bool readBool(int fd) { + char c; + int rc; + + rc = lseek(fd, 0, SEEK_SET); + if (rc) { + LOG(ERROR) << "failed to seek fd, err: " << rc; + return false; + } + + rc = read(fd, &c, sizeof(char)); + if (rc != 1) { + LOG(ERROR) << "failed to read bool from fd, err: " << rc; + return false; + } + + return c != '0'; +} + +} // anonymous namespace + +class XiaomiSm8450UdfpsHander : public UdfpsHandler { + public: + void init(fingerprint_device_t* device) { + mDevice = device; + touch_fd_ = android::base::unique_fd(open(TOUCH_DEV_PATH, O_RDWR)); + + std::thread([this]() { + int fd = open(FOD_PRESS_STATUS_PATH, O_RDONLY); + if (fd < 0) { + LOG(ERROR) << "failed to open fd, err: " << fd; + return; + } + + struct pollfd fodPressStatusPoll = { + .fd = fd, + .events = POLLERR | POLLPRI, + .revents = 0, + }; + + while (true) { + int rc = poll(&fodPressStatusPoll, 1, -1); + if (rc < 0) { + LOG(ERROR) << "failed to poll fd, err: " << rc; + continue; + } + + mDevice->extCmd(mDevice, COMMAND_FOD_PRESS_STATUS, + readBool(fd) ? PARAM_FOD_PRESSED : PARAM_FOD_RELEASED); + } + }).detach(); + } + + void onFingerDown(uint32_t /*x*/, uint32_t /*y*/, float /*minor*/, float /*major*/) { + LOG(INFO) << __func__; + setFingerDown(true); + } + + void onFingerUp() { + LOG(INFO) << __func__; + setFingerDown(false); + } + + void onAcquired(int32_t result, int32_t vendorCode) { + LOG(INFO) << __func__ << " result: " << result << " vendorCode: " << vendorCode; + if (result == FINGERPRINT_ACQUIRED_GOOD) { + setFingerDown(false); + setFodStatus(FOD_STATUS_OFF); + } else if (vendorCode == 21 || vendorCode == 23) { + /* + * vendorCode = 21 waiting for fingerprint authentication + * vendorCode = 23 waiting for fingerprint enroll + */ + setFodStatus(FOD_STATUS_ON); + } + } + + void cancel() { + LOG(INFO) << __func__; + setFingerDown(false); + setFodStatus(FOD_STATUS_OFF); + } + + private: + fingerprint_device_t* mDevice; + android::base::unique_fd touch_fd_; + + void setFodStatus(int value) { + int buf[MAX_BUF_SIZE] = {TOUCH_ID, Touch_Fod_Enable, value}; + ioctl(touch_fd_.get(), TOUCH_IOC_SET_CUR_VALUE, &buf); + } + + void setFingerDown(bool pressed) { + mDevice->extCmd(mDevice, COMMAND_NIT, pressed ? PARAM_NIT_FOD : PARAM_NIT_NONE); + + int buf[MAX_BUF_SIZE] = {TOUCH_ID, THP_FOD_DOWNUP_CTL, pressed ? 1 : 0}; + ioctl(touch_fd_.get(), TOUCH_IOC_SET_CUR_VALUE, &buf); + + set(DISP_PARAM_PATH, + std::string(DISP_PARAM_LOCAL_HBM_MODE) + " " + + (pressed ? DISP_PARAM_LOCAL_HBM_ON : DISP_PARAM_LOCAL_HBM_OFF)); + } +}; + +static UdfpsHandler* create() { + return new XiaomiSm8450UdfpsHander(); +} + +static void destroy(UdfpsHandler* handler) { + delete handler; +} + +extern "C" UdfpsHandlerFactory UDFPS_HANDLER_FACTORY = { + .create = create, + .destroy = destroy, +}; diff --git a/udfps/xiaomi_touch.h b/udfps/xiaomi_touch.h new file mode 100644 index 0000000..14bddfa --- /dev/null +++ b/udfps/xiaomi_touch.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 The LineageOS Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/*CUR,DEFAULT,MIN,MAX*/ +#define VALUE_TYPE_SIZE 6 +#define VALUE_GRIP_SIZE 9 +#define MAX_BUF_SIZE 256 +#define BTN_INFO 0x152 +#define MAX_TOUCH_ID 10 +#define RAW_BUF_NUM 4 +#define THP_CMD_BASE 1000 + +enum MODE_CMD { + SET_CUR_VALUE = 0, + GET_CUR_VALUE, + GET_DEF_VALUE, + GET_MIN_VALUE, + GET_MAX_VALUE, + GET_MODE_VALUE, + RESET_MODE, + SET_LONG_VALUE, +}; + +enum MODE_TYPE { + Touch_Game_Mode = 0, + Touch_Active_MODE = 1, + Touch_UP_THRESHOLD = 2, + Touch_Tolerance = 3, + Touch_Aim_Sensitivity = 4, + Touch_Tap_Stability = 5, + Touch_Expert_Mode = 6, + Touch_Edge_Filter = 7, + Touch_Panel_Orientation = 8, + Touch_Report_Rate = 9, + Touch_Fod_Enable = 10, + Touch_Aod_Enable = 11, + Touch_Resist_RF = 12, + Touch_Idle_Time = 13, + Touch_Doubletap_Mode = 14, + Touch_Grip_Mode = 15, + Touch_FodIcon_Enable = 16, + Touch_Nonui_Mode = 17, + Touch_Debug_Level = 18, + Touch_Power_Status = 19, + Touch_Mode_NUM = 20, + THP_LOCK_SCAN_MODE = THP_CMD_BASE + 0, + THP_FOD_DOWNUP_CTL = THP_CMD_BASE + 1, + THP_SELF_CAP_SCAN = THP_CMD_BASE + 2, + THP_REPORT_POINT_SWITCH = THP_CMD_BASE + 3, + THP_HAL_INIT_READY = THP_CMD_BASE + 4, +};