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 ATRACE_TAG (ATRACE_TAG_VIBRATOR | ATRACE_TAG_HAL)
18 #define LOG_TAG "android.hardware.vibrator@1.3-service.coral"
19 
20 #include "Vibrator.h"
21 
22 #include <hardware/hardware.h>
23 #include <hardware/vibrator.h>
24 #include <log/log.h>
25 #include <utils/Trace.h>
26 
27 #include <cinttypes>
28 #include <cmath>
29 #include <fstream>
30 #include <iostream>
31 
32 #ifndef ARRAY_SIZE
33 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
34 #endif
35 
36 namespace android {
37 namespace hardware {
38 namespace vibrator {
39 namespace V1_3 {
40 namespace implementation {
41 
42 using Status = ::android::hardware::vibrator::V1_0::Status;
43 using EffectStrength = ::android::hardware::vibrator::V1_0::EffectStrength;
44 
45 static constexpr uint32_t BASE_CONTINUOUS_EFFECT_OFFSET = 32768;
46 
47 static constexpr uint32_t WAVEFORM_SIMPLE_EFFECT_INDEX = 2;
48 
49 static constexpr uint32_t WAVEFORM_TEXTURE_TICK_EFFECT_LEVEL = 0;
50 
51 static constexpr uint32_t WAVEFORM_TICK_EFFECT_LEVEL = 1;
52 
53 static constexpr uint32_t WAVEFORM_CLICK_EFFECT_LEVEL = 2;
54 
55 static constexpr uint32_t WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL = 3;
56 
57 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
58 
59 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0;
60 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
61 static constexpr uint32_t WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3 + BASE_CONTINUOUS_EFFECT_OFFSET;
62 
63 static constexpr uint32_t WAVEFORM_TRIGGER_QUEUE_INDEX = 65534;
64 
65 static constexpr uint32_t VOLTAGE_GLOBAL_SCALE_LEVEL = 5;
66 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
67 
68 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
69 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1; // ALERT Irq Handling
70 
71 static constexpr float AMP_ATTENUATE_STEP_SIZE = 0.125f;
72 static constexpr float EFFECT_FREQUENCY_KHZ = 48.0f;
73 
amplitudeToScale(uint8_t amplitude,uint8_t maximum)74 static uint8_t amplitudeToScale(uint8_t amplitude, uint8_t maximum) {
75     return std::round((-20 * std::log10(amplitude / static_cast<float>(maximum))) /
76                       (AMP_ATTENUATE_STEP_SIZE));
77 }
78 
Vibrator(std::unique_ptr<HwApi> hwapi,std::unique_ptr<HwCal> hwcal)79 Vibrator::Vibrator(std::unique_ptr<HwApi> hwapi, std::unique_ptr<HwCal> hwcal)
80     : mHwApi(std::move(hwapi)), mHwCal(std::move(hwcal)) {
81     uint32_t caldata;
82     uint32_t effectDuration;
83 
84     if (!mHwApi->setState(true)) {
85         ALOGE("Failed to set state (%d): %s", errno, strerror(errno));
86     }
87 
88     if (mHwCal->getF0(&caldata)) {
89         mHwApi->setF0(caldata);
90     }
91     if (mHwCal->getRedc(&caldata)) {
92         mHwApi->setRedc(caldata);
93     }
94     if (mHwCal->getQ(&caldata)) {
95         mHwApi->setQ(caldata);
96     }
97     mHwCal->getVolLevels(&mVolLevels);
98 
99     mHwApi->setEffectIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
100     mHwApi->getEffectDuration(&effectDuration);
101 
102     mSimpleEffectDuration = std::ceil(effectDuration / EFFECT_FREQUENCY_KHZ);
103 
104     const uint32_t scaleFall =
105         amplitudeToScale(mVolLevels[WAVEFORM_CLICK_EFFECT_LEVEL], VOLTAGE_SCALE_MAX);
106     const uint32_t scaleRise =
107         amplitudeToScale(mVolLevels[WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL], VOLTAGE_SCALE_MAX);
108 
109     mHwApi->setGpioFallIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
110     mHwApi->setGpioFallScale(scaleFall);
111     mHwApi->setGpioRiseIndex(WAVEFORM_SIMPLE_EFFECT_INDEX);
112     mHwApi->setGpioRiseScale(scaleRise);
113 }
114 
on(uint32_t timeoutMs,uint32_t effectIndex)115 Return<Status> Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex) {
116     mHwApi->setEffectIndex(effectIndex);
117     mHwApi->setDuration(timeoutMs);
118     mHwApi->setActivate(1);
119 
120     return Status::OK;
121 }
122 
123 // Methods from ::android::hardware::vibrator::V1_1::IVibrator follow.
on(uint32_t timeoutMs)124 Return<Status> Vibrator::on(uint32_t timeoutMs) {
125     ATRACE_NAME("Vibrator::on");
126     const uint32_t index = timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS
127                                ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
128                                : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
129     if (MAX_COLD_START_LATENCY_MS <= UINT32_MAX - timeoutMs) {
130         timeoutMs += MAX_COLD_START_LATENCY_MS;
131     }
132     setGlobalAmplitude(true);
133     return on(timeoutMs, index);
134 }
135 
off()136 Return<Status> Vibrator::off() {
137     ATRACE_NAME("Vibrator::off");
138     setGlobalAmplitude(false);
139     if (!mHwApi->setActivate(0)) {
140         ALOGE("Failed to turn vibrator off (%d): %s", errno, strerror(errno));
141         return Status::UNKNOWN_ERROR;
142     }
143     return Status::OK;
144 }
145 
supportsAmplitudeControl()146 Return<bool> Vibrator::supportsAmplitudeControl() {
147     ATRACE_NAME("Vibrator::supportsAmplitudeControl");
148     return !isUnderExternalControl() && mHwApi->hasEffectScale();
149 }
150 
setAmplitude(uint8_t amplitude)151 Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
152     ATRACE_NAME("Vibrator::setAmplitude");
153     if (!amplitude) {
154         return Status::BAD_VALUE;
155     }
156 
157     if (!isUnderExternalControl()) {
158         return setEffectAmplitude(amplitude, UINT8_MAX);
159     } else {
160         return Status::UNSUPPORTED_OPERATION;
161     }
162 }
163 
setEffectAmplitude(uint8_t amplitude,uint8_t maximum)164 Return<Status> Vibrator::setEffectAmplitude(uint8_t amplitude, uint8_t maximum) {
165     int32_t scale = amplitudeToScale(amplitude, maximum);
166 
167     if (!mHwApi->setEffectScale(scale)) {
168         ALOGE("Failed to set effect amplitude (%d): %s", errno, strerror(errno));
169         return Status::UNKNOWN_ERROR;
170     }
171 
172     return Status::OK;
173 }
174 
setGlobalAmplitude(bool set)175 Return<Status> Vibrator::setGlobalAmplitude(bool set) {
176     uint8_t amplitude = set ? mVolLevels[VOLTAGE_GLOBAL_SCALE_LEVEL] : VOLTAGE_SCALE_MAX;
177     int32_t scale = amplitudeToScale(amplitude, VOLTAGE_SCALE_MAX);
178 
179     if (!mHwApi->setGlobalScale(scale)) {
180         ALOGE("Failed to set global amplitude (%d): %s", errno, strerror(errno));
181         return Status::UNKNOWN_ERROR;
182     }
183 
184     return Status::OK;
185 }
186 
187 // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
188 
supportsExternalControl()189 Return<bool> Vibrator::supportsExternalControl() {
190     ATRACE_NAME("Vibrator::supportsExternalControl");
191     return (mHwApi->hasAspEnable() ? true : false);
192 }
193 
setExternalControl(bool enabled)194 Return<Status> Vibrator::setExternalControl(bool enabled) {
195     ATRACE_NAME("Vibrator::setExternalControl");
196     setGlobalAmplitude(enabled);
197 
198     if (!mHwApi->setAspEnable(enabled)) {
199         ALOGE("Failed to set external control (%d): %s", errno, strerror(errno));
200         return Status::UNKNOWN_ERROR;
201     }
202     return Status::OK;
203 }
204 
isUnderExternalControl()205 bool Vibrator::isUnderExternalControl() {
206     bool isAspEnabled;
207     mHwApi->getAspEnable(&isAspEnabled);
208     return isAspEnabled;
209 }
210 
211 // Methods from ::android.hidl.base::V1_0::IBase follow.
212 
debug(const hidl_handle & handle,const hidl_vec<hidl_string> &)213 Return<void> Vibrator::debug(const hidl_handle &handle,
214                              const hidl_vec<hidl_string> & /* options */) {
215     if (handle == nullptr || handle->numFds < 1 || handle->data[0] < 0) {
216         ALOGE("Called debug() with invalid fd.");
217         return Void();
218     }
219 
220     int fd = handle->data[0];
221 
222     dprintf(fd, "HIDL:\n");
223 
224     dprintf(fd, "  Voltage Levels:");
225     for (auto v : mVolLevels) {
226         dprintf(fd, " %" PRIu32, v);
227     }
228     dprintf(fd, "\n");
229 
230     dprintf(fd, "  Effect Duration: %" PRIu32 "\n", mSimpleEffectDuration);
231 
232     dprintf(fd, "\n");
233 
234     mHwApi->debug(fd);
235 
236     dprintf(fd, "\n");
237 
238     mHwCal->debug(fd);
239 
240     fsync(fd);
241     return Void();
242 }
243 
244 template <typename T>
performWrapper(T effect,EffectStrength strength,perform_cb _hidl_cb)245 Return<void> Vibrator::performWrapper(T effect, EffectStrength strength, perform_cb _hidl_cb) {
246     ATRACE_NAME("Vibrator::performWrapper");
247     auto validRange = hidl_enum_range<T>();
248     if (effect < *validRange.begin() || effect > *std::prev(validRange.end())) {
249         _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
250         return Void();
251     }
252     return performEffect(static_cast<Effect>(effect), strength, _hidl_cb);
253 }
254 
perform(V1_0::Effect effect,EffectStrength strength,perform_cb _hidl_cb)255 Return<void> Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
256     return performWrapper(effect, strength, _hidl_cb);
257 }
258 
perform_1_1(V1_1::Effect_1_1 effect,EffectStrength strength,perform_cb _hidl_cb)259 Return<void> Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
260                                    perform_cb _hidl_cb) {
261     return performWrapper(effect, strength, _hidl_cb);
262 }
263 
perform_1_2(V1_2::Effect effect,EffectStrength strength,perform_cb _hidl_cb)264 Return<void> Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength,
265                                    perform_cb _hidl_cb) {
266     return performWrapper(effect, strength, _hidl_cb);
267 }
268 
perform_1_3(Effect effect,EffectStrength strength,perform_cb _hidl_cb)269 Return<void> Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
270     return performWrapper(effect, strength, _hidl_cb);
271 }
272 
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,uint32_t * outVolLevel)273 Return<Status> Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
274                                           uint32_t *outTimeMs, uint32_t *outVolLevel) {
275     uint32_t timeMs;
276     uint32_t volLevel;
277     uint32_t volIndex;
278     int8_t volOffset;
279 
280     switch (strength) {
281         case EffectStrength::LIGHT:
282             volOffset = -1;
283             break;
284         case EffectStrength::MEDIUM:
285             volOffset = 0;
286             break;
287         case EffectStrength::STRONG:
288             volOffset = 1;
289             break;
290         default:
291             return Status::UNSUPPORTED_OPERATION;
292     }
293 
294     switch (effect) {
295         case Effect::TEXTURE_TICK:
296             volIndex = WAVEFORM_TEXTURE_TICK_EFFECT_LEVEL;
297             volOffset = 0;
298             break;
299         case Effect::TICK:
300             volIndex = WAVEFORM_TICK_EFFECT_LEVEL;
301             volOffset = 0;
302             break;
303         case Effect::CLICK:
304             volIndex = WAVEFORM_CLICK_EFFECT_LEVEL;
305             break;
306         case Effect::HEAVY_CLICK:
307             volIndex = WAVEFORM_HEAVY_CLICK_EFFECT_LEVEL;
308             break;
309         default:
310             return Status::UNSUPPORTED_OPERATION;
311     }
312 
313     volLevel = mVolLevels[volIndex + volOffset];
314     timeMs = mSimpleEffectDuration + MAX_COLD_START_LATENCY_MS;
315 
316     *outTimeMs = timeMs;
317     *outVolLevel = volLevel;
318 
319     return Status::OK;
320 }
321 
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,uint32_t *,std::string * outEffectQueue)322 Return<Status> Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
323                                             uint32_t *outTimeMs, uint32_t * /*outVolLevel*/,
324                                             std::string *outEffectQueue) {
325     Status status;
326     uint32_t timeMs;
327     std::ostringstream effectBuilder;
328     uint32_t thisTimeMs;
329     uint32_t thisVolLevel;
330 
331     switch (effect) {
332         case Effect::DOUBLE_CLICK:
333             timeMs = 0;
334 
335             status = getSimpleDetails(Effect::CLICK, strength, &thisTimeMs, &thisVolLevel);
336             if (status != Status::OK) {
337                 return status;
338             }
339             effectBuilder << WAVEFORM_SIMPLE_EFFECT_INDEX << "." << thisVolLevel;
340             timeMs += thisTimeMs;
341 
342             effectBuilder << ",";
343 
344             effectBuilder << WAVEFORM_DOUBLE_CLICK_SILENCE_MS;
345             timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
346 
347             effectBuilder << ",";
348 
349             status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisTimeMs, &thisVolLevel);
350             if (status != Status::OK) {
351                 return status;
352             }
353             effectBuilder << WAVEFORM_SIMPLE_EFFECT_INDEX << "." << thisVolLevel;
354             timeMs += thisTimeMs;
355 
356             break;
357         default:
358             return Status::UNSUPPORTED_OPERATION;
359     }
360 
361     *outTimeMs = timeMs;
362     *outEffectQueue = effectBuilder.str();
363 
364     return Status::OK;
365 }
366 
setEffectQueue(const std::string & effectQueue)367 Return<Status> Vibrator::setEffectQueue(const std::string &effectQueue) {
368     if (!mHwApi->setEffectQueue(effectQueue)) {
369         ALOGE("Failed to write \"%s\" to effect queue (%d): %s", effectQueue.c_str(), errno,
370               strerror(errno));
371         return Status::UNKNOWN_ERROR;
372     }
373 
374     return Status::OK;
375 }
376 
performEffect(Effect effect,EffectStrength strength,perform_cb _hidl_cb)377 Return<void> Vibrator::performEffect(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
378     Status status = Status::OK;
379     uint32_t timeMs = 0;
380     uint32_t effectIndex;
381     uint32_t volLevel;
382     std::string effectQueue;
383 
384     switch (effect) {
385         case Effect::TEXTURE_TICK:
386             // fall-through
387         case Effect::TICK:
388             // fall-through
389         case Effect::CLICK:
390             // fall-through
391         case Effect::HEAVY_CLICK:
392             status = getSimpleDetails(effect, strength, &timeMs, &volLevel);
393             break;
394         case Effect::DOUBLE_CLICK:
395             status = getCompoundDetails(effect, strength, &timeMs, &volLevel, &effectQueue);
396             break;
397         default:
398             status = Status::UNSUPPORTED_OPERATION;
399             break;
400     }
401     if (status != Status::OK) {
402         goto exit;
403     }
404 
405     if (!effectQueue.empty()) {
406         status = setEffectQueue(effectQueue);
407         if (status != Status::OK) {
408             goto exit;
409         }
410         setEffectAmplitude(VOLTAGE_SCALE_MAX, VOLTAGE_SCALE_MAX);
411         effectIndex = WAVEFORM_TRIGGER_QUEUE_INDEX;
412     } else {
413         setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
414         effectIndex = WAVEFORM_SIMPLE_EFFECT_INDEX;
415     }
416 
417     on(timeMs, effectIndex);
418 
419 exit:
420 
421     _hidl_cb(status, timeMs);
422 
423     return Void();
424 }
425 
426 }  // namespace implementation
427 }  // namespace V1_3
428 }  // namespace vibrator
429 }  // namespace hardware
430 }  // namespace android
431