• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (write(fd, (const void *)&gain, sizeof(gain)) != sizeof(gain)) {
108             return false;
109         }
110         return true;
111     }
setFFEffect(int fd,struct ff_effect * effect,uint16_t timeoutMs)112     bool setFFEffect(int fd, struct ff_effect *effect, uint16_t timeoutMs) override {
113         if (((*effect).replay.length != timeoutMs) || (ioctl(fd, EVIOCSFF, effect) < 0)) {
114             ALOGE("setFFEffect fail");
115             return false;
116         } else {
117             return true;
118         }
119     }
setFFPlay(int fd,int8_t index,bool value)120     bool setFFPlay(int fd, int8_t index, bool value) override {
121         struct input_event play = {
122                 .type = EV_FF,
123                 .code = static_cast<uint16_t>(index),
124                 .value = value,
125         };
126         if (write(fd, (const void *)&play, sizeof(play)) != sizeof(play)) {
127             return false;
128         } else {
129             return true;
130         }
131     }
getHapticAlsaDevice(int * card,int * device)132     bool getHapticAlsaDevice(int *card, int *device) override {
133         std::string line;
134         std::ifstream myfile(PROC_SND_PCM);
135         if (myfile.is_open()) {
136             while (getline(myfile, line)) {
137                 if (line.find(HAPTIC_PCM_DEVICE_SYMBOL) != std::string::npos) {
138                     std::stringstream ss(line);
139                     std::string currentToken;
140                     std::getline(ss, currentToken, ':');
141                     sscanf(currentToken.c_str(), "%d-%d", card, device);
142                     return true;
143                 }
144             }
145             myfile.close();
146         } else {
147             ALOGE("Failed to read file: %s", PROC_SND_PCM);
148         }
149         return false;
150     }
setHapticPcmAmp(struct pcm ** haptic_pcm,bool enable,int card,int device)151     bool setHapticPcmAmp(struct pcm **haptic_pcm, bool enable, int card, int device) override {
152         int ret = 0;
153 
154         if (enable) {
155             *haptic_pcm = pcm_open(card, device, PCM_OUT, &haptic_nohost_config);
156             if (!pcm_is_ready(*haptic_pcm)) {
157                 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(*haptic_pcm));
158                 goto fail;
159             }
160 
161             ret = pcm_prepare(*haptic_pcm);
162             if (ret < 0) {
163                 ALOGE("cannot prepare haptic_pcm: %s", pcm_get_error(*haptic_pcm));
164                 goto fail;
165             }
166 
167             ret = pcm_start(*haptic_pcm);
168             if (ret < 0) {
169                 ALOGE("cannot start haptic_pcm: %s", pcm_get_error(*haptic_pcm));
170                 goto fail;
171             }
172 
173             return true;
174         } else {
175             if (*haptic_pcm) {
176                 pcm_close(*haptic_pcm);
177                 *haptic_pcm = NULL;
178             }
179             return true;
180         }
181 
182     fail:
183         pcm_close(*haptic_pcm);
184         *haptic_pcm = NULL;
185         return false;
186     }
uploadOwtEffect(int fd,uint8_t * owtData,uint32_t numBytes,struct ff_effect * effect,uint32_t * outEffectIndex,int * status)187     bool uploadOwtEffect(int fd, uint8_t *owtData, uint32_t numBytes, struct ff_effect *effect,
188                          uint32_t *outEffectIndex, int *status) override {
189         (*effect).u.periodic.custom_len = numBytes / sizeof(uint16_t);
190         delete[] ((*effect).u.periodic.custom_data);
191         (*effect).u.periodic.custom_data = new int16_t[(*effect).u.periodic.custom_len]{0x0000};
192         if ((*effect).u.periodic.custom_data == nullptr) {
193             ALOGE("Failed to allocate memory for custom data\n");
194             *status = EX_NULL_POINTER;
195             return false;
196         }
197         memcpy((*effect).u.periodic.custom_data, owtData, numBytes);
198 
199         if ((*effect).id != -1) {
200             ALOGE("(*effect).id != -1");
201         }
202 
203         /* Create a new OWT waveform to update the PWLE or composite effect. */
204         (*effect).id = -1;
205         if (ioctl(fd, EVIOCSFF, effect) < 0) {
206             ALOGE("Failed to upload effect %d (%d): %s", *outEffectIndex, errno, strerror(errno));
207             delete[] ((*effect).u.periodic.custom_data);
208             *status = EX_ILLEGAL_STATE;
209             return false;
210         }
211 
212         if ((*effect).id >= FF_MAX_EFFECTS || (*effect).id < 0) {
213             ALOGE("Invalid waveform index after upload OWT effect: %d", (*effect).id);
214             *status = EX_ILLEGAL_ARGUMENT;
215             return false;
216         }
217         *outEffectIndex = (*effect).id;
218         *status = 0;
219         return true;
220     }
eraseOwtEffect(int fd,int8_t effectIndex,std::vector<ff_effect> * effect)221     bool eraseOwtEffect(int fd, int8_t effectIndex, std::vector<ff_effect> *effect) override {
222         uint32_t effectCountBefore, effectCountAfter, i, successFlush = 0;
223 
224         if (effectIndex < WAVEFORM_MAX_PHYSICAL_INDEX) {
225             ALOGE("Invalid waveform index for OWT erase: %d", effectIndex);
226             return false;
227         }
228         // Turn off the waiting time for SVC init phase to complete since chip
229         // should already under STOP state
230         setMinOnOffInterval(0);
231         // Do erase flow
232         if (effectIndex < WAVEFORM_MAX_INDEX) {
233             /* Normal situation. Only erase the effect which we just played. */
234             if (ioctl(fd, EVIOCRMFF, effectIndex) < 0) {
235                 ALOGE("Failed to erase effect %d (%d): %s", effectIndex, errno, strerror(errno));
236             }
237             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
238                 if ((*effect)[i].id == effectIndex) {
239                     (*effect)[i].id = -1;
240                     break;
241                 }
242             }
243         } else {
244             /* Flush all non-prestored effects of ff-core and driver. */
245             getEffectCount(&effectCountBefore);
246             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < FF_MAX_EFFECTS; i++) {
247                 if (ioctl(fd, EVIOCRMFF, i) >= 0) {
248                     successFlush++;
249                 }
250             }
251             getEffectCount(&effectCountAfter);
252             ALOGW("Flushed effects: ff: %d; driver: %d -> %d; success: %d", effectIndex,
253                   effectCountBefore, effectCountAfter, successFlush);
254             /* Reset all OWT effect index of HAL. */
255             for (i = WAVEFORM_MAX_PHYSICAL_INDEX; i < WAVEFORM_MAX_INDEX; i++) {
256                 (*effect)[i].id = -1;
257             }
258         }
259         // Turn on the waiting time for SVC init phase to complete
260         setMinOnOffInterval(Vibrator::MIN_ON_OFF_INTERVAL_US);
261         return true;
262     }
263 
debug(int fd)264     void debug(int fd) override { HwApiBase::debug(fd); }
265 
266   private:
267     std::ofstream mF0;
268     std::ofstream mF0Offset;
269     std::ofstream mRedc;
270     std::ofstream mQ;
271     std::ifstream mEffectCount;
272     std::ifstream mVibeState;
273     std::ifstream mOwtFreeSpace;
274     std::ofstream mF0CompEnable;
275     std::ofstream mRedcCompEnable;
276     std::ofstream mMinOnOffInterval;
277 };
278 
279 class HwCal : public Vibrator::HwCal, private HwCalBase {
280   private:
281     static constexpr char VERSION[] = "version";
282     static constexpr char F0_CONFIG[] = "f0_measured";
283     static constexpr char F0_CONFIG_DUAL[] = "f0_measured_dual";
284     static constexpr char REDC_CONFIG[] = "redc_measured";
285     static constexpr char Q_CONFIG[] = "q_measured";
286     static constexpr char TICK_VOLTAGES_CONFIG[] = "v_tick";
287     static constexpr char CLICK_VOLTAGES_CONFIG[] = "v_click";
288     static constexpr char LONG_VOLTAGES_CONFIG[] = "v_long";
289 
290     static constexpr uint32_t VERSION_DEFAULT = 2;
291     static constexpr int32_t DEFAULT_FREQUENCY_SHIFT = 0;
292     static constexpr std::array<uint32_t, 2> V_TICK_DEFAULT = {1, 100};
293     static constexpr std::array<uint32_t, 2> V_CLICK_DEFAULT = {1, 100};
294     static constexpr std::array<uint32_t, 2> V_LONG_DEFAULT = {1, 100};
295 
296   public:
HwCal()297     HwCal() {}
Create()298     static std::unique_ptr<HwCal> Create() {
299         auto hwcal = std::unique_ptr<HwCal>(new HwCal());
300         return hwcal;
301     }
302 
getVersion(uint32_t * value)303     bool getVersion(uint32_t *value) override {
304         if (getPersist(VERSION, value)) {
305             return true;
306         }
307         *value = VERSION_DEFAULT;
308         return true;
309     }
getLongFrequencyShift(int32_t * value)310     bool getLongFrequencyShift(int32_t *value) override {
311         return getProperty("long.frequency.shift", value, DEFAULT_FREQUENCY_SHIFT);
312     }
getF0(std::string * value)313     bool getF0(std::string *value) override { return getPersist(F0_CONFIG, value); }
getF0SyncOffset(uint32_t * value)314     bool getF0SyncOffset(uint32_t *value) override {
315         std::string cal_0{8, '0'};
316         std::string cal_1{8, '0'};
317 
318         if (getPersist(F0_CONFIG, &cal_0) && getPersist(F0_CONFIG_DUAL, &cal_1)) {
319             float f0_0 = static_cast<float>(std::stoul(cal_0, nullptr, 16)) / (1 << 14);
320             float f0_1 = static_cast<float>(std::stoul(cal_1, nullptr, 16)) / (1 << 14);
321             float f0_offset = std::abs(f0_0 - f0_1)/2;
322 
323             if (f0_0 < f0_1) {
324                 *value = static_cast<uint32_t>(f0_offset * std::pow(2, 14));
325             } else if (f0_0 > f0_1) {
326                 *value = static_cast<uint32_t>(std::pow(2, 24) - std::abs(f0_offset) * std::pow(2, 14));
327             } else {
328                 *value = 0;
329             }
330 
331             return true;
332         } else {
333             ALOGE("Vibrator: Unable to load F0_CONFIG or F0_CONFIG_DUAL config");
334             *value = 0;
335             return false;
336         }
337     }
getRedc(std::string * value)338     bool getRedc(std::string *value) override { return getPersist(REDC_CONFIG, value); }
getQ(std::string * value)339     bool getQ(std::string *value) override { return getPersist(Q_CONFIG, value); }
getTickVolLevels(std::array<uint32_t,2> * value)340     bool getTickVolLevels(std::array<uint32_t, 2> *value) override {
341         if (getPersist(TICK_VOLTAGES_CONFIG, value)) {
342             return true;
343         }
344         *value = V_TICK_DEFAULT;
345         return true;
346     }
getClickVolLevels(std::array<uint32_t,2> * value)347     bool getClickVolLevels(std::array<uint32_t, 2> *value) override {
348         if (getPersist(CLICK_VOLTAGES_CONFIG, value)) {
349             return true;
350         }
351         *value = V_CLICK_DEFAULT;
352         return true;
353     }
getLongVolLevels(std::array<uint32_t,2> * value)354     bool getLongVolLevels(std::array<uint32_t, 2> *value) override {
355         if (getPersist(LONG_VOLTAGES_CONFIG, value)) {
356             return true;
357         }
358         *value = V_LONG_DEFAULT;
359         return true;
360     }
isChirpEnabled()361     bool isChirpEnabled() override {
362         bool value;
363         getProperty("chirp.enabled", &value, false);
364         return value;
365     }
getSupportedPrimitives(uint32_t * value)366     bool getSupportedPrimitives(uint32_t *value) override {
367         return getProperty("supported_primitives", value, (uint32_t)0);
368     }
isF0CompEnabled()369     bool isF0CompEnabled() override {
370         bool value;
371         getProperty("f0.comp.enabled", &value, true);
372         return value;
373     }
isRedcCompEnabled()374     bool isRedcCompEnabled() override {
375         bool value;
376         getProperty("redc.comp.enabled", &value, false);
377         return value;
378     }
debug(int fd)379     void debug(int fd) override { HwCalBase::debug(fd); }
380 };
381 
382 }  // namespace vibrator
383 }  // namespace hardware
384 }  // namespace android
385 }  // namespace aidl
386