1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "VibratorService"
18
19 #include <log/log.h>
20
21 #include <cutils/properties.h>
22 #include <hardware/hardware.h>
23 #include <hardware/vibrator.h>
24
25 #include "Vibrator.h"
26
27 #include <cinttypes>
28 #include <cmath>
29 #include <fstream>
30 #include <iostream>
31
32 namespace android {
33 namespace hardware {
34 namespace vibrator {
35 namespace V1_2 {
36 namespace implementation {
37
38 static constexpr int8_t MAX_RTP_INPUT = 127;
39 static constexpr int8_t MIN_RTP_INPUT = 0;
40
41 static constexpr char RTP_MODE[] = "rtp";
42 static constexpr char WAVEFORM_MODE[] = "waveform";
43
44 static constexpr uint32_t LOOP_MODE_OPEN = 1;
45 static constexpr uint32_t SINE_WAVE = 1;
46 static constexpr uint32_t SQUARE_WAVE = 0;
47
48 // Default max voltage 2.15V
49 static constexpr uint32_t VOLTAGE_MAX = 107;
50
51 // Use effect #1 in the waveform library for CLICK effect
52 static constexpr char WAVEFORM_CLICK_EFFECT_SEQ[] = "1 0";
53 static constexpr int32_t WAVEFORM_CLICK_EFFECT_MS = 6;
54
55 // Use effect #2 in the waveform library for TICK effect
56 static constexpr char WAVEFORM_TICK_EFFECT_SEQ[] = "2 0";
57 static constexpr int32_t WAVEFORM_TICK_EFFECT_MS = 2;
58
59 // Use effect #3 in the waveform library for DOUBLE_CLICK effect
60 static constexpr char WAVEFORM_DOUBLE_CLICK_EFFECT_SEQ[] = "3 0";
61 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_EFFECT_MS = 182;
62
63 // Use effect #4 in the waveform library for HEAVY_CLICK effect
64 static constexpr char WAVEFORM_HEAVY_CLICK_EFFECT_SEQ[] = "4 0";
65 static constexpr uint32_t WAVEFORM_HEAVY_CLICK_EFFECT_MS = 8;
66
67 using Status = ::android::hardware::vibrator::V1_0::Status;
68 using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
69
Vibrator(HwApi && hwapi,std::uint32_t short_lra_period,std::uint32_t long_lra_period)70 Vibrator::Vibrator(HwApi &&hwapi, std::uint32_t short_lra_period, std::uint32_t long_lra_period)
71 : mHwApi(std::move(hwapi)), mShortLraPeriod(short_lra_period), mLongLraPeriod(long_lra_period) {
72 mClickDuration = property_get_int32("ro.vibrator.hal.click.duration", WAVEFORM_CLICK_EFFECT_MS);
73 mTickDuration = property_get_int32("ro.vibrator.hal.tick.duration", WAVEFORM_TICK_EFFECT_MS);
74 mHeavyClickDuration =
75 property_get_int32("ro.vibrator.hal.heavyclick.duration", WAVEFORM_HEAVY_CLICK_EFFECT_MS);
76 mShortVoltageMax = property_get_int32("ro.vibrator.hal.short.voltage", VOLTAGE_MAX);
77 mLongVoltageMax = property_get_int32("ro.vibrator.hal.long.voltage", VOLTAGE_MAX);
78
79 // This enables effect #1 from the waveform library to be triggered by SLPI
80 // while the AP is in suspend mode
81 mHwApi.lpTriggerEffect << 1 << std::endl;
82 if (!mHwApi.lpTriggerEffect) {
83 ALOGW("Failed to set LP trigger mode (%d): %s", errno, strerror(errno));
84 }
85 }
86
on(uint32_t timeoutMs,bool isWaveform)87 Return<Status> Vibrator::on(uint32_t timeoutMs, bool isWaveform) {
88 // Bonito / Sargo only support open-loop mode
89 mHwApi.ctrlLoop << LOOP_MODE_OPEN << std::endl;
90 mHwApi.duration << timeoutMs << std::endl;
91 if (!mHwApi.duration) {
92 ALOGE("Failed to set duration (%d): %s", errno, strerror(errno));
93 return Status::UNKNOWN_ERROR;
94 }
95
96 if (isWaveform) {
97 mHwApi.mode << WAVEFORM_MODE << std::endl;
98 mHwApi.lraWaveShape << SINE_WAVE << std::endl;
99 mHwApi.odClamp << mShortVoltageMax << std::endl;
100 mHwApi.olLraPeriod << mShortLraPeriod << std::endl;
101 } else {
102 mHwApi.mode << RTP_MODE << std::endl;
103 mHwApi.lraWaveShape << SQUARE_WAVE << std::endl;
104 mHwApi.odClamp << mLongVoltageMax << std::endl;
105 mHwApi.olLraPeriod << mLongLraPeriod << std::endl;
106 }
107
108 mHwApi.activate << 1 << std::endl;
109 if (!mHwApi.activate) {
110 ALOGE("Failed to activate (%d): %s", errno, strerror(errno));
111 return Status::UNKNOWN_ERROR;
112 }
113
114 return Status::OK;
115 }
116
117 // Methods from ::android::hardware::vibrator::V1_2::IVibrator follow.
on(uint32_t timeoutMs)118 Return<Status> Vibrator::on(uint32_t timeoutMs) {
119 return on(timeoutMs, false /* isWaveform */);
120 }
121
off()122 Return<Status> Vibrator::off() {
123 mHwApi.activate << 0 << std::endl;
124 if (!mHwApi.activate) {
125 ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
126 return Status::UNKNOWN_ERROR;
127 }
128 return Status::OK;
129 }
130
supportsAmplitudeControl()131 Return<bool> Vibrator::supportsAmplitudeControl() {
132 return (mHwApi.rtpInput ? true : false);
133 }
134
setAmplitude(uint8_t amplitude)135 Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
136 if (amplitude == 0) {
137 return Status::BAD_VALUE;
138 }
139
140 int32_t rtp_input =
141 std::round((amplitude - 1) / 254.0 * (MAX_RTP_INPUT - MIN_RTP_INPUT) + MIN_RTP_INPUT);
142
143 mHwApi.rtpInput << rtp_input << std::endl;
144 if (!mHwApi.rtpInput) {
145 ALOGE("Failed to set amplitude (%d): %s", errno, strerror(errno));
146 return Status::UNKNOWN_ERROR;
147 }
148
149 return Status::OK;
150 }
151
convertEffectStrength(EffectStrength strength)152 static uint8_t convertEffectStrength(EffectStrength strength) {
153 uint8_t scale;
154
155 switch (strength) {
156 case EffectStrength::LIGHT:
157 scale = 2; // 50%
158 break;
159 case EffectStrength::MEDIUM:
160 case EffectStrength::STRONG:
161 scale = 0; // 100%
162 break;
163 }
164
165 return scale;
166 }
167
perform(V1_0::Effect effect,EffectStrength strength,perform_cb _hidl_cb)168 Return<void> Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
169 return performWrapper(effect, strength, _hidl_cb);
170 }
171
perform_1_1(V1_1::Effect_1_1 effect,EffectStrength strength,perform_cb _hidl_cb)172 Return<void> Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
173 perform_cb _hidl_cb) {
174 return performWrapper(effect, strength, _hidl_cb);
175 }
176
perform_1_2(Effect effect,EffectStrength strength,perform_cb _hidl_cb)177 Return<void> Vibrator::perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
178 return performWrapper(effect, strength, _hidl_cb);
179 }
180
181 template <typename T>
performWrapper(T effect,EffectStrength strength,perform_cb _hidl_cb)182 Return<void> Vibrator::performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb) {
183 auto validEffectRange = hidl_enum_range<T>();
184 if (effect < *validEffectRange.begin() || effect > *std::prev(validEffectRange.end())) {
185 _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
186 return Void();
187 }
188 auto validStrengthRange = hidl_enum_range<EffectStrength>();
189 if (strength < *validStrengthRange.begin() || strength > *std::prev(validStrengthRange.end())) {
190 _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
191 return Void();
192 }
193 return performEffect(static_cast<Effect>(effect), strength, _hidl_cb);
194 }
195
performEffect(Effect effect,EffectStrength strength,perform_cb _hidl_cb)196 Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
197 Status status = Status::OK;
198 uint32_t timeMS;
199
200 switch (effect) {
201 case Effect::CLICK:
202 mHwApi.sequencer << WAVEFORM_CLICK_EFFECT_SEQ << std::endl;
203 timeMS = mClickDuration;
204 break;
205 case Effect::DOUBLE_CLICK:
206 mHwApi.sequencer << WAVEFORM_DOUBLE_CLICK_EFFECT_SEQ << std::endl;
207 timeMS = WAVEFORM_DOUBLE_CLICK_EFFECT_MS;
208 break;
209 case Effect::TICK:
210 mHwApi.sequencer << WAVEFORM_TICK_EFFECT_SEQ << std::endl;
211 timeMS = mTickDuration;
212 break;
213 case Effect::HEAVY_CLICK:
214 mHwApi.sequencer << WAVEFORM_HEAVY_CLICK_EFFECT_SEQ << std::endl;
215 timeMS = mHeavyClickDuration;
216 break;
217 default:
218 _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
219 return Void();
220 }
221 mHwApi.scale << convertEffectStrength(strength) << std::endl;
222 on(timeMS, true /* isWaveform */);
223 _hidl_cb(status, timeMS);
224 return Void();
225 }
226
227 } // namespace implementation
228 } // namespace V1_2
229 } // namespace vibrator
230 } // namespace hardware
231 } // namespace android
232