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