blob: f45b97a499116c5263b356948a2c5b8aea785313 [file] [log] [blame]
Vincent Becker022224f2012-08-10 14:40:49 +02001/*
2 * Copyright (C) 2013 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
YU Shixian9e9e9322023-03-03 18:31:49 +080017#define LOG_TAG "vibrator_hw"
18#define LOG_NDEBUG 1
Vincent Becker022224f2012-08-10 14:40:49 +020019#include <hardware/hardware.h>
Mark Salyzynd88dfe82017-04-11 08:56:09 -070020#include <hardware/vibrator.h>
Vincent Becker022224f2012-08-10 14:40:49 +020021
Mark Salyzynd88dfe82017-04-11 08:56:09 -070022#include <errno.h>
23#include <fcntl.h>
Elliott Hughes07c08552015-01-29 21:19:10 -080024#include <malloc.h>
Mark Salyzynd88dfe82017-04-11 08:56:09 -070025#include <math.h>
Rob Herring61701df2015-11-16 12:54:30 -060026#include <stdbool.h>
Mark Salyzynd88dfe82017-04-11 08:56:09 -070027#include <stdio.h>
Rob Herring61701df2015-11-16 12:54:30 -060028#include <string.h>
Vincent Becker022224f2012-08-10 14:40:49 +020029#include <unistd.h>
Mark Salyzynd88dfe82017-04-11 08:56:09 -070030
31#include <log/log.h>
Vincent Becker022224f2012-08-10 14:40:49 +020032
Rob Herring61701df2015-11-16 12:54:30 -060033#define TIMEOUT_STR_LEN 20
34
Vincent Becker022224f2012-08-10 14:40:49 +020035static const char THE_DEVICE[] = "/sys/class/timed_output/vibrator/enable";
36
David Lin4e8f5612017-03-08 17:27:59 -080037static bool device_exists(const char *file) {
Vincent Becker022224f2012-08-10 14:40:49 +020038 int fd;
39
David Lin4e8f5612017-03-08 17:27:59 -080040 fd = TEMP_FAILURE_RETRY(open(file, O_RDWR));
Vincent Becker022224f2012-08-10 14:40:49 +020041 if(fd < 0) {
David Lin4e8f5612017-03-08 17:27:59 -080042 return false;
Vincent Becker022224f2012-08-10 14:40:49 +020043 }
44
45 close(fd);
David Lin4e8f5612017-03-08 17:27:59 -080046 return true;
47}
48
49static bool vibra_exists() {
50 return device_exists(THE_DEVICE);
Vincent Becker022224f2012-08-10 14:40:49 +020051}
52
Rob Herring61701df2015-11-16 12:54:30 -060053static int write_value(const char *file, const char *value)
Vincent Becker022224f2012-08-10 14:40:49 +020054{
55 int to_write, written, ret, fd;
56
Rob Herring61701df2015-11-16 12:54:30 -060057 fd = TEMP_FAILURE_RETRY(open(file, O_WRONLY));
58 if (fd < 0) {
Vincent Becker022224f2012-08-10 14:40:49 +020059 return -errno;
60 }
61
Rob Herring61701df2015-11-16 12:54:30 -060062 to_write = strlen(value) + 1;
Vincent Becker022224f2012-08-10 14:40:49 +020063 written = TEMP_FAILURE_RETRY(write(fd, value, to_write));
Vincent Becker022224f2012-08-10 14:40:49 +020064 if (written == -1) {
65 ret = -errno;
66 } else if (written != to_write) {
67 /* even though EAGAIN is an errno value that could be set
68 by write() in some cases, none of them apply here. So, this return
69 value can be clearly identified when debugging and suggests the
Rob Herring61701df2015-11-16 12:54:30 -060070 caller that it may try to call vibrator_on() again */
Vincent Becker022224f2012-08-10 14:40:49 +020071 ret = -EAGAIN;
72 } else {
73 ret = 0;
74 }
75
76 errno = 0;
77 close(fd);
78
79 return ret;
80}
81
Rob Herring61701df2015-11-16 12:54:30 -060082static int sendit(unsigned int timeout_ms)
83{
84 char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */
85
86 snprintf(value, sizeof(value), "%u", timeout_ms);
87 return write_value(THE_DEVICE, value);
88}
89
Vincent Becker022224f2012-08-10 14:40:49 +020090static int vibra_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
91{
92 /* constant on, up to maximum allowed time */
93 return sendit(timeout_ms);
94}
95
96static int vibra_off(vibrator_device_t* vibradev __unused)
97{
98 return sendit(0);
99}
100
Rob Herring61701df2015-11-16 12:54:30 -0600101static const char LED_DEVICE[] = "/sys/class/leds/vibrator";
102
103static int write_led_file(const char *file, const char *value)
104{
105 char file_str[50];
106
107 snprintf(file_str, sizeof(file_str), "%s/%s", LED_DEVICE, file);
108 return write_value(file_str, value);
109}
110
David Lin4e8f5612017-03-08 17:27:59 -0800111static bool vibra_led_exists()
Rob Herring61701df2015-11-16 12:54:30 -0600112{
David Lin4e8f5612017-03-08 17:27:59 -0800113 char file_str[50];
114
115 snprintf(file_str, sizeof(file_str), "%s/%s", LED_DEVICE, "activate");
116 return device_exists(file_str);
Rob Herring61701df2015-11-16 12:54:30 -0600117}
118
119static int vibra_led_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
120{
121 int ret;
122 char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */
123
124 ret = write_led_file("state", "1");
125 if (ret)
126 return ret;
127
128 snprintf(value, sizeof(value), "%u\n", timeout_ms);
129 ret = write_led_file("duration", value);
130 if (ret)
131 return ret;
132
133 return write_led_file("activate", "1");
134}
135
136static int vibra_led_off(vibrator_device_t* vibradev __unused)
137{
138 return write_led_file("activate", "0");
139}
140
YU Shixian9e9e9322023-03-03 18:31:49 +0800141static const char AW_DEVICE[] = "/sys/class/leds/vibrator_1";
142static int write_aw_file(const char *file, const char *value)
143{
144 char file_str[50];
145
146 snprintf(file_str, sizeof(file_str), "%s/%s", AW_DEVICE, file);
147 return write_value(file_str, value);
148}
149
150static bool vibra_aw_exists()
151{
152 char file_str[50];
153
154 snprintf(file_str, sizeof(file_str), "%s/%s", AW_DEVICE, "activate");
155 return device_exists(file_str);
156}
157
158static int vibra_aw_on(vibrator_device_t* vibradev __unused, unsigned int timeout_ms)
159{
160 int ret;
161 char value[TIMEOUT_STR_LEN]; /* large enough for millions of years */
162
163 ALOGI("%s time = %d ", __func__,timeout_ms);
164 if(timeout_ms <= 50) // MODIFIED by hongwei.tian, 2019-12-18,BUG-8509225
165 {
166 ret = write_aw_file("seq", "0x00 0x01");
167 if (ret)
168 return ret;
169 ret = write_aw_file("seq", "0x01 0x00");
170 if (ret)
171 return ret;
172 ret = write_aw_file("loop", "0x00 0x00");
173 if (ret)
174 return ret;
175 ret = write_aw_file("brightness", "1");
176 if (ret)
177 return ret;
178 ALOGI("%s short viber = %d ", __func__,timeout_ms);
179 return 0;
180 }
181 ret = write_aw_file("activate_mode", "0");
182 if (ret)
183 return ret;
184
185 ret = write_aw_file("index", "2");
186 if (ret)
187 return ret;
188
189 snprintf(value, sizeof(value), "%u\n", timeout_ms);
190 ret = write_aw_file("duration", value);
191 if (ret)
192 return ret;
193
194 return write_aw_file("activate", "1");
195}
196
197static int vibra_aw_off(vibrator_device_t* vibradev __unused)
198{
199 return write_aw_file("activate", "0");
200}
201typedef enum VIBRA_TYPE {
202 VIBRA_TIMEOUT = 0,
203 VIBRA_LED,
204 VIBRA_AW,
205}VIBRA_TYPE;
Vincent Becker022224f2012-08-10 14:40:49 +0200206static int vibra_close(hw_device_t *device)
207{
208 free(device);
209 return 0;
210}
211
212static int vibra_open(const hw_module_t* module, const char* id __unused,
213 hw_device_t** device __unused) {
Rob Herring61701df2015-11-16 12:54:30 -0600214 bool use_led;
YU Shixian9e9e9322023-03-03 18:31:49 +0800215 VIBRA_TYPE vibra_type = VIBRA_LED;
Rob Herring61701df2015-11-16 12:54:30 -0600216
YU Shixian9e9e9322023-03-03 18:31:49 +0800217 /* MODIFIED-BEGIN by hongwei.tian, 2020-06-02,BUG-9491648*/
218 if (vibra_aw_exists()) {
219 ALOGD("Vibrator using LED AW trigger");
220 use_led = true;
221 vibra_type = VIBRA_AW;
222 } else if (vibra_exists()) {
223 /* MODIFIED-END by hongwei.tian,BUG-9491648*/
Rob Herring61701df2015-11-16 12:54:30 -0600224 ALOGD("Vibrator using timed_output");
YU Shixian9e9e9322023-03-03 18:31:49 +0800225 vibra_type = VIBRA_TIMEOUT;
Rob Herring61701df2015-11-16 12:54:30 -0600226 use_led = false;
227 } else if (vibra_led_exists()) {
228 ALOGD("Vibrator using LED trigger");
229 use_led = true;
YU Shixian9e9e9322023-03-03 18:31:49 +0800230 vibra_type = VIBRA_LED;
Rob Herring61701df2015-11-16 12:54:30 -0600231 } else {
Vincent Becker022224f2012-08-10 14:40:49 +0200232 ALOGE("Vibrator device does not exist. Cannot start vibrator");
233 return -ENODEV;
234 }
235
236 vibrator_device_t *vibradev = calloc(1, sizeof(vibrator_device_t));
237
238 if (!vibradev) {
239 ALOGE("Can not allocate memory for the vibrator device");
240 return -ENOMEM;
241 }
242
243 vibradev->common.tag = HARDWARE_DEVICE_TAG;
244 vibradev->common.module = (hw_module_t *) module;
245 vibradev->common.version = HARDWARE_DEVICE_API_VERSION(1,0);
246 vibradev->common.close = vibra_close;
247
Rob Herring61701df2015-11-16 12:54:30 -0600248 if (use_led) {
YU Shixian9e9e9322023-03-03 18:31:49 +0800249 if(vibra_type == VIBRA_LED)
250 {
251 vibradev->vibrator_on = vibra_led_on;
252 vibradev->vibrator_off = vibra_led_off;
253 }
254 else
255 {
256 vibradev->vibrator_on = vibra_aw_on;
257 vibradev->vibrator_off = vibra_aw_off;
258 }
Rob Herring61701df2015-11-16 12:54:30 -0600259 } else {
260 vibradev->vibrator_on = vibra_on;
261 vibradev->vibrator_off = vibra_off;
262 }
Vincent Becker022224f2012-08-10 14:40:49 +0200263
264 *device = (hw_device_t *) vibradev;
265
266 return 0;
267}
268
269/*===========================================================================*/
270/* Default vibrator HW module interface definition */
271/*===========================================================================*/
272
273static struct hw_module_methods_t vibrator_module_methods = {
274 .open = vibra_open,
275};
276
277struct hw_module_t HAL_MODULE_INFO_SYM = {
278 .tag = HARDWARE_MODULE_TAG,
279 .module_api_version = VIBRATOR_API_VERSION,
280 .hal_api_version = HARDWARE_HAL_API_VERSION,
281 .id = VIBRATOR_HARDWARE_MODULE_ID,
282 .name = "Default vibrator HAL",
283 .author = "The Android Open Source Project",
284 .methods = &vibrator_module_methods,
285};