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 #pragma once
17 
18 #include <algorithm>
19 #include <cmath>
20 
21 #include "HardwareBase.h"
22 #include "Vibrator.h"
23 
24 #define PROC_SND_PCM "/proc/asound/pcm"
25 #define HAPTIC_PCM_DEVICE_SYMBOL "haptic nohost playback"
26 
27 static struct pcm_config haptic_nohost_config = {
28         .channels = 1,
29         .rate = 48000,
30         .period_size = 80,
31         .period_count = 2,
32         .format = PCM_FORMAT_S16_LE,
33 };
34 
35 enum WaveformIndex : uint16_t {
36     /* Physical waveform */
37     WAVEFORM_LONG_VIBRATION_EFFECT_INDEX = 0,
38     WAVEFORM_RESERVED_INDEX_1 = 1,
39     WAVEFORM_CLICK_INDEX = 2,
40     WAVEFORM_SHORT_VIBRATION_EFFECT_INDEX = 3,
41     WAVEFORM_THUD_INDEX = 4,
42     WAVEFORM_SPIN_INDEX = 5,
43     WAVEFORM_QUICK_RISE_INDEX = 6,
44     WAVEFORM_SLOW_RISE_INDEX = 7,
45     WAVEFORM_QUICK_FALL_INDEX = 8,
46     WAVEFORM_LIGHT_TICK_INDEX = 9,
47     WAVEFORM_LOW_TICK_INDEX = 10,
48     WAVEFORM_RESERVED_MFG_1,
49     WAVEFORM_RESERVED_MFG_2,
50     WAVEFORM_RESERVED_MFG_3,
51     WAVEFORM_MAX_PHYSICAL_INDEX,
52     /* OWT waveform */
53     WAVEFORM_COMPOSE = WAVEFORM_MAX_PHYSICAL_INDEX,
54     WAVEFORM_PWLE,
55     /*
56      * Refer to <linux/input.h>, the WAVEFORM_MAX_INDEX must not exceed 96.
57      * #define FF_GAIN          0x60  // 96 in decimal
58      * #define FF_MAX_EFFECTS   FF_GAIN
59      */
60     WAVEFORM_MAX_INDEX,
61 };
62 
63 namespace aidl {
64 namespace android {
65 namespace hardware {
66 namespace vibrator {
67 
68 class HwApi : public Vibrator::HwApi, private HwApiBase {
69   public:
Create()70     static std::unique_ptr<HwApi> Create() {
71         auto hwapi = std::unique_ptr<HwApi>(new HwApi());
72         return hwapi;
73     }
HwApi()74     HwApi() {
75         open("calibration/f0_stored", &mF0);
76         open("default/f0_offset", &mF0Offset);
77         open("calibration/redc_stored", &mRedc);
78         open("calibration/q_stored", &mQ);
79         open("default/vibe_state", &mVibeState);
80         open("default/num_waves", &mEffectCount);
81         open("default/owt_free_space", &mOwtFreeSpace);
82         open("default/f0_comp_enable", &mF0CompEnable);
83         open("default/redc_comp_enable", &mRedcCompEnable);
84         open("default/delay_before_stop_playback_us", &mMinOnOffInterval);
85     }
86 
setF0(std::string value)87     bool setF0(std::string value) override { return set(value, &mF0); }
setF0Offset(uint32_t value)88     bool setF0Offset(uint32_t value) override { return set(value, &mF0Offset); }
setRedc(std::string value)89     bool setRedc(std::string value) override { return set(value, &mRedc); }
setQ(std::string value)90     bool setQ(std::string value) override { return set(value, &mQ); }
getEffectCount(uint32_t * value)91     bool getEffectCount(uint32_t *value) override { return get(value, &mEffectCount); }
pollVibeState(uint32_t value,int32_t timeoutMs)92     bool pollVibeState(uint32_t value, int32_t timeoutMs) override {
93         return poll(value, &mVibeState, timeoutMs);
94     }
hasOwtFreeSpace()95     bool hasOwtFreeSpace() override { return has(mOwtFreeSpace); }
getOwtFreeSpace(uint32_t * value)96     bool getOwtFreeSpace(uint32_t *value) override { return get(value, &mOwtFreeSpace); }
setF0CompEnable(bool value)97     bool setF0CompEnable(bool value) override { return set(value, &mF0CompEnable); }
setRedcCompEnable(bool value)98     bool setRedcCompEnable(bool value) override { return set(value, &mRedcCompEnable); }
setMinOnOffInterval(uint32_t value)99     bool setMinOnOffInterval(uint32_t value) override { return set(value, &mMinOnOffInterval); }
100     // TODO(b/234338136): Need to add the force feedback HW API test cases
setFFGain(int fd,uint16_t value)101     bool setFFGain(int fd, uint16_t value) override {
102         struct input_event gain = {
103                 .type = EV_FF,
104                 .code = FF_GAIN,
105                 .value = value,
106         };
107         if (value > 100) {
108             ALOGE("Invalid gain");
109             return false;
110         }
111         if (write(fd, (const void *)&gain, sizeof(gain)) != sizeof(gain)) {
112             return false;
113         }
114         return true;
115     }
setFFEffect(int fd,struct ff_effect * effect,uint16_t timeoutMs)116     bool setFFEffect(int fd, struct ff_effect *effect, uint16_t timeoutMs) override {
117         if (effect == nullptr) {
118             ALOGE("Invalid ff_effect");
119             return false;
120         }
121         if (ioctl(fd, EVIOCSFF, effect) < 0) {
122             ALOGE("setFFEffect fail");
123             return false;
124         }
125         return true;
126     }
setFFPlay(int fd,int8_t index,bool value)127     bool setFFPlay(int fd, int8_t index, bool value) override {
128         struct input_event play = {
129                 .type = EV_FF,
130                 .code = static_cast<uint16_t>(index),
131                 .value = value,
132         };
133         if (write(fd, (const void *)&play, sizeof(play)) != sizeof(play)) {
134             return false;
135         } else {
136             return true;
137         }
138     }
getHapticAlsaDevice(int * card,int * device)139     bool getHapticAlsaDevice(int *card, int *device) override {
140         std::string line;
141         std::ifstream myfile(PROC_SND_PCM);
142         if (myfile.is_open()) {
143             while (getline(myfile, line)) {
144                 if (line.find(HAPTIC_PCM_DEVICE_SYMBOL) != std::string::npos) {
145                     std::stringstream ss(line);
146                     std::string currentToken;
147                     std::getline(ss, currentToken, ':');
148                     sscanf(currentToken.c_str(), "%d-%d", card, device);
149                     return true;
150                 }
151             }
152             myfile.close();
153         } else {
154             ALOGE("Failed to read file: %s", PROC_SND_PCM);
155         }
156         return false;
157     }
setHapticPcmAmp(struct pcm ** haptic_pcm,bool enable,int card,int device)158     bool setHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) override {
159         int ret = 0;
160 
161         if (enable) {
162             *haptic_pcm = pcm_open(card, device, PCM_OUT, &haptic_nohost_config);
163             if (!pcm_is_ready(*haptic_pcm)) {
164                 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(*haptic_pcm));
165                 goto fail;
166             }
167 
168             ret = pcm_prepare(*haptic_pcm);
169             if (ret < 0) {
170                 ALOGE("cannot prepare haptic_pcm: %s", pcm_get_error(*haptic_pcm));
171                 goto fail;
172             }
173 
174             ret = pcm_start(*haptic_pcm);
175             if (ret < 0) {
176                 ALOGE("cannot start haptic_pcm: %s", pcm_get_error(*haptic_pcm));
177                 goto fail;
178             }
179 
180             return true;
181         } else {
182             if (*haptic_pcm) {
183                 pcm_close(*haptic_pcm);
184                 *haptic_pcm = NULL;
185             }
186             return true;
187         }
188 
189     fail:
190         pcm_close(*haptic_pcm);
191         *haptic_pcm = NULL;
192         return false;
193     }
uploadOwtEffect(int fd,const uint8_t * owtData,const uint32_t numBytes,struct ff_effect * effect,uint32_t * outEffectIndex,int * status)194     bool uploadOwtEffect(int fd, const uint8_t *owtData, const uint32_t numBytes, struct ff_effect *effect,
195                          uint32_t *outEffectIndex, int *status) override {
196         if (owtData == nullptr || effect == nullptr || outEffectIndex == nullptr) {
197             ALOGE("Invalid argument owtData, ff_effect or outEffectIndex");
198             *status = EX_NULL_POINTER;
199             return false;
200         }
201         if (status == nullptr) {
202             ALOGE("Invalid argument status");
203             return false;
204         }
205 
206         (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t);
207         memcpy((*effect).u.periodic.custom_data, owtData, numBytes);
208 
209         if ((*effect).id != -1) {
210             ALOGE("(*effect).id != -1");
211         }
212 
213         /* Create a new OWT waveform to update the PWLE or composite effect. */
214         (*effect).id = -1;
215         if (ioctl(fd, EVIOCSFF, effect) < 0) {
216             ALOGE("Failed to upload effect %d (%d): %s", *outEffectIndex, errno, strerror(errno));
217             *status = EX_ILLEGAL_STATE;
218             return false;
219         }
220 
221         if ((*effect).id >= FF_MAX_EFFECTS || (*effect).id < 0) {
222             ALOGE("Invalid waveform index after upload OWT effect: %d", (*effect).id);
223             *status = EX_ILLEGAL_ARGUMENT;
224             return false;
225         }
226         *outEffectIndex = (*effect).id;
227         *status = 0;
228         return true;
229     }
eraseOwtEffect(int fd,int8_t effectIndex,std::vector<ff_effect> * effect)230     bool eraseOwtEffect(int fd, int8_t effectIndex, std::vector<ff_effect> *effect) override {
231         uint32_t effectCountBefore, effectCountAfter, i, successFlush = 0;
232 
233         if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
234             ALOGE("Invalid waveform index for OWT erase: %d", effectIndex);
235             return false;
236         }
237         if (effect == nullptr || (*effect).empty()) {
238             ALOGE("Invalid argument effect");
239             return false;
240         }
241         // Turn off the waiting time for SVC init phase to complete since chip
242         // should already under STOP state
243         setMinOnOffInterval(0);
244         // Do erase flow
245         if (effectIndex < WAVEFORM_MAX_INDEX) {
246             /* Normal situation. Only erase the effect which we just played. */
247             if (ioctl(fd, EVIOCRMFF, effectIndex) < 0) {
248                 ALOGE("Failed to erase effect %d (%d): %s", effectIndex, errno, strerror(errno));
249             }
250             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
251                 if ((*effect)[i].id == effectIndex) {
252                     (*effect)[i].id = -1;
253                     break;
254                 }
255             }
256         } else {
257             /* Flush all non-prestored effects of ff-core and driver. */
258             getEffectCount(&effectCountBefore);
259             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < FF_MAX_EFFECTS; i++) {
260                 if (ioctl(fd, EVIOCRMFF, i) >= 0) {
261                     successFlush++;
262                 }
263             }
264             getEffectCount(&effectCountAfter);
265             ALOGW("Flushed effects: ff: %d; driver: %d -> %d; success: %d", effectIndex,
266                   effectCountBefore, effectCountAfter, successFlush);
267             /* Reset all OWT effect index of HAL. */
268             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
269                 (*effect)[i].id = -1;
270             }
271         }
272         // Turn on the waiting time for SVC init phase to complete
273         setMinOnOffInterval(Vibrator::MIN_ON_OFF_INTERVAL_US);
274         return true;
275     }
276 
debug(int fd)277     void debug(int fd) override { HwApiBase::debug(fd); }
278 
279   private:
280     std::ofstream mF0;
281     std::ofstream mF0Offset;
282     std::ofstream mRedc;
283     std::ofstream mQ;
284     std::ifstream mEffectCount;
285     std::ifstream mVibeState;
286     std::ifstream mOwtFreeSpace;
287     std::ofstream mF0CompEnable;
288     std::ofstream mRedcCompEnable;
289     std::ofstream mMinOnOffInterval;
290 };
291 
292 class HwCal : public Vibrator::HwCal, private HwCalBase {
293   private:
294     static constexpr char VERSION[] = "version";
295     static constexpr char F0_CONFIG[] = "f0_measured";
296     static constexpr char F0_CONFIG_DUAL[] = "f0_measured_dual";
297     static constexpr char REDC_CONFIG[] = "redc_measured";
298     static constexpr char Q_CONFIG[] = "q_measured";
299     static constexpr char TICK_VOLTAGES_CONFIG[] = "v_tick";
300     static constexpr char CLICK_VOLTAGES_CONFIG[] = "v_click";
301     static constexpr char LONG_VOLTAGES_CONFIG[] = "v_long";
302 
303     static constexpr uint32_t VERSION_DEFAULT = 2;
304     static constexpr int32_t DEFAULT_FREQUENCY_SHIFT = 0;
305     static constexpr std::array<uint32_t, 2> V_TICK_DEFAULT = {1, 100};
306     static constexpr std::array<uint32_t, 2> V_CLICK_DEFAULT = {1, 100};
307     static constexpr std::array<uint32_t, 2> V_LONG_DEFAULT = {1, 100};
308 
309   public:
HwCal()310     HwCal() {}
Create()311     static std::unique_ptr<HwCal> Create() {
312         auto hwcal = std::unique_ptr<HwCal>(new HwCal());
313         return hwcal;
314     }
315 
getVersion(uint32_t * value)316     bool getVersion(uint32_t *value) override {
317         if (getPersist(VERSION, value)) {
318             return true;
319         }
320         *value = VERSION_DEFAULT;
321         return true;
322     }
getLongFrequencyShift(int32_t * value)323     bool getLongFrequencyShift(int32_t *value) override {
324         return getProperty("long.frequency.shift", value, DEFAULT_FREQUENCY_SHIFT);
325     }
getF0(std::string * value)326     bool getF0(std::string *value) override { return getPersist(F0_CONFIG, value); }
getF0SyncOffset(uint32_t * value)327     bool getF0SyncOffset(uint32_t *value) override {
328         std::string cal_0{8, '0'};
329         std::string cal_1{8, '0'};
330 
331         if (getPersist(F0_CONFIG, &cal_0) && getPersist(F0_CONFIG_DUAL, &cal_1)) {
332             float f0_0 = static_cast<float>(std::stoul(cal_0, nullptr, 16)) / (1 << 14);
333             float f0_1 = static_cast<float>(std::stoul(cal_1, nullptr, 16)) / (1 << 14);
334             float f0_offset = std::abs(f0_0 - f0_1)/2;
335 
336             if (f0_0 < f0_1) {
337                 *value = static_cast<uint32_t>(f0_offset * std::pow(2, 14));
338             } else if (f0_0 > f0_1) {
339                 *value = static_cast<uint32_t>(std::pow(2, 24) - std::abs(f0_offset) * std::pow(2, 14));
340             } else {
341                 *value = 0;
342             }
343 
344             return true;
345         } else {
346             ALOGE("Vibrator: Unable to load F0_CONFIG or F0_CONFIG_DUAL config");
347             *value = 0;
348             return false;
349         }
350     }
getRedc(std::string * value)351     bool getRedc(std::string *value) override { return getPersist(REDC_CONFIG, value); }
getQ(std::string * value)352     bool getQ(std::string *value) override { return getPersist(Q_CONFIG, value); }
getTickVolLevels(std::array<uint32_t,2> * value)353     bool getTickVolLevels(std::array<uint32_t, 2> *value) override {
354         if (getPersist(TICK_VOLTAGES_CONFIG, value)) {
355             return true;
356         }
357         *value = V_TICK_DEFAULT;
358         return true;
359     }
getClickVolLevels(std::array<uint32_t,2> * value)360     bool getClickVolLevels(std::array<uint32_t, 2> *value) override {
361         if (getPersist(CLICK_VOLTAGES_CONFIG, value)) {
362             return true;
363         }
364         *value = V_CLICK_DEFAULT;
365         return true;
366     }
getLongVolLevels(std::array<uint32_t,2> * value)367     bool getLongVolLevels(std::array<uint32_t, 2> *value) override {
368         if (getPersist(LONG_VOLTAGES_CONFIG, value)) {
369             return true;
370         }
371         *value = V_LONG_DEFAULT;
372         return true;
373     }
isChirpEnabled()374     bool isChirpEnabled() override {
375         return utils::getProperty("persist.vendor.vibrator.hal.chirp.enabled", false);
376     }
getSupportedPrimitives(uint32_t * value)377     bool getSupportedPrimitives(uint32_t *value) override {
378         return getProperty("supported_primitives", value, (uint32_t)0);
379     }
isF0CompEnabled()380     bool isF0CompEnabled() override {
381         bool value;
382         getProperty("f0.comp.enabled", &value, true);
383         return value;
384     }
isRedcCompEnabled()385     bool isRedcCompEnabled() override {
386         bool value;
387         getProperty("redc.comp.enabled", &value, false);
388         return value;
389     }
debug(int fd)390     void debug(int fd) override { HwCalBase::debug(fd); }
391 };
392 
393 }  // namespace vibrator
394 }  // namespace hardware
395 }  // namespace android
396 }  // namespace aidl
397