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