• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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