1 /* 2 * Copyright (C) 2017 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 #define LOG_TAG "android.hardware.vibrator (at) 1.2-service.bonito" 17 18 #include <android/hardware/vibrator/1.2/IVibrator.h> 19 #include <cutils/properties.h> 20 #include <hidl/HidlSupport.h> 21 #include <hidl/HidlTransportSupport.h> 22 #include <utils/Errors.h> 23 #include <utils/StrongPointer.h> 24 25 #include "Vibrator.h" 26 27 using android::hardware::configureRpcThreadpool; 28 using android::hardware::joinRpcThreadpool; 29 using android::hardware::vibrator::V1_2::IVibrator; 30 using android::hardware::vibrator::V1_2::implementation::Vibrator; 31 using namespace android; 32 33 // Refer to Documentation/ABI/testing/sysfs-class-led-driver-drv2624 34 // kernel documentation on the detail usages for ABIs below 35 static constexpr char ACTIVATE_PATH[] = "/sys/class/leds/vibrator/activate"; 36 static constexpr char DURATION_PATH[] = "/sys/class/leds/vibrator/duration"; 37 static constexpr char STATE_PATH[] = "/sys/class/leds/vibrator/state"; 38 static constexpr char RTP_INPUT_PATH[] = "/sys/class/leds/vibrator/device/rtp_input"; 39 static constexpr char MODE_PATH[] = "/sys/class/leds/vibrator/device/mode"; 40 static constexpr char SEQUENCER_PATH[] = "/sys/class/leds/vibrator/device/set_sequencer"; 41 static constexpr char SCALE_PATH[] = "/sys/class/leds/vibrator/device/scale"; 42 static constexpr char CTRL_LOOP_PATH[] = "/sys/class/leds/vibrator/device/ctrl_loop"; 43 static constexpr char LP_TRIGGER_PATH[] = "/sys/class/leds/vibrator/device/lp_trigger_effect"; 44 static constexpr char LRA_WAVE_SHAPE_PATH[] = "/sys/class/leds/vibrator/device/lra_wave_shape"; 45 static constexpr char OD_CLAMP_PATH[] = "/sys/class/leds/vibrator/device/od_clamp"; 46 47 // File path to the calibration file 48 static constexpr char CALIBRATION_FILEPATH[] = "/persist/haptics/drv2624.cal"; 49 50 // Kernel ABIs for updating the calibration data 51 static constexpr char AUTOCAL_CONFIG[] = "autocal"; 52 static constexpr char LRA_PERIOD_CONFIG[] = "lra_period"; 53 static constexpr char AUTOCAL_FILEPATH[] = "/sys/class/leds/vibrator/device/autocal"; 54 static constexpr char OL_LRA_PERIOD_FILEPATH[] = "/sys/class/leds/vibrator/device/ol_lra_period"; 55 56 // Set a default lra period in case there is no calibration file 57 static constexpr uint32_t DEFAULT_LRA_PERIOD = 262; 58 static constexpr uint32_t DEFAULT_FREQUENCY_SHIFT = 10; 59 60 static std::uint32_t freqPeriodFormula(std::uint32_t in) { 61 return 1000000000 / (24615 * in); 62 } 63 64 static std::string trim(const std::string &str, const std::string &whitespace = " \t") { 65 const auto str_begin = str.find_first_not_of(whitespace); 66 if (str_begin == std::string::npos) { 67 return ""; 68 } 69 70 const auto str_end = str.find_last_not_of(whitespace); 71 const auto str_range = str_end - str_begin + 1; 72 73 return str.substr(str_begin, str_range); 74 } 75 76 static bool loadCalibrationData(std::uint32_t &short_lra_period, std::uint32_t &long_lra_period) { 77 std::map<std::string, std::string> config_data; 78 79 std::ofstream autocal{AUTOCAL_FILEPATH}; 80 if (!autocal) { 81 int error = errno; 82 ALOGE("Failed to open %s (%d): %s", AUTOCAL_FILEPATH, error, strerror(error)); 83 return false; 84 } 85 86 std::ofstream ol_lra_period{OL_LRA_PERIOD_FILEPATH}; 87 if (!ol_lra_period) { 88 int error = errno; 89 ALOGE("Failed to open %s (%d): %s", OL_LRA_PERIOD_FILEPATH, error, strerror(error)); 90 return false; 91 } 92 93 std::ifstream cal_data{CALIBRATION_FILEPATH}; 94 if (!cal_data) { 95 int error = errno; 96 ALOGE("Failed to open %s (%d): %s", CALIBRATION_FILEPATH, error, strerror(error)); 97 return false; 98 } 99 100 std::string line; 101 102 while (std::getline(cal_data, line)) { 103 if (line.empty() || line[0] == '#') { 104 continue; 105 } 106 std::istringstream is_line(line); 107 std::string key; 108 if (std::getline(is_line, key, ':')) { 109 std::string value; 110 111 if (std::getline(is_line, value)) { 112 config_data[trim(key)] = trim(value); 113 } 114 } 115 } 116 117 if (config_data.find(AUTOCAL_CONFIG) != config_data.end()) { 118 autocal << config_data[AUTOCAL_CONFIG] << std::endl; 119 } 120 121 if (config_data.find(LRA_PERIOD_CONFIG) != config_data.end()) { 122 uint32_t thisFrequency; 123 uint32_t thisPeriod; 124 ol_lra_period << config_data[LRA_PERIOD_CONFIG] << std::endl; 125 thisPeriod = std::stoul(config_data[LRA_PERIOD_CONFIG]); 126 short_lra_period = thisPeriod; 127 // 1. Change long lra period to frequency 128 // 2. Get frequency': subtract the frequency shift from the frequency 129 // 3. Get final long lra period after put the frequency' to formula 130 thisFrequency = 131 freqPeriodFormula(thisPeriod) - 132 property_get_int32("ro.vibrator.hal.long.frequency.shift", DEFAULT_FREQUENCY_SHIFT); 133 long_lra_period = freqPeriodFormula(thisFrequency); 134 } 135 136 return true; 137 } 138 139 status_t registerVibratorService() { 140 // Calibration data: lra period 262(i.e. 155Hz) 141 std::uint32_t short_lra_period(DEFAULT_LRA_PERIOD); 142 std::uint32_t long_lra_period(DEFAULT_LRA_PERIOD); 143 Vibrator::HwApi hwapi; 144 145 // ostreams below are required 146 hwapi.activate.open(ACTIVATE_PATH); 147 if (!hwapi.activate) { 148 int error = errno; 149 ALOGE("Failed to open %s (%d): %s", ACTIVATE_PATH, error, strerror(error)); 150 return -error; 151 } 152 153 hwapi.duration.open(DURATION_PATH); 154 if (!hwapi.duration) { 155 int error = errno; 156 ALOGE("Failed to open %s (%d): %s", DURATION_PATH, error, strerror(error)); 157 return -error; 158 } 159 160 hwapi.state.open(STATE_PATH); 161 if (!hwapi.state) { 162 int error = errno; 163 ALOGE("Failed to open %s (%d): %s", STATE_PATH, error, strerror(error)); 164 return -error; 165 } 166 167 hwapi.state << 1 << std::endl; 168 if (!hwapi.state) { 169 int error = errno; 170 ALOGE("Failed to set state (%d): %s", errno, strerror(errno)); 171 return -error; 172 } 173 174 // ostreams below are optional 175 hwapi.rtpInput.open(RTP_INPUT_PATH); 176 if (!hwapi.rtpInput) { 177 int error = errno; 178 ALOGW("Failed to open %s (%d): %s", RTP_INPUT_PATH, error, strerror(error)); 179 } 180 181 hwapi.mode.open(MODE_PATH); 182 if (!hwapi.mode) { 183 int error = errno; 184 ALOGW("Failed to open %s (%d): %s", MODE_PATH, error, strerror(error)); 185 } 186 187 hwapi.sequencer.open(SEQUENCER_PATH); 188 if (!hwapi.sequencer) { 189 int error = errno; 190 ALOGW("Failed to open %s (%d): %s", SEQUENCER_PATH, error, strerror(error)); 191 } 192 193 hwapi.scale.open(SCALE_PATH); 194 if (!hwapi.scale) { 195 int error = errno; 196 ALOGW("Failed to open %s (%d): %s", SCALE_PATH, error, strerror(error)); 197 } 198 199 hwapi.ctrlLoop.open(CTRL_LOOP_PATH); 200 if (!hwapi.ctrlLoop) { 201 int error = errno; 202 ALOGW("Failed to open %s (%d): %s", CTRL_LOOP_PATH, error, strerror(error)); 203 } 204 205 hwapi.lpTriggerEffect.open(LP_TRIGGER_PATH); 206 if (!hwapi.lpTriggerEffect) { 207 int error = errno; 208 ALOGW("Failed to open %s (%d): %s", LP_TRIGGER_PATH, error, strerror(error)); 209 } 210 211 hwapi.lraWaveShape.open(LRA_WAVE_SHAPE_PATH); 212 if (!hwapi.lraWaveShape) { 213 int error = errno; 214 ALOGW("Failed to open %s (%d): %s", LRA_WAVE_SHAPE_PATH, error, strerror(error)); 215 } 216 217 hwapi.odClamp.open(OD_CLAMP_PATH); 218 if (!hwapi.odClamp) { 219 int error = errno; 220 ALOGW("Failed to open %s (%d): %s", OD_CLAMP_PATH, error, strerror(error)); 221 } 222 223 hwapi.olLraPeriod.open(OL_LRA_PERIOD_FILEPATH); 224 if (!hwapi.olLraPeriod) { 225 int error = errno; 226 ALOGW("Failed to open %s (%d): %s", OL_LRA_PERIOD_FILEPATH, error, strerror(error)); 227 } 228 229 if (!loadCalibrationData(short_lra_period, long_lra_period)) { 230 ALOGW("Failed load calibration data"); 231 } 232 233 sp<IVibrator> vibrator = new Vibrator(std::move(hwapi), short_lra_period, long_lra_period); 234 235 return vibrator->registerAsService(); 236 } 237 238 int main() { 239 configureRpcThreadpool(1, true); 240 status_t status = registerVibratorService(); 241 242 if (status != OK) { 243 return status; 244 } 245 246 joinRpcThreadpool(); 247 } 248