sm8250-common: vibrator: Implement OOS style effects for LED vibrator
This change implements the following effects: - Effect::CLICK - Effect::DOUBLE_CLICK - Effect::TICK - Effect::HEAVY_CLICK Effect write streams were dumped using following strace command: - strace -fp `pidof vendor.oneplus.hardware.lmvibrator@1.0-service` -e openat,write Also, these effects can easily be tested with following test app: - https://github.com/luk1337/VibeTest Change-Id: Ie65caa0c65dc81bb35a7bcc56870649e895ced3f
This commit is contained in:
parent
dc3d086fbd
commit
04cf04fab5
2 changed files with 85 additions and 17 deletions
|
@ -34,6 +34,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <log/log.h>
|
#include <log/log.h>
|
||||||
|
#include <map>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -58,6 +59,53 @@ namespace vibrator {
|
||||||
|
|
||||||
static const char LED_DEVICE[] = "/sys/class/leds/vibrator";
|
static const char LED_DEVICE[] = "/sys/class/leds/vibrator";
|
||||||
|
|
||||||
|
static std::map<Effect, std::vector<std::pair<std::string, std::string>>> LED_EFFECTS{
|
||||||
|
{ Effect::CLICK, {
|
||||||
|
{ "/sys/class/leds/vibrator/ignore_store", "0" },
|
||||||
|
{ "/sys/class/leds/vibrator/duration", "10" },
|
||||||
|
{ "/sys/class/leds/vibrator/vmax", "0x1f" },
|
||||||
|
{ "/sys/class/leds/vibrator/gain", "0x80" },
|
||||||
|
{ "/sys/class/leds/vibrator/seq", "0x00 0x03" },
|
||||||
|
{ "/sys/class/leds/vibrator/loop", "0x00 0x00" },
|
||||||
|
{ "/sys/class/leds/vibrator/brightness", "1" },
|
||||||
|
}},
|
||||||
|
{ Effect::DOUBLE_CLICK, {
|
||||||
|
{ "/sys/class/leds/vibrator/ignore_store", "0" },
|
||||||
|
{ "/sys/class/leds/vibrator/duration", "30" },
|
||||||
|
{ "/sys/class/leds/vibrator/vmax", "0x1f" },
|
||||||
|
{ "/sys/class/leds/vibrator/gain", "0x80" },
|
||||||
|
{ "/sys/class/leds/vibrator/seq", "0x00 0x03" },
|
||||||
|
{ "/sys/class/leds/vibrator/loop", "0x00 0x00" },
|
||||||
|
{ "/sys/class/leds/vibrator/brightness", "1" },
|
||||||
|
{ "SLEEP", "150" },
|
||||||
|
{ "/sys/class/leds/vibrator/ignore_store", "0" },
|
||||||
|
{ "/sys/class/leds/vibrator/duration", "30" },
|
||||||
|
{ "/sys/class/leds/vibrator/vmax", "0x1f" },
|
||||||
|
{ "/sys/class/leds/vibrator/gain", "0x80" },
|
||||||
|
{ "/sys/class/leds/vibrator/seq", "0x00 0x03" },
|
||||||
|
{ "/sys/class/leds/vibrator/loop", "0x00 0x00" },
|
||||||
|
{ "/sys/class/leds/vibrator/brightness", "1" },
|
||||||
|
}},
|
||||||
|
{ Effect::TICK, {
|
||||||
|
{ "/sys/class/leds/vibrator/ignore_store", "0" },
|
||||||
|
{ "/sys/class/leds/vibrator/duration", "30" },
|
||||||
|
{ "/sys/class/leds/vibrator/vmax", "0x1f" },
|
||||||
|
{ "/sys/class/leds/vibrator/gain", "0x80" },
|
||||||
|
{ "/sys/class/leds/vibrator/seq", "0x00 0x03" },
|
||||||
|
{ "/sys/class/leds/vibrator/loop", "0x00 0x00" },
|
||||||
|
{ "/sys/class/leds/vibrator/brightness", "1" },
|
||||||
|
}},
|
||||||
|
{ Effect::HEAVY_CLICK, {
|
||||||
|
{ "/sys/class/leds/vibrator/ignore_store", "0" },
|
||||||
|
{ "/sys/class/leds/vibrator/duration", "10" },
|
||||||
|
{ "/sys/class/leds/vibrator/vmax", "0x1f" },
|
||||||
|
{ "/sys/class/leds/vibrator/gain", "0x80" },
|
||||||
|
{ "/sys/class/leds/vibrator/seq", "0x00 0x03" },
|
||||||
|
{ "/sys/class/leds/vibrator/loop", "0x00 0x00" },
|
||||||
|
{ "/sys/class/leds/vibrator/brightness", "1" },
|
||||||
|
}}
|
||||||
|
};
|
||||||
|
|
||||||
InputFFDevice::InputFFDevice()
|
InputFFDevice::InputFFDevice()
|
||||||
{
|
{
|
||||||
DIR *dp;
|
DIR *dp;
|
||||||
|
@ -439,21 +487,41 @@ ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es, const std
|
||||||
long playLengthMs;
|
long playLengthMs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ledVib.mDetected)
|
|
||||||
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
|
||||||
|
|
||||||
ALOGD("Vibrator perform effect %d", effect);
|
ALOGD("Vibrator perform effect %d", effect);
|
||||||
|
|
||||||
if (effect < Effect::CLICK ||
|
if (ledVib.mDetected) {
|
||||||
effect > Effect::HEAVY_CLICK)
|
if (const auto it = LED_EFFECTS.find(effect); it != LED_EFFECTS.end()) {
|
||||||
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
for (const auto &[path, value] : it->second) {
|
||||||
|
if (path == "SLEEP") {
|
||||||
|
usleep(atoi(value.c_str()) * 1000);
|
||||||
|
} else {
|
||||||
|
ledVib.write_value(path.c_str(), value.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (es != EffectStrength::LIGHT && es != EffectStrength::MEDIUM && es != EffectStrength::STRONG)
|
// Restore gain from persist prop
|
||||||
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
char gain[PROPERTY_VALUE_MAX]{};
|
||||||
|
property_get("persist.vendor.vib.gain", gain, "0x55");
|
||||||
|
ledVib.write_value("/sys/class/leds/vibrator/gain", gain);
|
||||||
|
|
||||||
ret = ff.playEffect((static_cast<int>(effect)), es, &playLengthMs);
|
// Return magic value for play length so that we won't end up calling on() / off()
|
||||||
if (ret != 0)
|
playLengthMs = 150;
|
||||||
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
|
} else {
|
||||||
|
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (effect < Effect::CLICK ||
|
||||||
|
effect > Effect::HEAVY_CLICK)
|
||||||
|
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
||||||
|
|
||||||
|
if (es != EffectStrength::LIGHT && es != EffectStrength::MEDIUM &&
|
||||||
|
es != EffectStrength::STRONG)
|
||||||
|
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
|
||||||
|
|
||||||
|
ret = ff.playEffect((static_cast<int>(effect)), es, &playLengthMs);
|
||||||
|
if (ret != 0)
|
||||||
|
return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_SERVICE_SPECIFIC));
|
||||||
|
}
|
||||||
|
|
||||||
if (callback != nullptr) {
|
if (callback != nullptr) {
|
||||||
std::thread([=] {
|
std::thread([=] {
|
||||||
|
@ -469,11 +537,12 @@ ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength es, const std
|
||||||
}
|
}
|
||||||
|
|
||||||
ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
|
ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_return) {
|
||||||
if (ledVib.mDetected)
|
if (ledVib.mDetected) {
|
||||||
return ndk::ScopedAStatus::ok();
|
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::HEAVY_CLICK};
|
||||||
|
} else {
|
||||||
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD,
|
*_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD,
|
||||||
Effect::POP, Effect::HEAVY_CLICK};
|
Effect::POP, Effect::HEAVY_CLICK};
|
||||||
|
}
|
||||||
|
|
||||||
return ndk::ScopedAStatus::ok();
|
return ndk::ScopedAStatus::ok();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ public:
|
||||||
int on(int32_t timeoutMs);
|
int on(int32_t timeoutMs);
|
||||||
int off();
|
int off();
|
||||||
bool mDetected;
|
bool mDetected;
|
||||||
private:
|
|
||||||
int write_value(const char *file, const char *value);
|
int write_value(const char *file, const char *value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue