1/*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "battery_vibrate.h"
17
18#include <unistd.h>
19#include "file_ex.h"
20#include "charger_log.h"
21
22namespace OHOS {
23namespace PowerMgr {
24namespace {
25const std::string VIBRATOR_PLAYMODE_PATH = "/sys/class/leds/vibrator/play_mode";
26const std::string VIBRATOR_DURATIONMODE_PATH = "/sys/class/leds/vibrator/duration";
27const std::string VIBRATOR_ACTIVATEMODE_PATH = "/sys/class/leds/vibrator/activate";
28const std::string DURATION_MODE_DERECT = "direct";
29const std::string DURATION_MODE_AUDIO = "audio";
30constexpr int32_t VIBRATION_PLAYMODE = 0;
31constexpr int32_t VIBRATION_DURATIONMODE = 1;
32constexpr int32_t ACTIVE = 1;
33constexpr int32_t DEACTIVE = 0;
34constexpr int32_t VIBRATE_DELAY_MS = 5;
35constexpr int32_t USEC_TO_MSEC = 1000;
36}
37
38bool BatteryVibrate::InitVibration()
39{
40    BATTERY_HILOGD(FEATURE_CHARGING, "start init vibrate");
41
42    if (FileExists(VIBRATOR_PLAYMODE_PATH)) {
43        BATTERY_HILOGI(FEATURE_CHARGING, "vibrate path is play mode path");
44        vibrateMode_ = VIBRATION_PLAYMODE;
45        return true;
46    }
47
48    if (FileExists(VIBRATOR_DURATIONMODE_PATH)) {
49        BATTERY_HILOGI(FEATURE_CHARGING, "vibrate path is duration path");
50        vibrateMode_ = VIBRATION_DURATIONMODE;
51        return true;
52    }
53
54    BATTERY_HILOGW(FEATURE_CHARGING, "not support vibrate path");
55    return false;
56}
57
58void BatteryVibrate::HandlePlayMode(int32_t time)
59{
60    SetPlayMode(DURATION_MODE_DERECT);
61    SetDuration(time);
62    ActivateVibration(true);
63    usleep((time + VIBRATE_DELAY_MS) * USEC_TO_MSEC);
64    SetPlayMode(DURATION_MODE_AUDIO);
65}
66
67void BatteryVibrate::HandleDurationMode(int32_t time)
68{
69    SetDuration(time);
70    ActivateVibration(true);
71    usleep((time + VIBRATE_DELAY_MS) * USEC_TO_MSEC);
72    ActivateVibration(false);
73}
74
75void BatteryVibrate::HandleVibration(int32_t time) const
76{
77    switch (vibrateMode_) {
78        case VIBRATION_PLAYMODE: {
79            BATTERY_HILOGD(FEATURE_CHARGING, "vibrate play mode");
80            HandlePlayMode(time);
81            break;
82        }
83        case VIBRATION_DURATIONMODE: {
84            BATTERY_HILOGD(FEATURE_CHARGING, "vibrate duration mode");
85            HandleDurationMode(time);
86            break;
87        }
88        default: {
89            BATTERY_HILOGD(FEATURE_CHARGING, "vibrate unknown mode");
90            break;
91        }
92    }
93}
94
95void BatteryVibrate::SetPlayMode(const std::string& modeName)
96{
97    FILE* file = fopen(VIBRATOR_PLAYMODE_PATH.c_str(), "w");
98    if (file == nullptr) {
99        BATTERY_HILOGW(FEATURE_CHARGING, "play mode path open failed.");
100        return;
101    }
102    if (fprintf(file, "%s\n", modeName.c_str()) < 0) {
103        BATTERY_HILOGW(FEATURE_CHARGING, "play mode fprintf direct failed.");
104    }
105    if (fclose(file) < 0) {
106        BATTERY_HILOGW(FEATURE_CHARGING, "play mode fclose failed.");
107    }
108}
109
110void BatteryVibrate::ActivateVibration(bool isActive)
111{
112    int32_t value = isActive ? ACTIVE : DEACTIVE;
113    FILE* file = fopen(VIBRATOR_ACTIVATEMODE_PATH.c_str(), "w");
114    if (file == nullptr) {
115        BATTERY_HILOGW(FEATURE_CHARGING, "activate mode path open failed");
116        return;
117    }
118    if (fprintf(file, "%d\n", value) < 0) {
119        BATTERY_HILOGW(FEATURE_CHARGING, "activate mode fprintf failed, value=%{public}d", value);
120    }
121    if (fclose(file) < 0) {
122        BATTERY_HILOGW(FEATURE_CHARGING, "activate mode fclose failed");
123    }
124}
125
126void BatteryVibrate::SetDuration(int32_t time)
127{
128    FILE* file = fopen(VIBRATOR_DURATIONMODE_PATH.c_str(), "w");
129    if (file == nullptr) {
130        BATTERY_HILOGW(FEATURE_CHARGING, "duration mode path open failed");
131        return;
132    }
133    if (fprintf(file, "%d\n", time) < 0) {
134        BATTERY_HILOGW(FEATURE_CHARGING, "duration mode fprintf time failed, time=%{public}d", time);
135    }
136    if (fclose(file) < 0) {
137        BATTERY_HILOGW(FEATURE_CHARGING, "duration mode fclose failed.");
138    }
139}
140}  // namespace PowerMgr
141}  // namespace OHOS
142