Home | History | Annotate | Download | only in vibrator
      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