1 /*
2 * Copyright (C) 2021 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 #include "Vibrator.h"
18
19 #include <glob.h>
20 #include <hardware/hardware.h>
21 #include <hardware/vibrator.h>
22 #include <log/log.h>
23 #include <stdio.h>
24 #include <utils/Trace.h>
25
26 #include <cinttypes>
27 #include <cmath>
28 #include <fstream>
29 #include <iostream>
30 #include <memory>
31 #include <optional>
32 #include <sstream>
33
34 #ifndef ARRAY_SIZE
35 #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
36 #endif
37
38 #ifdef LOG_TAG
39 #undef LOG_TAG
40 #define LOG_TAG std::getenv("HAPTIC_NAME")
41 #endif
42
43 namespace aidl {
44 namespace android {
45 namespace hardware {
46 namespace vibrator {
47 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_COMP = 2044; // (COMPOSE_SIZE_MAX + 1) * 8 + 4
48 static constexpr uint16_t FF_CUSTOM_DATA_LEN_MAX_PWLE = 2302;
49
50 static constexpr uint32_t WAVEFORM_DOUBLE_CLICK_SILENCE_MS = 100;
51
52 static constexpr uint32_t WAVEFORM_LONG_VIBRATION_THRESHOLD_MS = 50;
53
54 static constexpr uint8_t VOLTAGE_SCALE_MAX = 100;
55
56 static constexpr int8_t MAX_COLD_START_LATENCY_MS = 6; // I2C Transaction + DSP Return-From-Standby
57 static constexpr int8_t MAX_PAUSE_TIMING_ERROR_MS = 1; // ALERT Irq Handling
58 static constexpr uint32_t MAX_TIME_MS = UINT16_MAX;
59
60 static constexpr auto ASYNC_COMPLETION_TIMEOUT = std::chrono::milliseconds(100);
61 static constexpr auto POLLING_TIMEOUT = 20;
62 static constexpr int32_t COMPOSE_DELAY_MAX_MS = 10000;
63
64 /* nsections is 8 bits. Need to preserve 1 section for the first delay before the first effect. */
65 static constexpr int32_t COMPOSE_SIZE_MAX = 254;
66 static constexpr int32_t COMPOSE_PWLE_SIZE_MAX_DEFAULT = 127;
67
68 // Measured resonant frequency, f0_measured, is represented by Q10.14 fixed
69 // point format on cs40l26 devices. The expression to calculate f0 is:
70 // f0 = f0_measured / 2^Q14_BIT_SHIFT
71 // See the LRA Calibration Support documentation for more details.
72 static constexpr int32_t Q14_BIT_SHIFT = 14;
73
74 // Measured Q factor, q_measured, is represented by Q8.16 fixed
75 // point format on cs40l26 devices. The expression to calculate q is:
76 // q = q_measured / 2^Q16_BIT_SHIFT
77 // See the LRA Calibration Support documentation for more details.
78 static constexpr int32_t Q16_BIT_SHIFT = 16;
79
80 static constexpr int32_t COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS = 16383;
81
82 static constexpr uint32_t WT_LEN_CALCD = 0x00800000;
83 static constexpr uint8_t PWLE_CHIRP_BIT = 0x8; // Dynamic/static frequency and voltage
84 static constexpr uint8_t PWLE_BRAKE_BIT = 0x4;
85 static constexpr uint8_t PWLE_AMP_REG_BIT = 0x2;
86
87 static constexpr float PWLE_LEVEL_MIN = 0.0;
88 static constexpr float PWLE_LEVEL_MAX = 1.0;
89 static constexpr float CS40L26_PWLE_LEVEL_MIN = -1.0;
90 static constexpr float CS40L26_PWLE_LEVEL_MAX = 0.9995118;
91 static constexpr float PWLE_FREQUENCY_RESOLUTION_HZ = 1.00;
92 static constexpr float PWLE_FREQUENCY_MIN_HZ = 1.00;
93 static constexpr float PWLE_FREQUENCY_MAX_HZ = 1000.00;
94 static constexpr float PWLE_BW_MAP_SIZE =
95 1 + ((PWLE_FREQUENCY_MAX_HZ - PWLE_FREQUENCY_MIN_HZ) / PWLE_FREQUENCY_RESOLUTION_HZ);
96
97 /*
98 * [15] Edge, 0:Falling, 1:Rising
99 * [14:12] GPI_NUM, 1:GPI1 (with CS40L26A, 1 is the only supported GPI)
100 * [8] BANK, 0:RAM, 1:R0M
101 * [7] USE_BUZZGEN, 0:Not buzzgen, 1:buzzgen
102 * [6:0] WAVEFORM_INDEX
103 * 0x9100 = 1001 0001 0000 0000: Rising + GPI1 + RAM + Not buzzgen
104 */
105 static constexpr uint16_t GPIO_TRIGGER_CONFIG = 0x9100;
106
amplitudeToScale(float amplitude,float maximum)107 static uint16_t amplitudeToScale(float amplitude, float maximum) {
108 float ratio = 100; /* Unit: % */
109 if (maximum != 0)
110 ratio = amplitude / maximum * 100;
111
112 if (maximum == 0 || ratio > 100)
113 ratio = 100;
114
115 return std::round(ratio);
116 }
117
118 enum WaveformBankID : uint8_t {
119 RAM_WVFRM_BANK,
120 ROM_WVFRM_BANK,
121 OWT_WVFRM_BANK,
122 };
123
124 enum WaveformIndex : uint16_t {
125 /* Physical waveform */
126 WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
127 WAVEFORM_RESERVED_INDEX_1 = 1,
128 WAVEFORM_CLICK_INDEX = 2,
129 WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
130 WAVEFORM_THUD_INDEX = 4,
131 WAVEFORM_SPIN_INDEX = 5,
132 WAVEFORM_QUICK_RISE_INDEX = 6,
133 WAVEFORM_SLOW_RISE_INDEX = 7,
134 WAVEFORM_QUICK_FALL_INDEX = 8,
135 WAVEFORM_LIGHT_TICK_INDEX = 9,
136 WAVEFORM_LOW_TICK_INDEX = 10,
137 WAVEFORM_RESERVED_MFG_1,
138 WAVEFORM_RESERVED_MFG_2,
139 WAVEFORM_RESERVED_MFG_3,
140 WAVEFORM_MAX_PHYSICAL_INDEX,
141 /* OWT waveform */
142 WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
143 WAVEFORM_PWLE,
144 /*
145 * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
146 * #define FF_GAIN 0x60 // 96 in decimal
147 * #define FF_MAX_EFFECTS FF_GAIN
148 */
149 WAVEFORM_MAX_INDEX,
150 };
151
152 std::vector<CompositePrimitive> defaultSupportedPrimitives = {
153 ndk::enum_range<CompositePrimitive>().begin(), ndk::enum_range<CompositePrimitive>().end()};
154
155 enum vibe_state {
156 VIBE_STATE_STOPPED = 0,
157 VIBE_STATE_HAPTIC,
158 VIBE_STATE_ASP,
159 };
160
161 class DspMemChunk {
162 private:
163 std::unique_ptr<uint8_t[]> head;
164 size_t bytes = 0;
165 uint8_t waveformType;
166 uint8_t *_current;
167 const uint8_t *_max;
168 uint32_t _cache = 0;
169 int _cachebits = 0;
170
isEnd() const171 bool isEnd() const { return _current == _max; }
min(int x,int y)172 int min(int x, int y) { return x < y ? x : y; }
173
write(int nbits,uint32_t val)174 int write(int nbits, uint32_t val) {
175 int nwrite, i;
176
177 nwrite = min(24 - _cachebits, nbits);
178 _cache <<= nwrite;
179 _cache |= val >> (nbits - nwrite);
180 _cachebits += nwrite;
181 nbits -= nwrite;
182
183 if (_cachebits == 24) {
184 if (isEnd())
185 return -ENOSPC;
186
187 _cache &= 0xFFFFFF;
188 for (i = 0; i < sizeof(_cache); i++, _cache <<= 8)
189 *_current++ = (_cache & 0xFF000000) >> 24;
190
191 bytes += sizeof(_cache);
192 _cachebits = 0;
193 }
194
195 if (nbits)
196 return write(nbits, val);
197
198 return 0;
199 }
200
fToU16(float input,uint16_t * output,float scale,float min,float max)201 int fToU16(float input, uint16_t *output, float scale, float min, float max) {
202 if (input < min || input > max)
203 return -ERANGE;
204
205 *output = roundf(input * scale);
206 return 0;
207 }
208
constructPwleSegment(uint16_t delay,uint16_t amplitude,uint16_t frequency,uint8_t flags,uint32_t vbemfTarget=0)209 void constructPwleSegment(uint16_t delay, uint16_t amplitude, uint16_t frequency, uint8_t flags,
210 uint32_t vbemfTarget = 0) {
211 write(16, delay);
212 write(12, amplitude);
213 write(12, frequency);
214 /* feature flags to control the chirp, CLAB braking, back EMF amplitude regulation */
215 write(8, (flags | 1) << 4);
216 if (flags & PWLE_AMP_REG_BIT) {
217 write(24, vbemfTarget); /* target back EMF voltage */
218 }
219 }
220
221 public:
front() const222 uint8_t *front() const { return head.get(); }
type() const223 uint8_t type() const { return waveformType; }
size() const224 size_t size() const { return bytes; }
225
DspMemChunk(uint8_t type,size_t size)226 DspMemChunk(uint8_t type, size_t size) : head(new uint8_t[size]{0x00}) {
227 waveformType = type;
228 _current = head.get();
229 _max = _current + size;
230
231 if (waveformType == WAVEFORM_COMPOSE) {
232 write(8, 0); /* Padding */
233 write(8, 0); /* nsections placeholder */
234 write(8, 0); /* repeat */
235 } else if (waveformType == WAVEFORM_PWLE) {
236 write(24, 0); /* Waveform length placeholder */
237 write(8, 0); /* Repeat */
238 write(12, 0); /* Wait time between repeats */
239 write(8, 0); /* nsections placeholder */
240 } else {
241 ALOGE("%s: Invalid type: %u", __func__, waveformType);
242 }
243 }
244
flush()245 int flush() {
246 if (!_cachebits)
247 return 0;
248
249 return write(24 - _cachebits, 0);
250 }
251
constructComposeSegment(uint32_t effectVolLevel,uint32_t effectIndex,uint8_t repeat,uint8_t flags,uint16_t nextEffectDelay)252 int constructComposeSegment(uint32_t effectVolLevel, uint32_t effectIndex, uint8_t repeat,
253 uint8_t flags, uint16_t nextEffectDelay) {
254 if (waveformType != WAVEFORM_COMPOSE) {
255 ALOGE("%s: Invalid type: %d", __func__, waveformType);
256 return -EDOM;
257 }
258 if (effectVolLevel > 100 || effectIndex > WAVEFORM_MAX_PHYSICAL_INDEX) {
259 ALOGE("%s: Invalid argument: %u, %u", __func__, effectVolLevel, effectIndex);
260 return -EINVAL;
261 }
262 write(8, effectVolLevel); /* amplitude */
263 write(8, effectIndex); /* index */
264 write(8, repeat); /* repeat */
265 write(8, flags); /* flags */
266 write(16, nextEffectDelay); /* delay */
267 return 0;
268 }
269
constructActiveSegment(int duration,float amplitude,float frequency,bool chirp)270 int constructActiveSegment(int duration, float amplitude, float frequency, bool chirp) {
271 uint16_t delay = 0;
272 uint16_t amp = 0;
273 uint16_t freq = 0;
274 uint8_t flags = 0x0;
275 if (waveformType != WAVEFORM_PWLE) {
276 ALOGE("%s: Invalid type: %d", __func__, waveformType);
277 return -EDOM;
278 }
279 if ((fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) ||
280 (fToU16(amplitude, &, 2048, CS40L26_PWLE_LEVEL_MIN, CS40L26_PWLE_LEVEL_MAX) < 0) ||
281 (fToU16(frequency, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ) < 0)) {
282 ALOGE("%s: Invalid argument: %d, %f, %f", __func__, duration, amplitude, frequency);
283 return -ERANGE;
284 }
285 if (chirp) {
286 flags |= PWLE_CHIRP_BIT;
287 }
288 constructPwleSegment(delay, amp, freq, flags, 0 /*ignored*/);
289 return 0;
290 }
291
constructBrakingSegment(int duration,Braking brakingType)292 int constructBrakingSegment(int duration, Braking brakingType) {
293 uint16_t delay = 0;
294 uint16_t freq = 0;
295 uint8_t flags = 0x00;
296 if (waveformType != WAVEFORM_PWLE) {
297 ALOGE("%s: Invalid type: %d", __func__, waveformType);
298 return -EDOM;
299 }
300 if (fToU16(duration, &delay, 4, 0.0f, COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) < 0) {
301 ALOGE("%s: Invalid argument: %d", __func__, duration);
302 return -ERANGE;
303 }
304 fToU16(PWLE_FREQUENCY_MIN_HZ, &freq, 4, PWLE_FREQUENCY_MIN_HZ, PWLE_FREQUENCY_MAX_HZ);
305 if (static_cast<std::underlying_type<Braking>::type>(brakingType)) {
306 flags |= PWLE_BRAKE_BIT;
307 }
308
309 constructPwleSegment(delay, 0 /*ignored*/, freq, flags, 0 /*ignored*/);
310 return 0;
311 }
312
updateWLength(uint32_t totalDuration)313 int updateWLength(uint32_t totalDuration) {
314 uint8_t *f = front();
315 if (f == nullptr) {
316 ALOGE("%s: head does not exist!", __func__);
317 return -ENOMEM;
318 }
319 if (waveformType != WAVEFORM_PWLE) {
320 ALOGE("%s: Invalid type: %d", __func__, waveformType);
321 return -EDOM;
322 }
323 if (totalDuration > 0x7FFFF) {
324 ALOGE("%s: Invalid argument: %u", __func__, totalDuration);
325 return -EINVAL;
326 }
327 totalDuration *= 8; /* Unit: 0.125 ms (since wlength played @ 8kHz). */
328 totalDuration |=
329 WT_LEN_CALCD; /* Bit 23 is for WT_LEN_CALCD; Bit 22 is for WT_INDEFINITE. */
330 *(f + 0) = (totalDuration >> 24) & 0xFF;
331 *(f + 1) = (totalDuration >> 16) & 0xFF;
332 *(f + 2) = (totalDuration >> 8) & 0xFF;
333 *(f + 3) = totalDuration & 0xFF;
334 return 0;
335 }
336
updateNSection(int segmentIdx)337 int updateNSection(int segmentIdx) {
338 uint8_t *f = front();
339 if (f == nullptr) {
340 ALOGE("%s: head does not exist!", __func__);
341 return -ENOMEM;
342 }
343
344 if (waveformType == WAVEFORM_COMPOSE) {
345 if (segmentIdx > COMPOSE_SIZE_MAX + 1 /*1st effect may have a delay*/) {
346 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
347 return -EINVAL;
348 }
349 *(f + 2) = (0xFF & segmentIdx);
350 } else if (waveformType == WAVEFORM_PWLE) {
351 if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
352 ALOGE("%s: Invalid argument: %d", __func__, segmentIdx);
353 return -EINVAL;
354 }
355 *(f + 7) |= (0xF0 & segmentIdx) >> 4; /* Bit 4 to 7 */
356 *(f + 9) |= (0x0F & segmentIdx) << 4; /* Bit 3 to 0 */
357 } else {
358 ALOGE("%s: Invalid type: %d", __func__, waveformType);
359 return -EDOM;
360 }
361
362 return 0;
363 }
364 };
365
Vibrator(std::unique_ptr<HwApi> hwApiDefault,std::unique_ptr<HwCal> hwCalDefault,std::unique_ptr<HwApi> hwApiDual,std::unique_ptr<HwCal> hwCalDual,std::unique_ptr<HwGPIO> hwgpio)366 Vibrator::Vibrator(std::unique_ptr<HwApi> hwApiDefault, std::unique_ptr<HwCal> hwCalDefault,
367 std::unique_ptr<HwApi> hwApiDual, std::unique_ptr<HwCal> hwCalDual,
368 std::unique_ptr<HwGPIO> hwgpio)
369 : mHwApiDef(std::move(hwApiDefault)),
370 mHwCalDef(std::move(hwCalDefault)),
371 mHwApiDual(std::move(hwApiDual)),
372 mHwCalDual(std::move(hwCalDual)),
373 mHwGPIO(std::move(hwgpio)),
374 mAsyncHandle(std::async([] {})) {
375 int32_t longFrequencyShift;
376 std::string caldata{8, '0'};
377 uint32_t calVer;
378
379 // ==================Single actuators and dual actuators checking =============================
380 if ((mHwApiDual != nullptr) && (mHwCalDual != nullptr))
381 mIsDual = true;
382
383 // ==================INPUT Devices== Base =================
384 const char *inputEventName = std::getenv("INPUT_EVENT_NAME");
385 const char *inputEventPathName = std::getenv("INPUT_EVENT_PATH");
386 if ((strstr(inputEventName, "cs40l26") != nullptr) ||
387 (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
388 glob_t inputEventPaths;
389 int fd = -1;
390 int ret;
391 uint32_t val = 0;
392 char str[20] = {0x00};
393 for (uint8_t retry = 0; retry < 10; retry++) {
394 ret = glob(inputEventPathName, 0, nullptr, &inputEventPaths);
395 if (ret) {
396 ALOGE("Failed to get input event paths (%d): %s", errno, strerror(errno));
397 } else {
398 for (int i = 0; i < inputEventPaths.gl_pathc; i++) {
399 fd = TEMP_FAILURE_RETRY(open(inputEventPaths.gl_pathv[i], O_RDWR));
400 if (fd > 0) {
401 if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 &&
402 (val & (1 << EV_FF)) && ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
403 strstr(str, inputEventName) != nullptr) {
404 mInputFd.reset(fd);
405 ALOGI("Control %s through %s", inputEventName,
406 inputEventPaths.gl_pathv[i]);
407 break;
408 }
409 close(fd);
410 }
411 }
412 }
413
414 if (ret == 0) {
415 globfree(&inputEventPaths);
416 }
417 if (mInputFd.ok()) {
418 break;
419 }
420
421 sleep(1);
422 ALOGW("Retry #%d to search in %zu input devices.", retry, inputEventPaths.gl_pathc);
423 }
424
425 if (!mInputFd.ok()) {
426 ALOGE("Failed to get an input event with name %s", inputEventName);
427 }
428 } else {
429 ALOGE("The input name %s is not cs40l26_input or cs40l26_dual_input", inputEventName);
430 }
431
432 // ==================INPUT Devices== Flip =================
433 if (mIsDual) {
434 const char *inputEventNameDual = std::getenv("INPUT_EVENT_NAME_DUAL");
435 if ((strstr(inputEventNameDual, "cs40l26_dual_input") != nullptr)) {
436 glob_t inputEventPaths;
437 int fd = -1;
438 int ret;
439 uint32_t val = 0;
440 char str[20] = {0x00};
441 for (uint8_t retry = 0; retry < 10; retry++) {
442 ret = glob(inputEventPathName, 0, nullptr, &inputEventPaths);
443 if (ret) {
444 ALOGE("Failed to get flip's input event paths (%d): %s", errno,
445 strerror(errno));
446 } else {
447 for (int i = 0; i < inputEventPaths.gl_pathc; i++) {
448 fd = TEMP_FAILURE_RETRY(open(inputEventPaths.gl_pathv[i], O_RDWR));
449 if (fd > 0) {
450 if (ioctl(fd, EVIOCGBIT(0, sizeof(val)), &val) > 0 &&
451 (val & (1 << EV_FF)) &&
452 ioctl(fd, EVIOCGNAME(sizeof(str)), &str) > 0 &&
453 strstr(str, inputEventNameDual) != nullptr) {
454 mInputFdDual.reset(fd);
455 ALOGI("Control %s through %s", inputEventNameDual,
456 inputEventPaths.gl_pathv[i]);
457 break;
458 }
459 close(fd);
460 }
461 }
462 }
463
464 if (ret == 0) {
465 globfree(&inputEventPaths);
466 }
467 if (mInputFdDual.ok()) {
468 break;
469 }
470
471 sleep(1);
472 ALOGW("Retry #%d to search in %zu input devices.", retry, inputEventPaths.gl_pathc);
473 }
474
475 if (!mInputFdDual.ok()) {
476 ALOGE("Failed to get an input event with name %s", inputEventNameDual);
477 }
478 ALOGE("HWAPI: %s", std::getenv("HWAPI_PATH_PREFIX"));
479 } else {
480 ALOGE("The input name %s is not cs40l26_dual_input", inputEventNameDual);
481 }
482 }
483 // ====================HAL internal effect table== Base ==================================
484
485 mFfEffects.resize(WAVEFORM_MAX_INDEX);
486 mEffectDurations.resize(WAVEFORM_MAX_INDEX);
487 mEffectDurations = {
488 1000, 100, 12, 1000, 300, 130, 150, 500, 100, 5, 12, 1000, 1000, 1000,
489 }; /* 11+3 waveforms. The duration must < UINT16_MAX */
490 mEffectCustomData.reserve(WAVEFORM_MAX_INDEX);
491
492 uint8_t effectIndex;
493 uint16_t numBytes = 0;
494 for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
495 if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
496 /* Initialize physical waveforms. */
497 mEffectCustomData.push_back({RAM_WVFRM_BANK, effectIndex});
498 mFfEffects[effectIndex] = {
499 .type = FF_PERIODIC,
500 .id = -1,
501 // Length == 0 to allow firmware control of the duration
502 .replay.length = 0,
503 .u.periodic.waveform = FF_CUSTOM,
504 .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
505 .u.periodic.custom_len =
506 static_cast<uint32_t>(mEffectCustomData[effectIndex].size()),
507 };
508 // Bypass the waveform update due to different input name
509 if ((strstr(inputEventName, "cs40l26") != nullptr) ||
510 (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
511 // Let the firmware control the playback duration to avoid
512 // cutting any effect that is played short
513 if (!mHwApiDef->setFFEffect(
514 mInputFd, &mFfEffects[effectIndex],
515 mEffectDurations[effectIndex])) {
516 ALOGE("Failed upload effect %d (%d): %s", effectIndex, errno, strerror(errno));
517 }
518 }
519 if (mFfEffects[effectIndex].id != effectIndex) {
520 ALOGW("Unexpected effect index: %d -> %d", effectIndex, mFfEffects[effectIndex].id);
521 }
522 } else {
523 /* Initiate placeholders for OWT effects. */
524 numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP
525 : FF_CUSTOM_DATA_LEN_MAX_PWLE;
526 std::vector<int16_t> tempVec(numBytes, 0);
527 mEffectCustomData.push_back(std::move(tempVec));
528 mFfEffects[effectIndex] = {
529 .type = FF_PERIODIC,
530 .id = -1,
531 .replay.length = 0,
532 .u.periodic.waveform = FF_CUSTOM,
533 .u.periodic.custom_data = mEffectCustomData[effectIndex].data(),
534 .u.periodic.custom_len = 0,
535 };
536 }
537 }
538
539 // ====================HAL internal effect table== Flip ==================================
540 if (mIsDual) {
541 mFfEffectsDual.resize(WAVEFORM_MAX_INDEX);
542 mEffectCustomDataDual.reserve(WAVEFORM_MAX_INDEX);
543
544 for (effectIndex = 0; effectIndex < WAVEFORM_MAX_INDEX; effectIndex++) {
545 if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
546 /* Initialize physical waveforms. */
547 mEffectCustomDataDual.push_back({RAM_WVFRM_BANK, effectIndex});
548 mFfEffectsDual[effectIndex] = {
549 .type = FF_PERIODIC,
550 .id = -1,
551 // Length == 0 to allow firmware control of the duration
552 .replay.length = 0,
553 .u.periodic.waveform = FF_CUSTOM,
554 .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(),
555 .u.periodic.custom_len =
556 static_cast<uint32_t>(mEffectCustomDataDual[effectIndex].size()),
557 };
558 // Bypass the waveform update due to different input name
559 if ((strstr(inputEventName, "cs40l26") != nullptr) ||
560 (strstr(inputEventName, "cs40l26_dual_input") != nullptr)) {
561 // Let the firmware control the playback duration to avoid
562 // cutting any effect that is played short
563 if (!mHwApiDual->setFFEffect(
564 mInputFdDual, &mFfEffectsDual[effectIndex],
565 mEffectDurations[effectIndex])) {
566 ALOGE("Failed upload flip's effect %d (%d): %s", effectIndex, errno,
567 strerror(errno));
568 }
569 }
570 if (mFfEffectsDual[effectIndex].id != effectIndex) {
571 ALOGW("Unexpected effect index: %d -> %d", effectIndex,
572 mFfEffectsDual[effectIndex].id);
573 }
574 } else {
575 /* Initiate placeholders for OWT effects. */
576 numBytes = effectIndex == WAVEFORM_COMPOSE ? FF_CUSTOM_DATA_LEN_MAX_COMP
577 : FF_CUSTOM_DATA_LEN_MAX_PWLE;
578 std::vector<int16_t> tempVec(numBytes, 0);
579 mEffectCustomDataDual.push_back(std::move(tempVec));
580 mFfEffectsDual[effectIndex] = {
581 .type = FF_PERIODIC,
582 .id = -1,
583 .replay.length = 0,
584 .u.periodic.waveform = FF_CUSTOM,
585 .u.periodic.custom_data = mEffectCustomDataDual[effectIndex].data(),
586 .u.periodic.custom_len = 0,
587 };
588 }
589 }
590 }
591 // ==============Calibration data checking======================================
592
593 if (mHwCalDef->getF0(&caldata)) {
594 mHwApiDef->setF0(caldata);
595 }
596 if (mHwCalDef->getRedc(&caldata)) {
597 mHwApiDef->setRedc(caldata);
598 }
599 if (mHwCalDef->getQ(&caldata)) {
600 mHwApiDef->setQ(caldata);
601 }
602
603 if (mHwCalDef->getF0SyncOffset(&mF0Offset)) {
604 ALOGD("Vibrator::Vibrator: F0 offset calculated from both base and flip calibration data: "
605 "%u",
606 mF0Offset);
607 } else {
608 mHwCalDef->getLongFrequencyShift(&longFrequencyShift);
609 if (longFrequencyShift > 0) {
610 mF0Offset = longFrequencyShift * std::pow(2, 14);
611 } else if (longFrequencyShift < 0) {
612 mF0Offset = std::pow(2, 24) - std::abs(longFrequencyShift) * std::pow(2, 14);
613 } else {
614 mF0Offset = 0;
615 }
616 ALOGD("Vibrator::Vibrator: F0 offset calculated from long shift frequency: %u", mF0Offset);
617 }
618
619 if (mIsDual) {
620 if (mHwCalDual->getF0(&caldata)) {
621 mHwApiDual->setF0(caldata);
622 }
623 if (mHwCalDual->getRedc(&caldata)) {
624 mHwApiDual->setRedc(caldata);
625 }
626 if (mHwCalDual->getQ(&caldata)) {
627 mHwApiDual->setQ(caldata);
628 }
629
630 if (mHwCalDual->getF0SyncOffset(&mF0OffsetDual)) {
631 ALOGD("Vibrator::Vibrator: Dual: F0 offset calculated from both base and flip "
632 "calibration data: "
633 "%u",
634 mF0OffsetDual);
635 }
636 }
637
638 mHwCalDef->getVersion(&calVer);
639 if (calVer == 2) {
640 mHwCalDef->getTickVolLevels(&(mTickEffectVol));
641 mHwCalDef->getClickVolLevels(&(mClickEffectVol));
642 mHwCalDef->getLongVolLevels(&(mLongEffectVol));
643 } else {
644 ALOGW("Unsupported calibration version! Using the default calibration value");
645 mHwCalDef->getTickVolLevels(&(mTickEffectVol));
646 mHwCalDef->getClickVolLevels(&(mClickEffectVol));
647 mHwCalDef->getLongVolLevels(&(mLongEffectVol));
648 }
649
650 // ================Project specific setting to driver===============================
651
652 mHwApiDef->setF0CompEnable(mHwCalDef->isF0CompEnabled());
653 mHwApiDef->setRedcCompEnable(mHwCalDef->isRedcCompEnabled());
654 mHwApiDef->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
655 if (mIsDual) {
656 mHwApiDual->setF0CompEnable(mHwCalDual->isF0CompEnabled());
657 mHwApiDual->setRedcCompEnable(mHwCalDual->isRedcCompEnabled());
658 mHwApiDual->setMinOnOffInterval(MIN_ON_OFF_INTERVAL_US);
659 }
660 // ===============Audio coupled haptics bool init ========
661 mIsUnderExternalControl = false;
662
663 // =============== Compose PWLE check =====================================
664 mIsChirpEnabled = mHwCalDef->isChirpEnabled();
665
666 mHwCalDef->getSupportedPrimitives(&mSupportedPrimitivesBits);
667 if (mSupportedPrimitivesBits > 0) {
668 for (auto e : defaultSupportedPrimitives) {
669 if (mSupportedPrimitivesBits & (1 << uint32_t(e))) {
670 mSupportedPrimitives.emplace_back(e);
671 }
672 }
673 } else {
674 for (auto e : defaultSupportedPrimitives) {
675 mSupportedPrimitivesBits |= (1 << uint32_t(e));
676 }
677 mSupportedPrimitives = defaultSupportedPrimitives;
678 }
679
680 mPrimitiveMaxScale = {1.0f, 0.95f, 0.75f, 0.9f, 1.0f, 1.0f, 1.0f, 0.75f, 0.75f};
681 mPrimitiveMinScale = {0.0f, 0.01f, 0.11f, 0.23f, 0.0f, 0.25f, 0.02f, 0.03f, 0.16f};
682
683 // ====== Get GPIO status and init it ================
684 mGPIOStatus = mHwGPIO->getGPIO();
685 if (!mGPIOStatus || !mHwGPIO->initGPIO()) {
686 ALOGE("Vibrator: GPIO initialization process error");
687 }
688 }
689
getCapabilities(int32_t * _aidl_return)690 ndk::ScopedAStatus Vibrator::getCapabilities(int32_t *_aidl_return) {
691 ATRACE_NAME("Vibrator::getCapabilities");
692
693 int32_t ret = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
694 IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_GET_RESONANT_FREQUENCY |
695 IVibrator::CAP_GET_Q_FACTOR;
696 if (hasHapticAlsaDevice()) {
697 ret |= IVibrator::CAP_EXTERNAL_CONTROL;
698 } else {
699 ALOGE("No haptics ALSA device");
700 }
701 if (mHwApiDef->hasOwtFreeSpace()) {
702 ret |= IVibrator::CAP_COMPOSE_EFFECTS;
703 if (mIsChirpEnabled) {
704 ret |= IVibrator::CAP_FREQUENCY_CONTROL | IVibrator::CAP_COMPOSE_PWLE_EFFECTS;
705 }
706 }
707 *_aidl_return = ret;
708 return ndk::ScopedAStatus::ok();
709 }
710
off()711 ndk::ScopedAStatus Vibrator::off() {
712 ATRACE_NAME("Vibrator::off");
713 bool ret{true};
714 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
715
716 if (mActiveId >= 0) {
717 ALOGD("Off: Stop the active effect: %d", mActiveId);
718 /* Stop the active effect. */
719 if (!mHwApiDef->setFFPlay(mInputFd, mActiveId, false)) {
720 ALOGE("Off: Failed to stop effect %d (%d): %s", mActiveId, errno, strerror(errno));
721 ret = false;
722 }
723 if (mIsDual && (!mHwApiDual->setFFPlay(mInputFdDual, mActiveId, false))) {
724 ALOGE("Off: Failed to stop flip's effect %d (%d): %s", mActiveId, errno,
725 strerror(errno));
726 ret = false;
727 }
728
729 if (!mHwGPIO->setGPIOOutput(false)) {
730 ALOGE("Off: Failed to reset GPIO(%d): %s", errno, strerror(errno));
731 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
732 }
733 } else {
734 ALOGD("Off: Vibrator is already off");
735 }
736
737 setGlobalAmplitude(false);
738 if (mF0Offset) {
739 mHwApiDef->setF0Offset(0);
740 if (mIsDual && mF0OffsetDual) {
741 mHwApiDual->setF0Offset(0);
742 }
743 }
744
745 if (ret) {
746 ALOGD("Off: Done.");
747 mActiveId = -1;
748 return ndk::ScopedAStatus::ok();
749 } else {
750 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
751 }
752 }
753
on(int32_t timeoutMs,const std::shared_ptr<IVibratorCallback> & callback)754 ndk::ScopedAStatus Vibrator::on(int32_t timeoutMs,
755 const std::shared_ptr<IVibratorCallback> &callback) {
756 ATRACE_NAME("Vibrator::on");
757 ALOGD("Vibrator::on");
758
759 if (timeoutMs > MAX_TIME_MS) {
760 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
761 }
762 const uint16_t index = (timeoutMs < WAVEFORM_LONG_VIBRATION_THRESHOLD_MS)
763 ? WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX
764 : WAVEFORM_LONG_VIBRATION_EFFECT_INDEX;
765 if (MAX_COLD_START_LATENCY_MS <= MAX_TIME_MS - timeoutMs) {
766 timeoutMs += MAX_COLD_START_LATENCY_MS;
767 }
768 setGlobalAmplitude(true);
769 if (mF0Offset) {
770 mHwApiDef->setF0Offset(mF0Offset);
771 if (mIsDual && mF0OffsetDual) {
772 mHwApiDual->setF0Offset(mF0OffsetDual);
773 }
774 }
775 return on(timeoutMs, index, nullptr /*ignored*/, callback);
776 }
777
perform(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * _aidl_return)778 ndk::ScopedAStatus Vibrator::perform(Effect effect, EffectStrength strength,
779 const std::shared_ptr<IVibratorCallback> &callback,
780 int32_t *_aidl_return) {
781 ATRACE_NAME("Vibrator::perform");
782 ALOGD("Vibrator::perform");
783 return performEffect(effect, strength, callback, _aidl_return);
784 }
785
getSupportedEffects(std::vector<Effect> * _aidl_return)786 ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect> *_aidl_return) {
787 *_aidl_return = {Effect::TEXTURE_TICK, Effect::TICK, Effect::CLICK, Effect::HEAVY_CLICK,
788 Effect::DOUBLE_CLICK};
789 return ndk::ScopedAStatus::ok();
790 }
791
setAmplitude(float amplitude)792 ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
793 ATRACE_NAME("Vibrator::setAmplitude");
794
795 if (amplitude <= 0.0f || amplitude > 1.0f) {
796 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
797 }
798
799 mLongEffectScale = amplitude;
800 if (!isUnderExternalControl()) {
801 return setGlobalAmplitude(true);
802 } else {
803 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
804 }
805 }
806
setExternalControl(bool enabled)807 ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
808 ATRACE_NAME("Vibrator::setExternalControl");
809
810 setGlobalAmplitude(enabled);
811
812 if (mHasHapticAlsaDevice || mConfigHapticAlsaDeviceDone || hasHapticAlsaDevice()) {
813 if (!mHwApiDef->setHapticPcmAmp(&mHapticPcm, enabled, mCard, mDevice)) {
814 ALOGE("Failed to %s haptic pcm device: %d", (enabled ? "enable" : "disable"), mDevice);
815 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
816 }
817 } else {
818 ALOGE("No haptics ALSA device");
819 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
820 }
821
822 mIsUnderExternalControl = enabled;
823 return ndk::ScopedAStatus::ok();
824 }
825
getCompositionDelayMax(int32_t * maxDelayMs)826 ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t *maxDelayMs) {
827 ATRACE_NAME("Vibrator::getCompositionDelayMax");
828 *maxDelayMs = COMPOSE_DELAY_MAX_MS;
829 return ndk::ScopedAStatus::ok();
830 }
831
getCompositionSizeMax(int32_t * maxSize)832 ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t *maxSize) {
833 ATRACE_NAME("Vibrator::getCompositionSizeMax");
834 *maxSize = COMPOSE_SIZE_MAX;
835 return ndk::ScopedAStatus::ok();
836 }
837
getSupportedPrimitives(std::vector<CompositePrimitive> * supported)838 ndk::ScopedAStatus Vibrator::getSupportedPrimitives(std::vector<CompositePrimitive> *supported) {
839 *supported = mSupportedPrimitives;
840 return ndk::ScopedAStatus::ok();
841 }
842
getPrimitiveDuration(CompositePrimitive primitive,int32_t * durationMs)843 ndk::ScopedAStatus Vibrator::getPrimitiveDuration(CompositePrimitive primitive,
844 int32_t *durationMs) {
845 ndk::ScopedAStatus status;
846 uint32_t effectIndex;
847 if (primitive != CompositePrimitive::NOOP) {
848 status = getPrimitiveDetails(primitive, &effectIndex);
849 if (!status.isOk()) {
850 return status;
851 }
852
853 *durationMs = mEffectDurations[effectIndex];
854 } else {
855 *durationMs = 0;
856 }
857 return ndk::ScopedAStatus::ok();
858 }
859
compose(const std::vector<CompositeEffect> & composite,const std::shared_ptr<IVibratorCallback> & callback)860 ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect> &composite,
861 const std::shared_ptr<IVibratorCallback> &callback) {
862 ATRACE_NAME("Vibrator::compose");
863 ALOGD("Vibrator::compose");
864 uint16_t size;
865 uint16_t nextEffectDelay;
866 uint16_t totalDuration = 0;
867
868 if (composite.size() > COMPOSE_SIZE_MAX || composite.empty()) {
869 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
870 }
871
872 /* Check if there is a wait before the first effect. */
873 nextEffectDelay = composite.front().delayMs;
874 totalDuration += nextEffectDelay;
875 if (nextEffectDelay > COMPOSE_DELAY_MAX_MS || nextEffectDelay < 0) {
876 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
877 } else if (nextEffectDelay > 0) {
878 size = composite.size() + 1;
879 } else {
880 size = composite.size();
881 }
882
883 DspMemChunk ch(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
884 const uint8_t header_count = ch.size();
885
886 /* Insert 1 section for a wait before the first effect. */
887 if (nextEffectDelay) {
888 ch.constructComposeSegment(0 /*amplitude*/, 0 /*index*/, 0 /*repeat*/, 0 /*flags*/,
889 nextEffectDelay /*delay*/);
890 }
891
892 for (uint32_t i_curr = 0, i_next = 1; i_curr < composite.size(); i_curr++, i_next++) {
893 auto &e_curr = composite[i_curr];
894 uint32_t effectIndex = 0;
895 uint32_t effectVolLevel = 0;
896 float effectScale = e_curr.scale;
897 if (effectScale < 0.0f || effectScale > 1.0f) {
898 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
899 }
900
901 if (e_curr.primitive != CompositePrimitive::NOOP) {
902 ndk::ScopedAStatus status;
903 status = getPrimitiveDetails(e_curr.primitive, &effectIndex);
904 if (!status.isOk()) {
905 return status;
906 }
907 // Add a max and min threshold to prevent the device crash(overcurrent) or no
908 // feeling
909 if (effectScale > mPrimitiveMaxScale[static_cast<uint32_t>(e_curr.primitive)]) {
910 effectScale = mPrimitiveMaxScale[static_cast<uint32_t>(e_curr.primitive)];
911 }
912 if (effectScale < mPrimitiveMinScale[static_cast<uint32_t>(e_curr.primitive)]) {
913 effectScale = mPrimitiveMinScale[static_cast<uint32_t>(e_curr.primitive)];
914 }
915 effectVolLevel = intensityToVolLevel(effectScale, effectIndex);
916 totalDuration += mEffectDurations[effectIndex];
917 }
918
919 /* Fetch the next composite effect delay and fill into the current section */
920 nextEffectDelay = 0;
921 if (i_next < composite.size()) {
922 auto &e_next = composite[i_next];
923 int32_t delay = e_next.delayMs;
924
925 if (delay > COMPOSE_DELAY_MAX_MS || delay < 0) {
926 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
927 }
928 nextEffectDelay = delay;
929 totalDuration += delay;
930 }
931
932 if (effectIndex == 0 && nextEffectDelay == 0) {
933 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
934 }
935
936 ch.constructComposeSegment(effectVolLevel, effectIndex, 0 /*repeat*/, 0 /*flags*/,
937 nextEffectDelay /*delay*/);
938 }
939
940 ch.flush();
941 if (ch.updateNSection(size) < 0) {
942 ALOGE("%s: Failed to update the section count", __func__);
943 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
944 }
945 if (header_count == ch.size()) {
946 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
947 } else {
948 // Composition duration should be 0 to allow firmware to play the whole effect
949 mFfEffects[WAVEFORM_COMPOSE].replay.length = 0;
950 if (mIsDual) {
951 mFfEffectsDual[WAVEFORM_COMPOSE].replay.length = 0;
952 }
953 return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
954 callback);
955 }
956 }
957
on(uint32_t timeoutMs,uint32_t effectIndex,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)958 ndk::ScopedAStatus Vibrator::on(uint32_t timeoutMs, uint32_t effectIndex, const DspMemChunk *ch,
959 const std::shared_ptr<IVibratorCallback> &callback) {
960 ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
961
962 if (effectIndex >= FF_MAX_EFFECTS) {
963 ALOGE("Invalid waveform index %d", effectIndex);
964 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
965 }
966 if (mAsyncHandle.wait_for(ASYNC_COMPLETION_TIMEOUT) != std::future_status::ready) {
967 ALOGE("Previous vibration pending: prev: %d, curr: %d", mActiveId, effectIndex);
968 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
969 }
970
971 if (ch) {
972 /* Upload OWT effect. */
973 if (ch->front() == nullptr) {
974 ALOGE("Invalid OWT bank");
975 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
976 }
977
978 if (ch->type() != WAVEFORM_PWLE && ch->type() != WAVEFORM_COMPOSE) {
979 ALOGE("Invalid OWT type");
980 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
981 }
982 effectIndex = ch->type();
983
984 uint32_t freeBytes;
985 mHwApiDef->getOwtFreeSpace(&freeBytes);
986 if (ch->size() > freeBytes) {
987 ALOGE("Invalid OWT length: Effect %d: %zu > %d!", effectIndex, ch->size(), freeBytes);
988 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
989 }
990 if (mIsDual) {
991 mHwApiDual->getOwtFreeSpace(&freeBytes);
992 if (ch-> size() > freeBytes) {
993 ALOGE("Invalid OWT length in flip: Effect %d: %d > %d!", effectIndex,
994 ch-> size(), freeBytes);
995 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
996 }
997 }
998
999 int errorStatus;
1000 if (mGPIOStatus && mIsDual) {
1001 mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1002 mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1003 } else {
1004 ALOGD("Not dual haptics HAL and GPIO status fail");
1005 }
1006
1007 if (!mHwApiDef->uploadOwtEffect(mInputFd, ch->front(), ch->size(), &mFfEffects[effectIndex],
1008 &effectIndex, &errorStatus)) {
1009 ALOGE("Invalid uploadOwtEffect");
1010 return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
1011 }
1012 if (mIsDual && !mHwApiDual->uploadOwtEffect(mInputFdDual, ch->front(), ch->size(),
1013 &mFfEffectsDual[effectIndex], &effectIndex,
1014 &errorStatus)) {
1015 ALOGE("Invalid uploadOwtEffect in flip");
1016 return ndk::ScopedAStatus::fromExceptionCode(errorStatus);
1017 }
1018
1019 } else if (effectIndex == WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX ||
1020 effectIndex == WAVEFORM_LONG_VIBRATION_EFFECT_INDEX) {
1021 /* Update duration for long/short vibration. */
1022 mFfEffects[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
1023 if (mGPIOStatus && mIsDual) {
1024 mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1025 mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1026 } else {
1027 ALOGD("Not dual haptics HAL and GPIO status fail");
1028 }
1029 if (!mHwApiDef->setFFEffect(mInputFd, &mFfEffects[effectIndex],
1030 static_cast<uint16_t>(timeoutMs))) {
1031 ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
1032 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1033 }
1034 if (mIsDual) {
1035 mFfEffectsDual[effectIndex].replay.length = static_cast<uint16_t>(timeoutMs);
1036 if (!mHwApiDual->setFFEffect(mInputFdDual, &mFfEffectsDual[effectIndex],
1037 static_cast<uint16_t>(timeoutMs))) {
1038 ALOGE("Failed to edit flip's effect %d (%d): %s", effectIndex, errno,
1039 strerror(errno));
1040 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1041 }
1042 }
1043 }
1044
1045 {
1046 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1047 /* Play the event now. */
1048 mActiveId = effectIndex;
1049 if (!mGPIOStatus) {
1050 ALOGE("GetVibrator: GPIO status error");
1051 // Do playcode to play effect
1052 if (!mHwApiDef->setFFPlay(mInputFd, effectIndex, true)) {
1053 ALOGE("Failed to play effect %d (%d): %s", effectIndex, errno, strerror(errno));
1054 mActiveId = -1;
1055 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1056 }
1057 if (mIsDual && !mHwApiDual->setFFPlay(mInputFdDual, effectIndex, true)) {
1058 ALOGE("Failed to play flip's effect %d (%d): %s", effectIndex, errno,
1059 strerror(errno));
1060 mActiveId = -1;
1061 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1062 }
1063 } else {
1064 // Using GPIO to play effect
1065 if ((effectIndex == WAVEFORM_CLICK_INDEX || effectIndex == WAVEFORM_LIGHT_TICK_INDEX)) {
1066 mFfEffects[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1067 if (!mHwApiDef->setFFEffect(mInputFd, &mFfEffects[effectIndex],
1068 mFfEffects[effectIndex].replay.length)) {
1069 ALOGE("Failed to edit effect %d (%d): %s", effectIndex, errno, strerror(errno));
1070 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1071 }
1072 if (mIsDual) {
1073 mFfEffectsDual[effectIndex].trigger.button = GPIO_TRIGGER_CONFIG | effectIndex;
1074 if (!mHwApiDual->setFFEffect(mInputFdDual, &mFfEffectsDual[effectIndex],
1075 mFfEffectsDual[effectIndex].replay.length)) {
1076 ALOGE("Failed to edit flip's effect %d (%d): %s", effectIndex, errno,
1077 strerror(errno));
1078 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1079 }
1080 }
1081 }
1082 if (!mHwGPIO->setGPIOOutput(true)) {
1083 ALOGE("Failed to trigger effect %d (%d) by GPIO: %s", effectIndex, errno,
1084 strerror(errno));
1085 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1086 }
1087 }
1088 }
1089
1090 mAsyncHandle = std::async(&Vibrator::waitForComplete, this, callback);
1091 ALOGD("Vibrator::on, set done.");
1092 return ndk::ScopedAStatus::ok();
1093 }
1094
setEffectAmplitude(float amplitude,float maximum)1095 ndk::ScopedAStatus Vibrator::setEffectAmplitude(float amplitude, float maximum) {
1096 uint16_t scale = amplitudeToScale(amplitude, maximum);
1097 if (!mHwApiDef->setFFGain(mInputFd, scale)) {
1098 ALOGE("Failed to set the gain to %u (%d): %s", scale, errno, strerror(errno));
1099 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1100 }
1101 if (mIsDual) {
1102 if (!mHwApiDual->setFFGain(mInputFdDual, scale)) {
1103 ALOGE("Failed to set flip's gain to %u (%d): %s", scale, errno, strerror(errno));
1104 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1105 }
1106 }
1107 return ndk::ScopedAStatus::ok();
1108 }
1109
setGlobalAmplitude(bool set)1110 ndk::ScopedAStatus Vibrator::setGlobalAmplitude(bool set) {
1111 uint8_t amplitude = set ? roundf(mLongEffectScale * mLongEffectVol[1]) : VOLTAGE_SCALE_MAX;
1112 if (!set) {
1113 mLongEffectScale = 1.0; // Reset the scale for the later new effect.
1114 }
1115
1116 return setEffectAmplitude(amplitude, VOLTAGE_SCALE_MAX);
1117 }
1118
getSupportedAlwaysOnEffects(std::vector<Effect> *)1119 ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector<Effect> * /*_aidl_return*/) {
1120 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1121 }
1122
alwaysOnEnable(int32_t,Effect,EffectStrength)1123 ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t /*id*/, Effect /*effect*/,
1124 EffectStrength /*strength*/) {
1125 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1126 }
alwaysOnDisable(int32_t)1127 ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t /*id*/) {
1128 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1129 }
1130
getResonantFrequency(float * resonantFreqHz)1131 ndk::ScopedAStatus Vibrator::getResonantFrequency(float *resonantFreqHz) {
1132 std::string caldata{8, '0'};
1133 if (!mHwCalDef->getF0(&caldata)) {
1134 ALOGE("Failed to get resonant frequency (%d): %s", errno, strerror(errno));
1135 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1136 }
1137 *resonantFreqHz = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q14_BIT_SHIFT);
1138
1139 return ndk::ScopedAStatus::ok();
1140 }
1141
getQFactor(float * qFactor)1142 ndk::ScopedAStatus Vibrator::getQFactor(float *qFactor) {
1143 std::string caldata{8, '0'};
1144 if (!mHwCalDef->getQ(&caldata)) {
1145 ALOGE("Failed to get q factor (%d): %s", errno, strerror(errno));
1146 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
1147 }
1148 *qFactor = static_cast<float>(std::stoul(caldata, nullptr, 16)) / (1 << Q16_BIT_SHIFT);
1149
1150 return ndk::ScopedAStatus::ok();
1151 }
1152
getFrequencyResolution(float * freqResolutionHz)1153 ndk::ScopedAStatus Vibrator::getFrequencyResolution(float *freqResolutionHz) {
1154 int32_t capabilities;
1155 Vibrator::getCapabilities(&capabilities);
1156 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1157 *freqResolutionHz = PWLE_FREQUENCY_RESOLUTION_HZ;
1158 return ndk::ScopedAStatus::ok();
1159 } else {
1160 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1161 }
1162 }
1163
getFrequencyMinimum(float * freqMinimumHz)1164 ndk::ScopedAStatus Vibrator::getFrequencyMinimum(float *freqMinimumHz) {
1165 int32_t capabilities;
1166 Vibrator::getCapabilities(&capabilities);
1167 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1168 *freqMinimumHz = PWLE_FREQUENCY_MIN_HZ;
1169 return ndk::ScopedAStatus::ok();
1170 } else {
1171 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1172 }
1173 }
1174
getBandwidthAmplitudeMap(std::vector<float> * _aidl_return)1175 ndk::ScopedAStatus Vibrator::getBandwidthAmplitudeMap(std::vector<float> *_aidl_return) {
1176 // TODO(b/170919640): complete implementation
1177 int32_t capabilities;
1178 Vibrator::getCapabilities(&capabilities);
1179 if (capabilities & IVibrator::CAP_FREQUENCY_CONTROL) {
1180 std::vector<float> bandwidthAmplitudeMap(PWLE_BW_MAP_SIZE, 1.0);
1181 *_aidl_return = bandwidthAmplitudeMap;
1182 return ndk::ScopedAStatus::ok();
1183 } else {
1184 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1185 }
1186 }
1187
getPwlePrimitiveDurationMax(int32_t * durationMs)1188 ndk::ScopedAStatus Vibrator::getPwlePrimitiveDurationMax(int32_t *durationMs) {
1189 int32_t capabilities;
1190 Vibrator::getCapabilities(&capabilities);
1191 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1192 *durationMs = COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS;
1193 return ndk::ScopedAStatus::ok();
1194 } else {
1195 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1196 }
1197 }
1198
getPwleCompositionSizeMax(int32_t * maxSize)1199 ndk::ScopedAStatus Vibrator::getPwleCompositionSizeMax(int32_t *maxSize) {
1200 int32_t capabilities;
1201 Vibrator::getCapabilities(&capabilities);
1202 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1203 *maxSize = COMPOSE_PWLE_SIZE_MAX_DEFAULT;
1204 return ndk::ScopedAStatus::ok();
1205 } else {
1206 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1207 }
1208 }
1209
getSupportedBraking(std::vector<Braking> * supported)1210 ndk::ScopedAStatus Vibrator::getSupportedBraking(std::vector<Braking> *supported) {
1211 int32_t capabilities;
1212 Vibrator::getCapabilities(&capabilities);
1213 if (capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) {
1214 *supported = {
1215 Braking::NONE,
1216 };
1217 return ndk::ScopedAStatus::ok();
1218 } else {
1219 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1220 }
1221 }
1222
resetPreviousEndAmplitudeEndFrequency(float * prevEndAmplitude,float * prevEndFrequency)1223 static void resetPreviousEndAmplitudeEndFrequency(float *prevEndAmplitude,
1224 float *prevEndFrequency) {
1225 const float reset = -1.0;
1226 *prevEndAmplitude = reset;
1227 *prevEndFrequency = reset;
1228 }
1229
incrementIndex(int * index)1230 static void incrementIndex(int *index) {
1231 *index += 1;
1232 }
1233
composePwle(const std::vector<PrimitivePwle> & composite,const std::shared_ptr<IVibratorCallback> & callback)1234 ndk::ScopedAStatus Vibrator::composePwle(const std::vector<PrimitivePwle> &composite,
1235 const std::shared_ptr<IVibratorCallback> &callback) {
1236 ATRACE_NAME("Vibrator::composePwle");
1237 int32_t capabilities;
1238
1239 Vibrator::getCapabilities(&capabilities);
1240 if ((capabilities & IVibrator::CAP_COMPOSE_PWLE_EFFECTS) == 0) {
1241 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1242 }
1243
1244 if (composite.empty() || composite.size() > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1245 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1246 }
1247
1248 std::vector<Braking> supported;
1249 Vibrator::getSupportedBraking(&supported);
1250 bool isClabSupported =
1251 std::find(supported.begin(), supported.end(), Braking::CLAB) != supported.end();
1252
1253 int segmentIdx = 0;
1254 uint32_t totalDuration = 0;
1255 float prevEndAmplitude;
1256 float prevEndFrequency;
1257 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1258 DspMemChunk ch(WAVEFORM_PWLE, FF_CUSTOM_DATA_LEN_MAX_PWLE);
1259 bool chirp = false;
1260
1261 for (auto &e : composite) {
1262 switch (e.getTag()) {
1263 case PrimitivePwle::active: {
1264 auto active = e.get<PrimitivePwle::active>();
1265 if (active.duration < 0 ||
1266 active.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1267 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1268 }
1269 if (active.startAmplitude < PWLE_LEVEL_MIN ||
1270 active.startAmplitude > PWLE_LEVEL_MAX ||
1271 active.endAmplitude < PWLE_LEVEL_MIN || active.endAmplitude > PWLE_LEVEL_MAX) {
1272 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1273 }
1274 if (active.startAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1275 active.startAmplitude = CS40L26_PWLE_LEVEL_MAX;
1276 }
1277 if (active.endAmplitude > CS40L26_PWLE_LEVEL_MAX) {
1278 active.endAmplitude = CS40L26_PWLE_LEVEL_MAX;
1279 }
1280
1281 if (active.startFrequency < PWLE_FREQUENCY_MIN_HZ ||
1282 active.startFrequency > PWLE_FREQUENCY_MAX_HZ ||
1283 active.endFrequency < PWLE_FREQUENCY_MIN_HZ ||
1284 active.endFrequency > PWLE_FREQUENCY_MAX_HZ) {
1285 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1286 }
1287
1288 if (!((active.startAmplitude == prevEndAmplitude) &&
1289 (active.startFrequency == prevEndFrequency))) {
1290 if (ch.constructActiveSegment(0, active.startAmplitude, active.startFrequency,
1291 false) < 0) {
1292 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1293 }
1294 incrementIndex(&segmentIdx);
1295 }
1296
1297 if (active.startFrequency != active.endFrequency) {
1298 chirp = true;
1299 }
1300 if (ch.constructActiveSegment(active.duration, active.endAmplitude,
1301 active.endFrequency, chirp) < 0) {
1302 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1303 }
1304 incrementIndex(&segmentIdx);
1305
1306 prevEndAmplitude = active.endAmplitude;
1307 prevEndFrequency = active.endFrequency;
1308 totalDuration += active.duration;
1309 chirp = false;
1310 break;
1311 }
1312 case PrimitivePwle::braking: {
1313 auto braking = e.get<PrimitivePwle::braking>();
1314 if (braking.braking > Braking::CLAB) {
1315 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1316 } else if (!isClabSupported && (braking.braking == Braking::CLAB)) {
1317 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1318 }
1319
1320 if (braking.duration > COMPOSE_PWLE_PRIMITIVE_DURATION_MAX_MS) {
1321 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1322 }
1323
1324 if (ch.constructBrakingSegment(0, braking.braking) < 0) {
1325 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1326 }
1327 incrementIndex(&segmentIdx);
1328
1329 if (ch.constructBrakingSegment(braking.duration, braking.braking) < 0) {
1330 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1331 }
1332 incrementIndex(&segmentIdx);
1333
1334 resetPreviousEndAmplitudeEndFrequency(&prevEndAmplitude, &prevEndFrequency);
1335 totalDuration += braking.duration;
1336 break;
1337 }
1338 }
1339
1340 if (segmentIdx > COMPOSE_PWLE_SIZE_MAX_DEFAULT) {
1341 ALOGE("Too many PrimitivePwle section!");
1342 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1343 }
1344 }
1345 ch.flush();
1346
1347 /* Update wlength */
1348 totalDuration += MAX_COLD_START_LATENCY_MS;
1349 if (totalDuration > 0x7FFFF) {
1350 ALOGE("Total duration is too long (%d)!", totalDuration);
1351 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1352 }
1353
1354 if (ch.updateWLength(totalDuration) < 0) {
1355 ALOGE("%s: Failed to update the waveform length length", __func__);
1356 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1357 }
1358
1359 /* Update nsections */
1360 if (ch.updateNSection(segmentIdx) < 0) {
1361 ALOGE("%s: Failed to update the section count", __func__);
1362 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1363 }
1364
1365 return performEffect(WAVEFORM_MAX_INDEX /*ignored*/, VOLTAGE_SCALE_MAX /*ignored*/, &ch,
1366 callback);
1367 }
1368
isUnderExternalControl()1369 bool Vibrator::isUnderExternalControl() {
1370 return mIsUnderExternalControl;
1371 }
1372
1373 // BnCInterface APIs
1374
dump(int fd,const char ** args,uint32_t numArgs)1375 binder_status_t Vibrator::dump(int fd, const char **args, uint32_t numArgs) {
1376 if (fd < 0) {
1377 ALOGE("Called debug() with invalid fd.");
1378 return STATUS_OK;
1379 }
1380
1381 (void)args;
1382 (void)numArgs;
1383
1384 dprintf(fd, "AIDL:\n");
1385
1386 dprintf(fd, " F0 Offset: base: %" PRIu32 " flip: %" PRIu32 "\n", mF0Offset, mF0OffsetDual);
1387
1388 dprintf(fd, " Voltage Levels:\n");
1389 dprintf(fd, " Tick Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mTickEffectVol[0],
1390 mTickEffectVol[1]);
1391 dprintf(fd, " Click Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mClickEffectVol[0],
1392 mClickEffectVol[1]);
1393 dprintf(fd, " Long Effect Min: %" PRIu32 " Max: %" PRIu32 "\n", mLongEffectVol[0],
1394 mLongEffectVol[1]);
1395
1396 dprintf(fd, " FF effect:\n");
1397 dprintf(fd, " Physical waveform:\n");
1398 dprintf(fd, "==== Base ====\n\tId\tIndex\tt ->\tt'\ttrigger button\n");
1399 uint8_t effectId;
1400 for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1401 dprintf(fd, "\t%d\t%d\t%d\t%d\t%X\n", mFfEffects[effectId].id,
1402 mFfEffects[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1403 mFfEffects[effectId].replay.length, mFfEffects[effectId].trigger.button);
1404 }
1405 if (mIsDual) {
1406 dprintf(fd, "==== Flip ====\n\tId\tIndex\tt ->\tt'\ttrigger button\n");
1407 for (effectId = 0; effectId < WAVEFORM_MAX_PHYSICAL_INDEX; effectId++) {
1408 dprintf(fd, "\t%d\t%d\t%d\t%d\t%X\n", mFfEffectsDual[effectId].id,
1409 mFfEffectsDual[effectId].u.periodic.custom_data[1], mEffectDurations[effectId],
1410 mFfEffectsDual[effectId].replay.length,
1411 mFfEffectsDual[effectId].trigger.button);
1412 }
1413 }
1414
1415 dprintf(fd, "Base: OWT waveform:\n");
1416 dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n");
1417 for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) {
1418 uint32_t numBytes = mFfEffects[effectId].u.periodic.custom_len * 2;
1419 std::stringstream ss;
1420 ss << " ";
1421 for (int i = 0; i < numBytes; i++) {
1422 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1423 << (uint16_t)(*(
1424 reinterpret_cast<uint8_t *>(mFfEffects[effectId].u.periodic.custom_data) +
1425 i))
1426 << " ";
1427 }
1428 dprintf(fd, "\t%d\t%d\t{%s}\t%u\t%X\n", mFfEffects[effectId].id, numBytes, ss.str().c_str(),
1429 mFfEffectsDual[effectId].replay.length, mFfEffects[effectId].trigger.button);
1430 }
1431 if (mIsDual) {
1432 dprintf(fd, "Flip: OWT waveform:\n");
1433 dprintf(fd, "\tId\tBytes\tData\tt\ttrigger button\n");
1434 for (effectId = WAVEFORM_MAX_PHYSICAL_INDEX; effectId < WAVEFORM_MAX_INDEX; effectId++) {
1435 uint32_t numBytes = mFfEffectsDual[effectId].u.periodic.custom_len * 2;
1436 std::stringstream ss;
1437 ss << " ";
1438 for (int i = 0; i < numBytes; i++) {
1439 ss << std::uppercase << std::setfill('0') << std::setw(2) << std::hex
1440 << (uint16_t)(*(reinterpret_cast<uint8_t *>(
1441 mFfEffectsDual[effectId].u.periodic.custom_data) +
1442 i))
1443 << " ";
1444 }
1445 dprintf(fd, "\t%d\t%d\t{%s}\t%u\t%X\n", mFfEffectsDual[effectId].id, numBytes,
1446 ss.str().c_str(), mFfEffectsDual[effectId].replay.length,
1447 mFfEffectsDual[effectId].trigger.button);
1448 }
1449 }
1450 dprintf(fd, "\n");
1451 dprintf(fd, "\n");
1452
1453 mHwApiDef->debug(fd);
1454
1455 dprintf(fd, "\n");
1456
1457 mHwCalDef->debug(fd);
1458
1459 if (mIsDual) {
1460 mHwApiDual->debug(fd);
1461 dprintf(fd, "\n");
1462 mHwCalDual->debug(fd);
1463 }
1464
1465 fsync(fd);
1466 return STATUS_OK;
1467 }
1468
hasHapticAlsaDevice()1469 bool Vibrator::hasHapticAlsaDevice() {
1470 // We need to call findHapticAlsaDevice once only. Calling in the
1471 // constructor is too early in the boot process and the pcm file contents
1472 // are empty. Hence we make the call here once only right before we need to.
1473 if (!mConfigHapticAlsaDeviceDone) {
1474 if (mHwApiDef->getHapticAlsaDevice(&mCard, &mDevice)) {
1475 mHasHapticAlsaDevice = true;
1476 mConfigHapticAlsaDeviceDone = true;
1477 } else {
1478 ALOGE("Haptic ALSA device not supported");
1479 }
1480 } else {
1481 ALOGD("Haptic ALSA device configuration done.");
1482 }
1483 return mHasHapticAlsaDevice;
1484 }
1485
getSimpleDetails(Effect effect,EffectStrength strength,uint32_t * outEffectIndex,uint32_t * outTimeMs,uint32_t * outVolLevel)1486 ndk::ScopedAStatus Vibrator::getSimpleDetails(Effect effect, EffectStrength strength,
1487 uint32_t *outEffectIndex, uint32_t *outTimeMs,
1488 uint32_t *outVolLevel) {
1489 uint32_t effectIndex;
1490 uint32_t timeMs;
1491 float intensity;
1492 uint32_t volLevel;
1493 switch (strength) {
1494 case EffectStrength::LIGHT:
1495 intensity = 0.5f;
1496 break;
1497 case EffectStrength::MEDIUM:
1498 intensity = 0.7f;
1499 break;
1500 case EffectStrength::STRONG:
1501 intensity = 1.0f;
1502 break;
1503 default:
1504 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1505 }
1506
1507 switch (effect) {
1508 case Effect::TEXTURE_TICK:
1509 effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1510 intensity *= 0.5f;
1511 break;
1512 case Effect::TICK:
1513 effectIndex = WAVEFORM_CLICK_INDEX;
1514 intensity *= 0.5f;
1515 break;
1516 case Effect::CLICK:
1517 effectIndex = WAVEFORM_CLICK_INDEX;
1518 intensity *= 0.7f;
1519 break;
1520 case Effect::HEAVY_CLICK:
1521 effectIndex = WAVEFORM_CLICK_INDEX;
1522 intensity *= 1.0f;
1523 // WAVEFORM_CLICK_INDEX is 2, but the primitive CLICK index is 1.
1524 if (intensity > mPrimitiveMaxScale[WAVEFORM_CLICK_INDEX - 1]) {
1525 intensity = mPrimitiveMaxScale[WAVEFORM_CLICK_INDEX - 1];
1526 }
1527 break;
1528 default:
1529 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1530 }
1531
1532 volLevel = intensityToVolLevel(intensity, effectIndex);
1533 timeMs = mEffectDurations[effectIndex] + MAX_COLD_START_LATENCY_MS;
1534
1535 *outEffectIndex = effectIndex;
1536 *outTimeMs = timeMs;
1537 *outVolLevel = volLevel;
1538 return ndk::ScopedAStatus::ok();
1539 }
1540
getCompoundDetails(Effect effect,EffectStrength strength,uint32_t * outTimeMs,DspMemChunk * outCh)1541 ndk::ScopedAStatus Vibrator::getCompoundDetails(Effect effect, EffectStrength strength,
1542 uint32_t *outTimeMs, DspMemChunk *outCh) {
1543 ndk::ScopedAStatus status;
1544 uint32_t timeMs = 0;
1545 uint32_t thisEffectIndex;
1546 uint32_t thisTimeMs;
1547 uint32_t thisVolLevel;
1548 switch (effect) {
1549 case Effect::DOUBLE_CLICK:
1550 status = getSimpleDetails(Effect::CLICK, strength, &thisEffectIndex, &thisTimeMs,
1551 &thisVolLevel);
1552 if (!status.isOk()) {
1553 return status;
1554 }
1555 timeMs += thisTimeMs;
1556 outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1557 WAVEFORM_DOUBLE_CLICK_SILENCE_MS);
1558
1559 timeMs += WAVEFORM_DOUBLE_CLICK_SILENCE_MS + MAX_PAUSE_TIMING_ERROR_MS;
1560
1561 status = getSimpleDetails(Effect::HEAVY_CLICK, strength, &thisEffectIndex, &thisTimeMs,
1562 &thisVolLevel);
1563 if (!status.isOk()) {
1564 return status;
1565 }
1566 timeMs += thisTimeMs;
1567
1568 outCh->constructComposeSegment(thisVolLevel, thisEffectIndex, 0 /*repeat*/, 0 /*flags*/,
1569 0 /*delay*/);
1570 outCh->flush();
1571 if (outCh->updateNSection(2) < 0) {
1572 ALOGE("%s: Failed to update the section count", __func__);
1573 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1574 }
1575
1576 break;
1577 default:
1578 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1579 }
1580
1581 *outTimeMs = timeMs;
1582 // Compositions should have 0 duration
1583 mFfEffects[WAVEFORM_COMPOSE].replay.length = 0;
1584 if (mIsDual) {
1585 mFfEffectsDual[WAVEFORM_COMPOSE].replay.length = 0;
1586 }
1587
1588 return ndk::ScopedAStatus::ok();
1589 }
1590
getPrimitiveDetails(CompositePrimitive primitive,uint32_t * outEffectIndex)1591 ndk::ScopedAStatus Vibrator::getPrimitiveDetails(CompositePrimitive primitive,
1592 uint32_t *outEffectIndex) {
1593 uint32_t effectIndex;
1594 uint32_t primitiveBit = 1 << int32_t(primitive);
1595 if ((primitiveBit & mSupportedPrimitivesBits) == 0x0) {
1596 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1597 }
1598
1599 switch (primitive) {
1600 case CompositePrimitive::NOOP:
1601 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
1602 case CompositePrimitive::CLICK:
1603 effectIndex = WAVEFORM_CLICK_INDEX;
1604 break;
1605 case CompositePrimitive::THUD:
1606 effectIndex = WAVEFORM_THUD_INDEX;
1607 break;
1608 case CompositePrimitive::SPIN:
1609 effectIndex = WAVEFORM_SPIN_INDEX;
1610 break;
1611 case CompositePrimitive::QUICK_RISE:
1612 effectIndex = WAVEFORM_QUICK_RISE_INDEX;
1613 break;
1614 case CompositePrimitive::SLOW_RISE:
1615 effectIndex = WAVEFORM_SLOW_RISE_INDEX;
1616 break;
1617 case CompositePrimitive::QUICK_FALL:
1618 effectIndex = WAVEFORM_QUICK_FALL_INDEX;
1619 break;
1620 case CompositePrimitive::LIGHT_TICK:
1621 effectIndex = WAVEFORM_LIGHT_TICK_INDEX;
1622 break;
1623 case CompositePrimitive::LOW_TICK:
1624 effectIndex = WAVEFORM_LOW_TICK_INDEX;
1625 break;
1626 default:
1627 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1628 }
1629
1630 *outEffectIndex = effectIndex;
1631
1632 return ndk::ScopedAStatus::ok();
1633 }
1634
performEffect(Effect effect,EffectStrength strength,const std::shared_ptr<IVibratorCallback> & callback,int32_t * outTimeMs)1635 ndk::ScopedAStatus Vibrator::performEffect(Effect effect, EffectStrength strength,
1636 const std::shared_ptr<IVibratorCallback> &callback,
1637 int32_t *outTimeMs) {
1638 ndk::ScopedAStatus status;
1639 uint32_t effectIndex;
1640 uint32_t timeMs = 0;
1641 uint32_t volLevel;
1642 std::optional<DspMemChunk> maybeCh;
1643 switch (effect) {
1644 case Effect::TEXTURE_TICK:
1645 // fall-through
1646 case Effect::TICK:
1647 // fall-through
1648 case Effect::CLICK:
1649 // fall-through
1650 case Effect::HEAVY_CLICK:
1651 status = getSimpleDetails(effect, strength, &effectIndex, &timeMs, &volLevel);
1652 break;
1653 case Effect::DOUBLE_CLICK:
1654 maybeCh.emplace(WAVEFORM_COMPOSE, FF_CUSTOM_DATA_LEN_MAX_COMP);
1655 status = getCompoundDetails(effect, strength, &timeMs, &*maybeCh);
1656 volLevel = VOLTAGE_SCALE_MAX;
1657 break;
1658 default:
1659 status = ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
1660 break;
1661 }
1662 if (status.isOk()) {
1663 DspMemChunk *ch = maybeCh ? &*maybeCh : nullptr;
1664 status = performEffect(effectIndex, volLevel, ch, callback);
1665 }
1666
1667 *outTimeMs = timeMs;
1668 return status;
1669 }
1670
performEffect(uint32_t effectIndex,uint32_t volLevel,const DspMemChunk * ch,const std::shared_ptr<IVibratorCallback> & callback)1671 ndk::ScopedAStatus Vibrator::performEffect(uint32_t effectIndex, uint32_t volLevel,
1672 const DspMemChunk *ch,
1673 const std::shared_ptr<IVibratorCallback> &callback) {
1674 setEffectAmplitude(volLevel, VOLTAGE_SCALE_MAX);
1675
1676 return on(MAX_TIME_MS, effectIndex, ch, callback);
1677 }
1678
waitForComplete(std::shared_ptr<IVibratorCallback> && callback)1679 void Vibrator::waitForComplete(std::shared_ptr<IVibratorCallback> &&callback) {
1680 ALOGD("waitForComplete: Callback status in waitForComplete(): callBack: %d",
1681 (callback != nullptr));
1682
1683 // Bypass checking flip part's haptic state
1684 if (!mHwApiDef->pollVibeState(VIBE_STATE_HAPTIC, POLLING_TIMEOUT)) {
1685 ALOGD("Failed to get state \"Haptic\"");
1686 }
1687
1688 mHwApiDef->pollVibeState(VIBE_STATE_STOPPED);
1689 // Check flip's state after base was done
1690 if (mIsDual) {
1691 mHwApiDual->pollVibeState(VIBE_STATE_STOPPED);
1692 }
1693 ALOGD("waitForComplete: get STOP");
1694 {
1695 const std::scoped_lock<std::mutex> lock(mActiveId_mutex);
1696 if (mActiveId >= WAVEFORM_MAX_PHYSICAL_INDEX) {
1697 if (!mHwApiDef->eraseOwtEffect(mInputFd, mActiveId, &mFfEffects)) {
1698 ALOGE("Failed to clean up the composed effect %d", mActiveId);
1699 }
1700 if (mIsDual &&
1701 (!mHwApiDual->eraseOwtEffect(mInputFdDual, mActiveId, &mFfEffectsDual))) {
1702 ALOGE("Failed to clean up flip's composed effect %d", mActiveId);
1703 }
1704 } else {
1705 ALOGD("waitForComplete: Vibrator is already off");
1706 }
1707 mActiveId = -1;
1708 if (mGPIOStatus && !mHwGPIO->setGPIOOutput(false)) {
1709 ALOGE("waitForComplete: Failed to reset GPIO(%d): %s", errno, strerror(errno));
1710 }
1711 // Do waveform number checking
1712 uint32_t effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1713 mHwApiDef->getEffectCount(&effectCount);
1714 if (effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) {
1715 // Forcibly clean all OWT waveforms
1716 if (!mHwApiDef->eraseOwtEffect(mInputFd, WAVEFORM_MAX_INDEX, &mFfEffects)) {
1717 ALOGE("Failed to clean up all base's composed effect");
1718 }
1719 }
1720
1721 if (mIsDual) {
1722 // Forcibly clean all OWT waveforms
1723 effectCount = WAVEFORM_MAX_PHYSICAL_INDEX;
1724 mHwApiDual->getEffectCount(&effectCount);
1725 if ((effectCount > WAVEFORM_MAX_PHYSICAL_INDEX) &&
1726 (!mHwApiDual->eraseOwtEffect(mInputFdDual, WAVEFORM_MAX_INDEX, &mFfEffectsDual))) {
1727 ALOGE("Failed to clean up all flip's composed effect");
1728 }
1729 }
1730 }
1731
1732 if (callback) {
1733 auto ret = callback->onComplete();
1734 if (!ret.isOk()) {
1735 ALOGE("Failed completion callback: %d", ret.getExceptionCode());
1736 }
1737 }
1738 ALOGD("waitForComplete: Done.");
1739 }
1740
intensityToVolLevel(float intensity,uint32_t effectIndex)1741 uint32_t Vibrator::intensityToVolLevel(float intensity, uint32_t effectIndex) {
1742 uint32_t volLevel;
1743 auto calc = [](float intst, std::array<uint32_t, 2> v) -> uint32_t {
1744 return std::lround(intst * (v[1] - v[0])) + v[0];
1745 };
1746
1747 switch (effectIndex) {
1748 case WAVEFORM_LIGHT_TICK_INDEX:
1749 volLevel = calc(intensity, mTickEffectVol);
1750 break;
1751 case WAVEFORM_QUICK_RISE_INDEX:
1752 // fall-through
1753 case WAVEFORM_QUICK_FALL_INDEX:
1754 volLevel = calc(intensity, mLongEffectVol);
1755 break;
1756 case WAVEFORM_CLICK_INDEX:
1757 // fall-through
1758 case WAVEFORM_THUD_INDEX:
1759 // fall-through
1760 case WAVEFORM_SPIN_INDEX:
1761 // fall-through
1762 case WAVEFORM_SLOW_RISE_INDEX:
1763 // fall-through
1764 default:
1765 volLevel = calc(intensity, mClickEffectVol);
1766 break;
1767 }
1768 return volLevel;
1769 }
1770
1771 } // namespace vibrator
1772 } // namespace hardware
1773 } // namespace android
1774 } // namespace aidl
1775