4 * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include <sys/types.h>
30 #include <linux/input.h>
33 #include "core/list.h"
36 #define MAX_MAGNITUDE 0xFFFF
37 #define PERIODIC_MAX_MAGNITUDE 0x7FFF /* 0.5 * MAX_MAGNITUDE */
38 #define RUMBLE_MAX_MAGNITUDE 0xFFFF
40 #define DEV_INPUT "/dev/input"
44 #define FF_INFO_MAGIC 0xDEADFEED
46 struct ff_info_header {
49 int ff_info_data_count;
53 int type;/* play, stop etc */
54 int magnitude; /* strength */
55 int length; /* in ms for stop, play*/
58 struct ff_info_buffer {
59 struct ff_info_header header;
60 struct ff_info_data data[MAX_DATA];
66 struct ff_effect effect;
67 struct ff_info_buffer *ffinfobuffer;
72 static dd_list *ff_list;
73 static dd_list *handle_list;
74 static char ff_path[PATH_MAX];
75 static int unique_number;
76 static int current_effect_id = -1;
78 static int stop_device(int device_handle);
80 struct ff_info *read_from_list(int handle)
85 DD_LIST_FOREACH(ff_list, elem, temp) {
86 if (temp->handle == handle)
92 static bool check_valid_handle(struct ff_info *info)
97 DD_LIST_FOREACH(ff_list, elem, temp) {
107 static bool check_fd(int *fd)
114 ffd = open(ff_path, O_RDWR);
122 static int ff_stop(int fd, struct ff_effect *effect);
123 static gboolean timer_cb(void *data)
125 struct ff_info *info = (struct ff_info *)data;
128 _E("Failed to check info.");
129 return G_SOURCE_REMOVE;
132 if (!check_valid_handle(info)) {
133 _E("Failed to check valied info.");
134 return G_SOURCE_REMOVE;
137 _I("Stop vibration by timer. id(%d)", info->effect.id);
139 /* stop previous vibration */
140 ff_stop(ff_fd, &info->effect);
145 return G_SOURCE_REMOVE;
148 static int ff_find_device(void)
152 char ev_path[PATH_MAX];
153 unsigned long features[1+FF_MAX/sizeof(unsigned long)];
156 dir = opendir(DEV_INPUT);
165 if (dent->d_type == DT_DIR ||
166 !strstr(dent->d_name, "event"))
169 snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name);
171 fd = open(ev_path, O_RDWR);
173 _E("Failed to open '%s'.: %d", ev_path, errno);
177 /* get force feedback device */
178 memset(features, 0, sizeof(features));
179 ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features);
185 if (test_bit(FF_CONSTANT, features))
186 _D("'%s' type: constant", ev_path);
187 if (test_bit(FF_PERIODIC, features))
188 _D("'%s' type: periodic", ev_path);
189 if (test_bit(FF_SPRING, features))
190 _D("'%s' type: spring", ev_path);
191 if (test_bit(FF_FRICTION, features))
192 _D("'%s' type: friction", ev_path);
193 if (test_bit(FF_RUMBLE, features))
194 _D("'%s' type: rumble", ev_path);
196 if (test_bit(FF_RUMBLE, features)) {
197 memcpy(ff_path, ev_path, strlen(ev_path));
198 ff_path[strlen(ev_path)] = '\0';
211 static int ff_init_effect(struct ff_effect *effect)
216 /*Only rumble supported as of now*/
217 effect->type = FF_RUMBLE;
218 effect->replay.length = 0;
219 effect->replay.delay = 10;
221 effect->u.rumble.strong_magnitude = 0;
226 static int ff_set_effect(struct ff_effect *effect, int length, int level)
231 _E("There is no valid effect.");
235 magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
236 magnitude *= RUMBLE_MAX_MAGNITUDE;
238 _I("magnitude=%d length=%d", (int)magnitude, length);
240 /* set member variables in effect struct */
241 effect->u.rumble.strong_magnitude = (int)magnitude;
242 effect->replay.length = length; /* length millisecond */
247 static int ff_play(int fd, struct ff_effect *effect)
249 struct input_event play;
252 if (fd < 0 || !effect) {
253 _E("Fd(%d) or effect(%s) is invalid", fd, effect ? "not null" : "null");
257 /* upload an effect */
258 if (current_effect_id == -1) {
259 if (ioctl(fd, EVIOCSFF, effect) == -1) {
260 _E("Failed to ioctl");
263 current_effect_id = effect->id;
265 effect->id = current_effect_id;
269 play.code = effect->id;
270 play.value = 1; /* 1 : PLAY, 0 : STOP */
272 ret = write(fd, (const void *)&play, sizeof(play));
274 _E("Failed to write");
281 static int ff_stop(int fd, struct ff_effect *effect)
283 struct input_event stop;
286 if (fd < 0 || !effect)
289 if (effect->id == -1) {
290 if (current_effect_id == -1)
292 effect->id = current_effect_id;
297 stop.code = effect->id;
298 stop.value = 0; /* 1 : PLAY, 0 : STOP */
299 ret = write(fd, (const void *)&stop, sizeof(stop));
303 /* removing an effect from the device */
304 if (ioctl(fd, EVIOCRMFF, effect->id) == -1)
307 /* reset effect id */
309 current_effect_id = -1;
314 /* START: Haptic Module APIs */
315 static int get_device_count(int *count)
317 /* suppose there is just one haptic device */
324 static int open_device(int device_index, int *device_handle)
326 struct ff_info *info;
334 /* if it is the first element */
335 n = DD_LIST_LENGTH(ff_list);
336 if (n == 0 && !ff_fd) {
337 _I("First element: open ff driver");
339 ff_fd = open(ff_path, O_RDWR);
341 _E("Failed to open %s : %d", ff_path, errno);
346 /* allocate memory */
347 info = calloc(sizeof(struct ff_info), 1);
349 _E("Failed to allocate memory : %d", errno);
353 /* initialize ff_effect structure */
354 ff_init_effect(&info->effect);
356 if (unique_number == INT_MAX)
359 while (found != true) {
361 elem = DD_LIST_FIND(handle_list, (gpointer)(long)unique_number);
366 info->handle = unique_number;
368 /* add info to local list */
369 DD_LIST_APPEND(ff_list, info);
370 DD_LIST_APPEND(handle_list, (gpointer)(long)info->handle);
372 *device_handle = info->handle;
376 static int close_device(int device_handle)
378 struct ff_info *info;
381 info = read_from_list(device_handle);
383 _E("Handle %d failed to check info", device_handle);
384 return -ENOENT; /* 2 */
387 if (!check_valid_handle(info)) {
388 _E("Handle %d failed to check valid handle", device_handle);
389 return -EINVAL; /* 22 */
392 if (!check_fd(&ff_fd)) {
393 _E("Handle %d failed to check fd", device_handle);
394 return -ENODEV; /* 19 */
398 stop_device(device_handle);
400 DD_LIST_REMOVE(handle_list, (gpointer)(long)info->handle);
402 safe_free(info->ffinfobuffer);
403 /* remove info from local list */
404 DD_LIST_REMOVE(ff_list, info);
407 /* if it is the last element */
408 n = DD_LIST_LENGTH(ff_list);
409 if (n == 0 && ff_fd) {
410 _I("Last element: close ff driver");
411 /* close ff driver */
419 static int vibrate_monotone(int device_handle, int duration, int feedback, int priority)
421 struct ff_info *info;
424 info = read_from_list(device_handle);
426 _E("Handle %d failed to check list", device_handle);
430 if (!check_valid_handle(info)) {
431 _E("Handle %d failed to check handle", device_handle);
435 if (!check_fd(&ff_fd))
439 _I("Handle %d skip requests with duration 0", device_handle);
443 /* Zero(0) is the infinitely vibration value */
444 if (duration == HAPTIC_MODULE_DURATION_UNLIMITED)
447 /* unregister existing timer */
449 ff_stop(ff_fd, &info->effect);
450 g_source_remove(info->timer);
454 /* set effect as per arguments */
455 ff_init_effect(&info->effect);
456 ret = ff_set_effect(&info->effect, duration, feedback);
458 _E("Handle %d fail to set effect(duration:%d, feedback:%d) : %d",
459 device_handle, duration, feedback, ret);
463 /* play effect as per arguments */
464 ret = ff_play(ff_fd, &info->effect);
466 _E("Handle %d fail to play haptic effect(fd:%d id:%d) : %d",
467 device_handle, ff_fd, info->effect.id, ret);
473 info->timer = g_timeout_add(duration, timer_cb, info);
475 _E("Handle %d failed to add timer callback", device_handle);
478 _D("Handle %d effect id : %d %dms", device_handle, info->effect.id, duration);
483 static int stop_device(int device_handle)
485 struct ff_info *info;
488 info = read_from_list(device_handle);
490 _E("Handle %d fail to check info", device_handle);
491 return -ENOENT; /* 2 */
494 if (!check_valid_handle(info)) {
495 _E("Handle %d fail to check handle", device_handle);
496 return -EINVAL; /* 22 */
499 if (!check_fd(&ff_fd)) {
500 _E("Handle %d fail to check fd", device_handle);
501 return -ENODEV; /* 19 */
504 if (cur_h_data.handle > 0 && cur_h_data.handle != info->handle) {
505 _E("Only same handle can stop current vibration");
510 r = ff_stop(ff_fd, &info->effect);
512 _E("failed to stop effect(id:%d) : %d", info->effect.id, r);
514 _D("succeed to stop effect");
516 /* unregister existing timer */
517 if (r >= 0 && info->timer) {
518 g_source_remove(info->timer);
524 /* END: Haptic Module APIs */
526 static const struct haptic_plugin_ops default_plugin = {
527 .get_device_count = get_device_count,
528 .open_device = open_device,
529 .close_device = close_device,
530 .vibrate_monotone = vibrate_monotone,
531 .stop_device = stop_device,
534 static bool is_valid(void)
538 ret = ff_find_device();
540 _E("Do not support standard haptic device");
544 _I("Support standard haptic device");
548 static const struct haptic_plugin_ops *load(void)
550 return &default_plugin;
553 static const struct haptic_ops std_ops = {
554 .type = HAPTIC_STANDARD,
555 .is_valid = is_valid,
559 HAPTIC_OPS_REGISTER(&std_ops)