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 <libsyscommon/dbus-system.h>
30 #include "core/list.h"
31 #include "core/common.h"
32 #include "core/device-idler.h"
33 #include "core/config-parser.h"
36 #define FEEDBACK_BASE_PATH "/usr/share/feedback/"
37 #define STANDARD_FILE_PATH FEEDBACK_BASE_PATH"vibration/"
38 #define VIBRATION_CONF_PATH FEEDBACK_BASE_PATH"vibration.conf"
40 #define PATTERN_DEFAULT_MONOTONE "FEEDBACK_PATTERN_DEFAULT"
42 #define HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf"
43 #define SIGNAL_POWEROFF_STATE "ChangeState"
44 #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator"
46 /* hardkey vibration variable */
47 #define HARDKEY_VIB_ITERATION 1
48 #define HARDKEY_VIB_FEEDBACK 3
49 #define HARDKEY_VIB_DURATION 30
50 #define HAPTIC_FEEDBACK_STEP 20
51 #define DEFAULT_FEEDBACK_LEVEL 3
52 #define HIGH_FEEDBACK_LEVEL 100
53 #define LOW_FEEDBACK_LEVEL 0
55 /* power on, power off vibration variable */
56 #define POWER_ON_VIB_DURATION 300
57 #define POWER_OFF_VIB_DURATION 300
58 #define POWER_VIB_FEEDBACK 100
60 #define MAX_EFFECT_BUFFER (64*1024)
62 #ifndef VCONFKEY_RECORDER_STATE
63 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
64 #define VCONFKEY_RECORDER_STATE_RECORDING 2
67 #define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV))
70 #define INTENSITY_BASE_RATE (10000)
71 #define VALUE_MAX_LEN 10
72 #define VIB_LOCK_TIMEOUT_MAX (300000) /* 5minutes */
75 1,A_W or A,A_W or 250D250W250D750W
82 struct vibration_config {
83 char *pattern; /* pattern name */
84 char *standard; /* assigned standard pattern name */
85 dd_list *data; /* duration_data list */
86 unsigned int pattern_duration;
90 struct duration_data {
107 dd_list *handle_list;
111 struct vibrate_pattern_info {
118 struct vibrate_monotone_info {
129 /* pattern configuration list */
130 static dd_list *vib_conf_list;
132 guint duration_timer;
134 /* haptic operation variable */
135 static dd_list *h_head;
136 static dd_list *haptic_handle_list;
137 static const struct haptic_plugin_ops *h_ops;
138 static enum haptic_type h_type;
139 static bool haptic_disabled;
141 struct haptic_config {
147 static struct haptic_config haptic_conf;
148 static struct duration_data haptic_default_data;
150 static int haptic_start(void);
151 static int haptic_stop(void);
152 static int haptic_internal_init(void);
153 static int remove_haptic_info(struct haptic_info *info);
155 struct haptic_data cur_h_data;
157 void add_haptic(const struct haptic_ops *ops)
159 DD_LIST_APPEND(h_head, (void *)ops);
162 void remove_haptic(const struct haptic_ops *ops)
164 DD_LIST_REMOVE(h_head, (void *)ops);
167 static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
169 struct duration_data *data;
171 data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
173 _E("Not enough memory.");
176 memcpy(data, update, sizeof(struct duration_data));
177 /* insert vibration pattern data */
179 // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdrive, data->wait);
180 DD_LIST_APPEND(*conf_data, data);
184 static void get_pattern_property(char **iter, char property, int *value)
187 unsigned long int val;
189 check = strchr(*iter, property);
194 val = strtoul(*iter, NULL, 10);
195 if (errno == EINVAL || errno == ERANGE) {
197 _E("Failed to get value of %s: %d", *iter, errno);
199 if (val > VIB_LOCK_TIMEOUT_MAX)
200 val = VIB_LOCK_TIMEOUT_MAX;
207 /* [A]xxxDxxxIxxxFxxxOxxxW format */
208 static int insert_raw_data_format(dd_list **conf_data, char *value)
210 struct duration_data update = {0, };
213 int pattern_duration = 0;
216 return insert_conf_data(conf_data, &update);
218 _E("Invalid parameter: Configuration list is null");
223 end = iter + strlen(iter);
225 memset(&update, 0, sizeof(struct duration_data));
227 get_pattern_property(&iter, 'D', &update.duration);
228 get_pattern_property(&iter, 'I', &update.intensity);
229 if (update.intensity > INTENSITY_BASE_RATE)
230 update.intensity = INTENSITY_BASE_RATE;
231 get_pattern_property(&iter, 'F', &update.frequency);
232 get_pattern_property(&iter, 'W', &update.wait);
234 if (update.duration == 0 && update.wait == 0) {
235 _D("Pattern duration is zero.");
239 pattern_duration += (update.duration + update.wait);
240 if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
241 _D("Max pattern duration.");
242 pattern_duration = VIB_LOCK_TIMEOUT_MAX;
245 if (insert_conf_data(conf_data, &update) < 0)
249 return pattern_duration;
252 static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
254 static int duration = 0;
255 static int intensity = 0;
259 if (count > 4 || count <= 0) {
260 _E("Invalid parameter: count is invalid");
264 if (!packed || !val || !pattern_duration || !update) {
265 _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
269 get_pattern_property(&val, 'C', &value);
275 *pattern_duration += duration;
276 if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
277 _D("Max pattern duration.");
278 *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
282 if (value > INTENSITY_BASE_RATE)
283 value = INTENSITY_BASE_RATE;
285 if (*packed == false) {
286 update->duration = duration;
287 update->intensity = intensity;
290 /* if intensity is 0, duration use for wait(off) time */
292 update->wait = duration;
302 update->frequency = value;
305 if (intensity != 0) {
306 update->overdrive = value;
318 duration, intensity, frequency, overdrive
319 waiting duration, intensity=0, frequency, overdrive
325 static int load_standard_format(const char *pattern)
327 struct duration_data update = {0, };
329 struct vibration_config *conf;
330 int ret = 0, count = 0, end = 2;
333 char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
335 snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
336 fd = open(path, O_RDONLY);
340 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
342 _E("Failed to alloc.");
347 conf->pattern = strdup(pattern);
348 if (!conf->pattern) {
349 _E("Failed to copy pattern data(%s).", pattern);
354 /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
355 while (read(fd, &elem, 1) != 0) {
357 if (insert_conf_data(&conf->data, &update) < 0)
361 if (elem == 'e' || elem == 'n' || elem == 'd') {
374 ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
378 if (insert_conf_data(&conf->data, &update) < 0)
380 memset(&update, 0, sizeof(struct duration_data));
384 if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
387 _E("Pattern(%s) is out of bound: %s", pattern, val);
391 DD_LIST_APPEND(vib_conf_list, conf);
405 static int vibration_load_config(struct parse_result *result, void *user_data)
407 struct vibration_config *conf;
416 if (!MATCH(result->section, "Vibration"))
420 if (!result->name || !result->value)
423 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
425 _E("Failed to alloc.");
429 conf->pattern_duration = 0;
430 conf->pattern = strdup(result->name);
431 if (!conf->pattern) {
432 _E("Failed to copy pattern data(%s).", result->name);
436 value = result->value;
440 if (insert_raw_data_format(&conf->data, NULL) < 0)
442 DD_LIST_APPEND(vib_conf_list, conf);
446 /* Load Standard Pattern Name */
447 /* value: 1,A_W or A,A_W */
448 if ((check = strchr(value, ','))) {
450 if (strncmp(value, "A", 1) == 0)
453 conf->standard = strdup(value);
454 if (!conf->standard) {
455 _E("Failed to copy standard name.");
458 DD_LIST_APPEND(vib_conf_list, conf);
462 /* value : A100D or 100D0W or 250D250W250D750W */
463 /* Load Vibration Pattern Data */
464 check = strchr(value, 'A');
471 len = len - strlen(value) - 1;
474 duration = insert_raw_data_format(&conf->data, value);
476 conf->pattern_duration = 0;
479 conf->pattern_duration = duration;
480 DD_LIST_APPEND(vib_conf_list, conf);
489 free(conf->standard);
494 static void load_standard_vibration_patterns(void)
500 dir = opendir(STANDARD_FILE_PATH);
502 _E("Failed to load '%s' Use default value.", STANDARD_FILE_PATH);
505 while ((dent = readdir(dir))) {
506 if (dent->d_type == DT_DIR)
508 ret = load_standard_format(dent->d_name);
510 _E("Failed to parse %s: %d", dent->d_name, ret);
513 _D("Success to load '%s'", STANDARD_FILE_PATH);
516 void pattern_config_parse(void)
520 ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
522 _E("Failed to load '%s'. Use default value: %d", VIBRATION_CONF_PATH, ret);
524 load_standard_vibration_patterns();
527 static void get_default_haptic_data()
530 struct vibration_config *conf;
531 char pattern[PATH_MAX] = {0,};
533 memset(&haptic_default_data, 0, sizeof(struct duration_data));
535 snprintf(pattern, sizeof(pattern), "%s", PATTERN_DEFAULT_MONOTONE);
536 DD_LIST_FOREACH(vib_conf_list, elem, conf) {
539 if (strcmp(conf->pattern, pattern))
542 if (conf->standard) {
543 snprintf(pattern, sizeof(pattern), "%s", conf->standard);
548 memcpy(&haptic_default_data, conf->data->data, sizeof(struct duration_data));
552 _D("Default haptic data: intensity=%d, frequency=%d", haptic_default_data.intensity, haptic_default_data.frequency);
555 static int haptic_module_load(void)
557 struct haptic_ops *ops;
561 pattern_config_parse();
562 get_default_haptic_data();
563 /* find valid plugin */
564 DD_LIST_FOREACH(h_head, elem, ops) {
565 if (ops->is_valid && ops->is_valid()) {
573 if (!CHECK_VALID_OPS(h_ops, r)) {
574 _E("Can't find the valid haptic device.");
579 * we do not use internal vibration except power off.
580 * if the last handle is closed during the playing of vibration,
581 * solution makes unlimited vibration.
582 * so we need at least one handle. */
583 haptic_internal_init();
589 static int convert_magnitude_by_conf(int level)
593 if (level < LOW_FEEDBACK_LEVEL)
594 level = LOW_FEEDBACK_LEVEL;
595 else if (level > HIGH_FEEDBACK_LEVEL)
596 level = HIGH_FEEDBACK_LEVEL;
598 step = 100 / (haptic_conf.level-1);
599 for (i = 0; i < haptic_conf.level; ++i) {
600 if (level <= i*step) {
601 _D("Level changed. %d -> %d", level, haptic_conf.level_arr[i]);
602 return haptic_conf.level_arr[i];
606 _D("Play default level.");
607 return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP;
610 GVariant *hdbus_get_count(GDBusConnection *conn,
611 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
612 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
616 if (!CHECK_VALID_OPS(h_ops, ret))
619 ret = h_ops->get_device_count(&val);
624 return g_variant_new("(i)", ret);
627 void haptic_name_owner_changed(GDBusConnection *connection,
632 struct haptic_info *info = user_data;
635 _I("%s (sender=%s)", __func__, name);
640 for (n = info->handle_list; n; n = n->next) {
641 handle = (int)(long)n->data;
642 h_ops->stop_device(handle);
643 h_ops->close_device(handle);
646 remove_haptic_info(info);
649 static struct haptic_info *add_haptic_info(const char *sender)
651 struct haptic_info *info;
655 info = calloc(1, sizeof(struct haptic_info));
659 info->sender = strdup(sender);
665 DD_LIST_APPEND(haptic_handle_list, info);
667 info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL);
672 static int remove_haptic_info(struct haptic_info *info)
676 dbus_handle_unwatch_name(info->id_watch);
678 DD_LIST_REMOVE(haptic_handle_list, info);
679 DD_LIST_FREE_LIST(info->handle_list);
688 static struct haptic_info *get_matched_haptic_info(const char *sender)
691 struct haptic_info *info;
696 len = strlen(sender) + 1;
697 DD_LIST_FOREACH(haptic_handle_list, n, info) {
698 if (!strncmp(info->sender, sender, len))
705 GVariant *hdbus_open_device(GDBusConnection *conn,
706 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
707 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
710 int index, handle, ret;
711 struct haptic_info *info;
713 /* Load haptic module before booting done */
714 if (!CHECK_VALID_OPS(h_ops, ret)) {
715 ret = haptic_module_load();
720 g_variant_get(param, "(i)", &index);
722 ret = h_ops->open_device(index, &handle);
728 h_ops->close_device(handle);
732 info = get_matched_haptic_info(sender);
734 info = add_haptic_info(sender);
736 _E("Failed to create haptic information.");
738 h_ops->close_device(handle);
743 DD_LIST_APPEND(info->handle_list, (gpointer)(long)handle);
748 return g_variant_new("(i)", ret);
751 int clear_current_data(void)
753 cur_h_data.handle = INVALID_HANDLE;
754 cur_h_data.priority = PRIORITY_MIN;
756 if (duration_timer) {
757 _I("Remove duration_timer.");
758 g_source_remove(duration_timer);
765 GVariant *hdbus_close_device(GDBusConnection *conn,
766 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
767 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
771 struct haptic_info *info;
774 if (!CHECK_VALID_OPS(h_ops, ret))
777 g_variant_get(param, "(u)", &handle);
780 _E("Failed to get sender from dbus message.");
785 ret = h_ops->close_device(handle);
789 if (cur_h_data.handle == handle) {
790 /* Remove duration_timer for vibrate_effect */
791 clear_current_data();
794 info = get_matched_haptic_info(sender);
796 _E("Failed to find the matched haptic info.");
800 DD_LIST_REMOVE(info->handle_list, (gpointer)(long)handle);
801 cnt = DD_LIST_LENGTH(info->handle_list);
803 remove_haptic_info(info);
806 return g_variant_new("(i)", ret);
809 static gboolean _cb(void *data)
811 if (duration_timer) {
812 g_source_remove(duration_timer);
816 cur_h_data.handle = INVALID_HANDLE;
817 cur_h_data.priority = PRIORITY_MIN;
819 return G_SOURCE_REMOVE;
822 static void vibrate_monotone_idler_cb(void *data)
824 struct vibrate_monotone_info *vibrate_info;
830 vibrate_info = (struct vibrate_monotone_info *)data;
832 if (vibrate_info->priority < cur_h_data.priority) {
833 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
838 if (duration_timer) {
839 g_source_remove(duration_timer);
843 cur_h_data.vibration_data = NULL;
844 cur_h_data.handle = vibrate_info->handle;
845 cur_h_data.level = vibrate_info->level;
846 cur_h_data.priority = vibrate_info->priority;
847 cur_h_data.stop = false;
848 cur_h_data.unlimit = false;
850 ret = device_power_request_lock(POWER_LOCK_CPU, vibrate_info->duration);
851 if (ret != DEVICE_ERROR_NONE)
852 _E("Failed to request power lock.");
854 _D("Handle(%d) play=%dms, level=%d, intensity=%d, frequency=%d)",
855 cur_h_data.handle, vibrate_info->duration, cur_h_data.level,
856 vibrate_info->intensity, haptic_default_data.frequency);
858 duration_timer = g_timeout_add(vibrate_info->duration, _cb, NULL);
859 h_ops->vibrate_monotone(cur_h_data.handle, vibrate_info->duration, haptic_default_data.frequency, 0, cur_h_data.level, vibrate_info->intensity, cur_h_data.priority);
864 GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
865 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
866 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
868 struct vibrate_monotone_info *vibrate_info;
870 int duration, level, intensity, priority, ret = 0;
872 if (!CHECK_VALID_OPS(h_ops, ret))
878 g_variant_get(param, "(uiii)", &handle, &duration, &intensity, &priority);
879 _D("param (uiii): handle=%u, duration=%d, intensity=%d, priority=%d", handle, duration, intensity, priority);
886 if (priority < PRIORITY_MIN)
887 priority = PRIORITY_MIN;
888 else if (priority > PRIORITY_TOP)
889 priority = PRIORITY_TOP;
892 _E("Skip vibrate handle(%d) requested less than 0.", handle);
897 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
898 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' value.");
903 vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
905 _E("Failed to allocate memory for vibrate_info.");
910 vibrate_info->handle = handle;
911 vibrate_info->duration = duration;
912 vibrate_info->level = (level/2) + 1;
913 vibrate_info->intensity = intensity * 100; // 1~100 (API spec)
914 vibrate_info->priority = priority;
916 ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
918 return g_variant_new("(i)", ret);
921 static gboolean haptic_duration_play(void *data)
923 dd_list *head, *n, *next;
924 struct duration_data *node;
927 if (duration_timer) {
928 g_source_remove(duration_timer);
933 if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
934 head = cur_h_data.vibration_data;
936 cur_h_data.handle = INVALID_HANDLE;
937 cur_h_data.priority = PRIORITY_MIN;
941 head = (dd_list *)data;
943 if (cur_h_data.stop) {
944 _I("Stop currunt vibration.");
945 cur_h_data.stop = false;
946 cur_h_data.handle = INVALID_HANDLE;
947 cur_h_data.priority = PRIORITY_MIN;
951 DD_LIST_FOREACH_SAFE(head, n, next, node) {
952 _I("Handle(%d) play=%dms and Wait=%dms %s type. (level=%d, intensity=%d, frequency=%d)",
953 cur_h_data.handle, node->duration, node->wait,
954 cur_h_data.unlimit ? "Unlimit" : "Once", cur_h_data.level, node->intensity, node->frequency);
955 if ((node->duration + node->wait) <= 0) {
956 if (!cur_h_data.unlimit) {
957 cur_h_data.handle = INVALID_HANDLE;
958 cur_h_data.priority = PRIORITY_MIN;
961 next = cur_h_data.vibration_data;
966 duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
968 ret = h_ops->vibrate_monotone(cur_h_data.handle, node->duration, node->frequency, node->overdrive, cur_h_data.level, node->intensity, cur_h_data.priority);
973 _D("Auto stop vibration.");
974 cur_h_data.stop = true;
977 return G_SOURCE_REMOVE;
980 static void vibrate_pattern_idler_cb(void *data)
982 struct vibrate_pattern_info *vibrate_info;
984 struct vibration_config *conf;
985 char pattern[PATH_MAX];
992 vibrate_info = (struct vibrate_pattern_info *)data;
994 if (!(vibrate_info->pattern)) {
999 /* Same or higher priority pattern should be played */
1000 if (vibrate_info->priority < cur_h_data.priority) {
1001 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
1005 snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
1006 DD_LIST_FOREACH(vib_conf_list, elem, conf) {
1009 if (strcmp(conf->pattern, pattern))
1011 if (conf->standard) {
1012 unlimit = conf->unlimit;
1013 snprintf(pattern, sizeof(pattern), "%s", conf->standard);
1018 cur_h_data.unlimit = unlimit;
1020 cur_h_data.unlimit = conf->unlimit;
1021 cur_h_data.vibration_data = conf->data;
1022 cur_h_data.handle = vibrate_info->handle;
1023 cur_h_data.level = vibrate_info->level;
1024 cur_h_data.priority = vibrate_info->priority;
1025 cur_h_data.stop = false;
1026 _I("Handle(%d) play=%s pri=%d %s", cur_h_data.handle, conf->pattern, cur_h_data.priority,
1027 cur_h_data.unlimit ? "Unlimit" : "Once");
1029 if (conf->pattern_duration <= 0)
1032 if (!cur_h_data.unlimit && conf->pattern_duration > 0) {
1033 ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration);
1034 if (ret != DEVICE_ERROR_NONE)
1035 _E("Failed to request power lock.");
1037 haptic_duration_play((void *)cur_h_data.vibration_data);
1040 _E("Handle(%d) %s is not supported.", vibrate_info->handle, pattern);
1043 free(vibrate_info->pattern);
1047 GVariant *hdbus_vibrate_pattern(GDBusConnection *conn,
1048 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1049 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1051 struct vibrate_pattern_info *vibrate_info;
1052 unsigned int handle;
1053 char *pattern = NULL;
1054 int level, priority, ret = 0;
1056 if (!CHECK_VALID_OPS(h_ops, ret))
1059 if (haptic_disabled)
1062 g_variant_get(param, "(usii)", &handle, &pattern, &level, &priority);
1069 if (priority < PRIORITY_MIN)
1070 priority = PRIORITY_MIN;
1071 else if (priority > PRIORITY_TOP)
1072 priority = PRIORITY_TOP;
1074 vibrate_info = calloc(1, sizeof(struct vibrate_pattern_info));
1075 if (!vibrate_info) {
1076 _E("Failed to allocate memory for vibrate_info.");
1080 vibrate_info->handle = handle;
1081 vibrate_info->pattern = pattern;
1083 if (!vibrate_info->pattern) {
1084 _E("Failed to allocate memory for pattern.");
1089 vibrate_info->level = level;
1090 vibrate_info->priority = priority;
1092 ret = add_idle_request(vibrate_pattern_idler_cb, (void *)vibrate_info);
1096 return g_variant_new("(i)", ret);
1099 GVariant *hdbus_stop_device(GDBusConnection *conn,
1100 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1101 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1103 unsigned int handle;
1106 if (!CHECK_VALID_OPS(h_ops, ret))
1109 if (haptic_disabled) {
1110 _I("Haptic disabled.");
1114 g_variant_get(param, "(u)", &handle);
1116 if (cur_h_data.handle != handle) {
1117 _D("Not the request from current vibration handle(%d). Skip.", handle);
1121 ret = h_ops->stop_device(handle);
1122 _I("Stop the device(handle=%u) :%d", handle, ret);
1124 /* Remove duration_timer for vibrate_effect */
1125 clear_current_data();
1128 return g_variant_new("(i)", ret);
1131 GVariant *hdbus_show_handle_list(GDBusConnection *conn,
1132 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1133 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1137 struct haptic_info *info;
1139 _D("Sender Handle");
1140 DD_LIST_FOREACH(haptic_handle_list, n, info) {
1141 for (elem = info->handle_list; elem; elem = elem->next)
1142 _D("%s %d", info->sender, (int)(long)elem->data);
1145 return g_variant_new_tuple(NULL, 0);
1148 int pattern_is_supported(const char *pattern)
1151 struct vibration_config *conf;
1158 DD_LIST_FOREACH(vib_conf_list, elem, conf) {
1161 if (!strcmp(conf->pattern, pattern)) {
1170 GVariant *hdbus_pattern_is_supported(GDBusConnection *conn,
1171 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1172 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1178 if (!CHECK_VALID_OPS(h_ops, ret))
1181 if (haptic_disabled)
1184 g_variant_get(param, "(s)", &data);
1186 ret = pattern_is_supported(data);
1188 _I("%s is supported: %d", data, ret);
1192 return g_variant_new("(i)", ret);
1195 static int haptic_internal_init(void)
1198 if (!CHECK_VALID_OPS(h_ops, r))
1200 return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle);
1203 static int haptic_internal_exit(void)
1206 if (!CHECK_VALID_OPS(h_ops, r))
1208 return h_ops->close_device(g_handle);
1211 static void haptic_poweroff_cb(GDBusConnection *conn,
1212 const gchar *sender,
1219 int type = POWER_OFF_NONE;
1221 struct timespec time = {0,};
1223 if (!dh_get_param_from_var(param, "(i)", &type)) {
1224 _E("Failed to get params from gvariant. expected:%s, type:%s", "(i)", g_variant_get_type_string(param));
1228 if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART)
1231 _D("Poweroff: %d", type);
1233 if (!CHECK_VALID_OPS(h_ops, ret)) {
1234 ret = haptic_module_load();
1240 haptic_internal_init();
1242 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
1243 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' vconf value.");
1246 level = (level/2) + 1;
1248 /* power off vibration */
1249 _I("Handle=%d dur=%dms pri=%d level=%d intensity=%d frequency=%d",
1250 g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, level,
1251 POWER_VIB_FEEDBACK * 100, haptic_default_data.frequency);
1252 ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, haptic_default_data.frequency, 0,
1253 level, POWER_VIB_FEEDBACK * 100, PRIORITY_HIGH);
1255 _E("Failed to vibrate_monotone: %d", ret);
1259 /* sleep for vibration */
1260 time.tv_nsec = POWER_OFF_VIB_DURATION * NANO_SECOND_MULTIPLIER;
1261 nanosleep(&time, NULL);
1265 static void sound_capturing_cb(keynode_t *key, void *data)
1269 status = vconf_keynode_get_int(key);
1271 /* if sound capture is in use, this value is 1(true). */
1272 if (status == VCONFKEY_RECORDER_STATE_RECORDING)
1278 static int parse_section(struct parse_result *result, void *user_data, int index)
1280 struct haptic_config *conf = (struct haptic_config *)user_data;
1285 if (!result->section || !result->name || !result->value)
1288 if (MATCH(result->name, "sound_capture")) {
1289 conf->sound_capture = atoi(result->value);
1290 } else if (MATCH(result->name, "level")) {
1291 conf->level = atoi(result->value);
1292 if (conf->level < 0 || conf->level >= INT_MAX - 1) {
1293 _E("You must set level with positive number in integer range.");
1296 conf->level_arr = calloc(sizeof(int), conf->level);
1297 if (!conf->level_arr) {
1298 _E("Failed to allocate memory for level.");
1301 } else if (MATCH(result->name, "value")) {
1304 conf->level_arr[index] = atoi(result->value);
1310 static int haptic_load_config(struct parse_result *result, void *user_data)
1312 struct haptic_config *conf = (struct haptic_config *)user_data;
1313 char name[NAME_MAX];
1320 if (!result->section || !result->name || !result->value)
1323 // Parsing 'Haptic' section
1324 if (MATCH(result->section, "Haptic")) {
1325 ret = parse_section(result, user_data, -1);
1327 _E("Failed to parse 'Haptic' section: %d", ret);
1333 // Parsing 'level' section
1334 for (index = 0; index < conf->level; ++index) {
1335 snprintf(name, sizeof(name), "level%d", index);
1336 if (MATCH(result->section, name)) {
1337 ret = parse_section(result, user_data, index);
1339 _E("Failed to parse 'level' section: %d", ret);
1350 static const dbus_method_s hdbus_methods[] = {
1351 { "GetCount", NULL, "i", hdbus_get_count }, // device_haptic_get_count
1352 { "OpenDevice", "i", "i", hdbus_open_device }, // device_haptic_open, feedback_initialize
1353 { "CloseDevice", "u", "i", hdbus_close_device }, // device_haptic_close, feedback_deinitialize
1354 { "StopDevice", "u", "i", hdbus_stop_device }, // device_haptic_stop, feedback_stop
1355 { "VibrateMonotone", "uiii", "i", hdbus_vibrate_monotone }, // device_haptic_vibrate
1356 { "VibratePattern", "usii", "i", hdbus_vibrate_pattern }, // feedback_play*
1357 { "ShowHandleList", NULL, NULL, hdbus_show_handle_list },
1358 { "IsSupported", "s", "i", hdbus_pattern_is_supported }, // feedback_is_supported_pattern
1359 /* Add methods here */
1362 static const dbus_interface_u dbus_interface = {
1363 .name = VIBRATOR_INTERFACE_HAPTIC,
1364 .methods = hdbus_methods,
1365 .nr_methods = ARRAY_SIZE(hdbus_methods),
1368 int haptic_probe(void)
1371 * load haptic module.
1372 * if there is no haptic module,
1373 * feedbackd does not activate a haptic interface.
1375 return haptic_module_load();
1378 guint id_sig_pwr_off_state;
1380 void haptic_init(void)
1384 /* get haptic data from configuration file */
1385 r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
1387 _E("Failed to load configuration file(%s): %d", HAPTIC_CONF_PATH, r);
1388 safe_free(haptic_conf.level_arr);
1391 /* init dbus interface */
1392 r = dbus_handle_register_dbus_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface);
1394 _E("Failed to init hdbus interface and method: %d", r);
1396 id_sig_pwr_off_state = subscribe_dbus_signal(NULL,
1397 DEVICED_PATH_POWEROFF,
1398 DEVICED_INTERFACE_POWEROFF,
1399 SIGNAL_POWEROFF_STATE,
1403 if (id_sig_pwr_off_state <= 0) {
1404 _E("Failed to register signal handler: %d", r);
1408 dbus_handle_emit_dbus_signal(NULL,
1409 VIBRATOR_PATH_HAPTIC,
1410 VIBRATOR_INTERFACE_HAPTIC,
1411 SIGNAL_VIBRATOR_INITIATED,
1414 /* add watch for sound capturing value */
1415 if (haptic_conf.sound_capture) {
1416 r = vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL);
1418 _W("Add watch for VCONFKEY_RECORDER_STATE failed.");
1421 /* Initialize vibration_handle (Use vibration now) */
1422 cur_h_data.handle = INVALID_HANDLE;
1423 cur_h_data.priority = PRIORITY_MIN;
1426 void haptic_exit(void)
1428 struct haptic_ops *ops;
1433 if (haptic_conf.sound_capture) {
1434 r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
1436 _W("Remove watch for VCONFKEY_RECORDER_STATE failed.");
1439 /* unregister notifier for below each event */
1440 unsubscribe_dbus_signal(NULL, id_sig_pwr_off_state);
1442 /* release haptic data memory */
1443 safe_free(haptic_conf.level_arr);
1445 if (!CHECK_VALID_OPS(h_ops, r))
1448 /* haptic exit for feedbackd */
1449 haptic_internal_exit();
1451 /* release plugin */
1452 DD_LIST_FOREACH(h_head, elem, ops) {
1453 if (ops->is_valid && ops->is_valid()) {
1462 static int haptic_start(void)
1465 haptic_disabled = false;
1469 static int haptic_stop(void)
1472 haptic_disabled = true;