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