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 HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf"
41 #define SIGNAL_POWEROFF_STATE "ChangeState"
42 #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator"
44 /* hardkey vibration variable */
45 #define HARDKEY_VIB_ITERATION 1
46 #define HARDKEY_VIB_FEEDBACK 3
47 #define HARDKEY_VIB_DURATION 30
48 #define HAPTIC_FEEDBACK_STEP 20
49 #define DEFAULT_FEEDBACK_LEVEL 3
50 #define HIGH_FEEDBACK_LEVEL 100
51 #define LOW_FEEDBACK_LEVEL 0
53 /* power on, power off vibration variable */
54 #define POWER_ON_VIB_DURATION 300
55 #define POWER_OFF_VIB_DURATION 300
56 #define POWER_VIB_FEEDBACK 100
58 #define MAX_EFFECT_BUFFER (64*1024)
60 #ifndef VCONFKEY_RECORDER_STATE
61 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
62 #define VCONFKEY_RECORDER_STATE_RECORDING 2
65 #define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV))
68 #define INTENSITY_BASE_RATE (10000)
69 #define VALUE_MAX_LEN 10
70 #define VIB_LOCK_TIMEOUT_MAX (300000) /* 5minutes */
73 1,A_W or A,A_W or 250D250W250D750W
80 struct vibration_config {
81 char *pattern; /* pattern name */
82 char *standard; /* assigned standard pattern name */
83 dd_list *data; /* duration_data list */
84 unsigned int pattern_duration;
88 struct duration_data {
105 dd_list *handle_list;
109 struct vibrate_pattern_info {
116 struct vibrate_monotone_info {
127 /* pattern configuration list */
128 static dd_list *vib_conf_list;
130 static guint duration_timer;
132 /* haptic operation variable */
133 static dd_list *h_head;
134 static dd_list *haptic_handle_list;
135 static const struct haptic_plugin_ops *h_ops;
136 static enum haptic_type h_type;
137 static bool haptic_disabled;
139 struct haptic_config {
145 static struct haptic_config haptic_conf;
147 static int haptic_start(void);
148 static int haptic_stop(void);
149 static int haptic_internal_init(void);
150 static int remove_haptic_info(struct haptic_info *info);
152 struct haptic_data cur_h_data;
154 void add_haptic(const struct haptic_ops *ops)
156 DD_LIST_APPEND(h_head, (void *)ops);
159 void remove_haptic(const struct haptic_ops *ops)
161 DD_LIST_REMOVE(h_head, (void *)ops);
164 static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
166 struct duration_data *data;
168 data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
170 _E("Not enough memory.");
173 memcpy(data, update, sizeof(struct duration_data));
174 /* insert vibration pattern data */
176 // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdrive, data->wait);
177 DD_LIST_APPEND(*conf_data, data);
181 static void get_pattern_property(char **iter, char property, int *value)
184 unsigned long int val;
186 check = strchr(*iter, property);
191 val = strtoul(*iter, NULL, 10);
192 if (errno == EINVAL || errno == ERANGE) {
194 _E("Failed to get value of %s: %d", *iter, errno);
196 if (val > VIB_LOCK_TIMEOUT_MAX)
197 val = VIB_LOCK_TIMEOUT_MAX;
204 /* [A]xxxDxxxIxxxFxxxOxxxW format */
205 static int insert_raw_data_format(dd_list **conf_data, char *value)
207 struct duration_data update = {0, };
210 int pattern_duration = 0;
213 return insert_conf_data(conf_data, &update);
215 _E("Invalid parameter: Configuration list is null");
220 end = iter + strlen(iter);
222 memset(&update, 0, sizeof(struct duration_data));
224 get_pattern_property(&iter, 'D', &update.duration);
225 get_pattern_property(&iter, 'I', &update.intensity);
226 if (update.intensity > INTENSITY_BASE_RATE)
227 update.intensity = INTENSITY_BASE_RATE;
228 get_pattern_property(&iter, 'F', &update.frequency);
229 get_pattern_property(&iter, 'W', &update.wait);
231 if (update.duration == 0 && update.wait == 0) {
232 _D("Pattern duration is zero.");
236 pattern_duration += (update.duration + update.wait);
237 if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
238 _D("Max pattern duration.");
239 pattern_duration = VIB_LOCK_TIMEOUT_MAX;
242 if (insert_conf_data(conf_data, &update) < 0)
246 return pattern_duration;
249 static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
251 static int duration = 0;
252 static int intensity = 0;
256 if (count > 4 || count <= 0) {
257 _E("Invalid parameter: count is invalid");
261 if (!packed || !val || !pattern_duration || !update) {
262 _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
266 get_pattern_property(&val, 'C', &value);
272 *pattern_duration += duration;
273 if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
274 _D("Max pattern duration.");
275 *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
279 if (value > INTENSITY_BASE_RATE)
280 value = INTENSITY_BASE_RATE;
282 if (*packed == false) {
283 update->duration = duration;
284 update->intensity = intensity;
287 /* if intensity is 0, duration use for wait(off) time */
289 update->wait = duration;
299 update->frequency = value;
302 if (intensity != 0) {
303 update->overdrive = value;
315 duration, intensity, frequency, overdrive
316 waiting duration, intensity=0, frequency, overdrive
322 static int load_standard_format(const char *pattern)
324 struct duration_data update = {0, };
326 struct vibration_config *conf;
327 int ret = 0, count = 0, end = 2;
330 char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
332 snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
333 fd = open(path, O_RDONLY);
337 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
339 _E("Failed to alloc.");
344 conf->pattern = strdup(pattern);
345 if (!conf->pattern) {
346 _E("Failed to copy pattern data(%s).", pattern);
351 /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
352 while (read(fd, &elem, 1) != 0) {
354 if (insert_conf_data(&conf->data, &update) < 0)
358 if (elem == 'e' || elem == 'n' || elem == 'd') {
371 ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
375 if (insert_conf_data(&conf->data, &update) < 0)
377 memset(&update, 0, sizeof(struct duration_data));
381 if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
384 _E("Pattern(%s) is out of bound: %s", pattern, val);
388 DD_LIST_APPEND(vib_conf_list, conf);
402 static int vibration_load_config(struct parse_result *result, void *user_data)
404 struct vibration_config *conf;
413 if (!MATCH(result->section, "Vibration"))
417 if (!result->name || !result->value)
420 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
422 _E("Failed to alloc.");
426 conf->pattern_duration = 0;
427 conf->pattern = strdup(result->name);
428 if (!conf->pattern) {
429 _E("Failed to copy pattern data(%s).", result->name);
433 value = result->value;
437 if (insert_raw_data_format(&conf->data, NULL) < 0)
439 DD_LIST_APPEND(vib_conf_list, conf);
443 /* Load Standard Pattern Name */
444 /* value: 1,A_W or A,A_W */
445 if ((check = strchr(value, ','))) {
447 if (strncmp(value, "A", 1) == 0)
450 conf->standard = strdup(value);
451 if (!conf->standard) {
452 _E("Failed to copy standard name.");
455 DD_LIST_APPEND(vib_conf_list, conf);
459 /* value : A100D or 100D0W or 250D250W250D750W */
460 /* Load Vibration Pattern Data */
461 check = strchr(value, 'A');
468 len = len - strlen(value) - 1;
471 duration = insert_raw_data_format(&conf->data, value);
473 conf->pattern_duration = 0;
476 conf->pattern_duration = duration;
477 DD_LIST_APPEND(vib_conf_list, conf);
486 free(conf->standard);
491 static void load_standard_vibration_patterns(void)
497 dir = opendir(STANDARD_FILE_PATH);
499 _E("Failed to load '%s' Use default value.", STANDARD_FILE_PATH);
502 while ((dent = readdir(dir))) {
503 if (dent->d_type == DT_DIR)
505 ret = load_standard_format(dent->d_name);
507 _E("Failed to parse %s: %d", dent->d_name, ret);
510 _D("Success to load '%s'", STANDARD_FILE_PATH);
513 void pattern_config_parse(void)
517 ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
519 _E("Failed to load '%s'. Use default value: %d", VIBRATION_CONF_PATH, ret);
521 load_standard_vibration_patterns();
524 static int haptic_module_load(void)
526 struct haptic_ops *ops;
530 pattern_config_parse();
531 /* find valid plugin */
532 DD_LIST_FOREACH(h_head, elem, ops) {
533 if (ops->is_valid && ops->is_valid()) {
541 if (!CHECK_VALID_OPS(h_ops, r)) {
542 _E("Can't find the valid haptic device.");
547 * we do not use internal vibration except power off.
548 * if the last handle is closed during the playing of vibration,
549 * solution makes unlimited vibration.
550 * so we need at least one handle. */
551 haptic_internal_init();
557 static int convert_magnitude_by_conf(int level)
561 if (level < LOW_FEEDBACK_LEVEL)
562 level = LOW_FEEDBACK_LEVEL;
563 else if (level > HIGH_FEEDBACK_LEVEL)
564 level = HIGH_FEEDBACK_LEVEL;
566 step = 100 / (haptic_conf.level-1);
567 for (i = 0; i < haptic_conf.level; ++i) {
568 if (level <= i*step) {
569 _D("Level changed. %d -> %d", level, haptic_conf.level_arr[i]);
570 return haptic_conf.level_arr[i];
574 _D("Play default level.");
575 return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP;
578 GVariant *hdbus_get_count(GDBusConnection *conn,
579 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
580 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
584 if (!CHECK_VALID_OPS(h_ops, ret))
587 ret = h_ops->get_device_count(&val);
592 return g_variant_new("(i)", ret);
595 void haptic_name_owner_changed(GDBusConnection *connection,
600 struct haptic_info *info = user_data;
603 _I("%s (sender=%s)", __func__, name);
608 for (n = info->handle_list; n; n = n->next) {
609 handle = (int)(long)n->data;
610 h_ops->stop_device(handle);
611 h_ops->close_device(handle);
614 remove_haptic_info(info);
617 static struct haptic_info *add_haptic_info(const char *sender)
619 struct haptic_info *info;
623 info = calloc(1, sizeof(struct haptic_info));
627 info->sender = strdup(sender);
633 DD_LIST_APPEND(haptic_handle_list, info);
635 info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL);
640 static int remove_haptic_info(struct haptic_info *info)
644 dbus_handle_unwatch_name(info->id_watch);
646 DD_LIST_REMOVE(haptic_handle_list, info);
647 DD_LIST_FREE_LIST(info->handle_list);
656 static struct haptic_info *get_matched_haptic_info(const char *sender)
659 struct haptic_info *info;
664 len = strlen(sender) + 1;
665 DD_LIST_FOREACH(haptic_handle_list, n, info) {
666 if (!strncmp(info->sender, sender, len))
673 GVariant *hdbus_open_device(GDBusConnection *conn,
674 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
675 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
678 int index, handle, ret;
679 struct haptic_info *info;
681 /* Load haptic module before booting done */
682 if (!CHECK_VALID_OPS(h_ops, ret)) {
683 ret = haptic_module_load();
688 g_variant_get(param, "(i)", &index);
690 ret = h_ops->open_device(index, &handle);
696 h_ops->close_device(handle);
700 info = get_matched_haptic_info(sender);
702 info = add_haptic_info(sender);
704 _E("Failed to create haptic information.");
706 h_ops->close_device(handle);
711 DD_LIST_APPEND(info->handle_list, (gpointer)(long)handle);
716 return g_variant_new("(i)", ret);
719 int clear_current_data(void)
721 cur_h_data.handle = INVALID_HANDLE;
722 cur_h_data.priority = PRIORITY_MIN;
724 if (duration_timer) {
725 _I("Remove duration_timer.");
726 g_source_remove(duration_timer);
733 GVariant *hdbus_close_device(GDBusConnection *conn,
734 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
735 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
739 struct haptic_info *info;
742 if (!CHECK_VALID_OPS(h_ops, ret))
745 g_variant_get(param, "(u)", &handle);
748 _E("Failed to get sender from dbus message.");
753 ret = h_ops->close_device(handle);
757 if (cur_h_data.handle == handle) {
758 /* Remove duration_timer for vibrate_effect */
759 clear_current_data();
762 info = get_matched_haptic_info(sender);
764 _E("Failed to find the matched haptic info.");
768 DD_LIST_REMOVE(info->handle_list, (gpointer)(long)handle);
769 cnt = DD_LIST_LENGTH(info->handle_list);
771 remove_haptic_info(info);
774 return g_variant_new("(i)", ret);
777 static gboolean _cb(void *data)
779 if (duration_timer) {
780 g_source_remove(duration_timer);
784 cur_h_data.handle = INVALID_HANDLE;
785 cur_h_data.priority = PRIORITY_MIN;
787 return G_SOURCE_REMOVE;
790 static void vibrate_monotone_idler_cb(void *data)
792 struct vibrate_monotone_info *vibrate_info;
798 vibrate_info = (struct vibrate_monotone_info *)data;
800 if (vibrate_info->priority < cur_h_data.priority) {
801 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
806 if (duration_timer) {
807 g_source_remove(duration_timer);
811 cur_h_data.vibration_data = NULL;
812 cur_h_data.handle = vibrate_info->handle;
813 cur_h_data.level = vibrate_info->level;
814 cur_h_data.priority = vibrate_info->priority;
815 cur_h_data.stop = false;
816 cur_h_data.unlimit = false;
818 ret = device_power_request_lock(POWER_LOCK_CPU, vibrate_info->duration);
819 if (ret != DEVICE_ERROR_NONE)
820 _E("Failed to request power lock.");
822 _D("Handle(%d) play=%dms, level=%d, intensity=%d, frequency=0)",
823 cur_h_data.handle, vibrate_info->duration, cur_h_data.level,
824 vibrate_info->intensity);
826 duration_timer = g_timeout_add(vibrate_info->duration, _cb, NULL);
827 h_ops->vibrate_monotone(cur_h_data.handle, vibrate_info->duration, 0, 0, cur_h_data.level, vibrate_info->intensity, cur_h_data.priority);
832 GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
833 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
834 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
836 struct vibrate_monotone_info *vibrate_info;
838 int duration, level, intensity, priority, ret = 0;
840 if (!CHECK_VALID_OPS(h_ops, ret))
846 g_variant_get(param, "(uiii)", &handle, &duration, &intensity, &priority);
847 _D("param (uiii): handle=%u, duration=%d, intensity=%d, priority=%d", handle, duration, intensity, priority);
854 if (priority < PRIORITY_MIN)
855 priority = PRIORITY_MIN;
856 else if (priority > PRIORITY_TOP)
857 priority = PRIORITY_TOP;
860 _E("Skip vibrate handle(%d) requested less than 0.", handle);
865 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
866 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' value.");
871 vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
873 _E("Failed to allocate memory for vibrate_info.");
878 vibrate_info->handle = handle;
879 vibrate_info->duration = duration;
880 vibrate_info->level = (level/2) + 1;
881 vibrate_info->intensity = intensity * 100; // 1~100 (API spec)
882 vibrate_info->priority = priority;
884 ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
886 return g_variant_new("(i)", ret);
889 static gboolean haptic_duration_play(void *data)
891 dd_list *head, *n, *next;
892 struct duration_data *node;
895 if (duration_timer) {
896 g_source_remove(duration_timer);
901 if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
902 head = cur_h_data.vibration_data;
904 cur_h_data.handle = INVALID_HANDLE;
905 cur_h_data.priority = PRIORITY_MIN;
909 head = (dd_list *)data;
911 if (cur_h_data.stop) {
912 _I("Stop currunt vibration.");
913 cur_h_data.stop = false;
914 cur_h_data.handle = INVALID_HANDLE;
915 cur_h_data.priority = PRIORITY_MIN;
919 DD_LIST_FOREACH_SAFE(head, n, next, node) {
920 _I("Handle(%d) play=%dms and Wait=%dms %s type. (level=%d, intensity=%d, frequency=%d)",
921 cur_h_data.handle, node->duration, node->wait,
922 cur_h_data.unlimit ? "Unlimit" : "Once", cur_h_data.level, node->intensity, node->frequency);
923 if ((node->duration + node->wait) <= 0) {
924 if (!cur_h_data.unlimit) {
925 cur_h_data.handle = INVALID_HANDLE;
926 cur_h_data.priority = PRIORITY_MIN;
929 next = cur_h_data.vibration_data;
934 duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
936 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);
941 _D("Auto stop vibration.");
942 cur_h_data.stop = true;
945 return G_SOURCE_REMOVE;
948 static void vibrate_pattern_idler_cb(void *data)
950 struct vibrate_pattern_info *vibrate_info;
952 struct vibration_config *conf;
953 char pattern[PATH_MAX];
960 vibrate_info = (struct vibrate_pattern_info *)data;
962 if (!(vibrate_info->pattern)) {
967 /* Same or higher priority pattern should be played */
968 if (vibrate_info->priority < cur_h_data.priority) {
969 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
973 snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
974 DD_LIST_FOREACH(vib_conf_list, elem, conf) {
977 if (strcmp(conf->pattern, pattern))
979 if (conf->standard) {
980 unlimit = conf->unlimit;
981 snprintf(pattern, sizeof(pattern), "%s", conf->standard);
986 cur_h_data.unlimit = unlimit;
988 cur_h_data.unlimit = conf->unlimit;
989 cur_h_data.vibration_data = conf->data;
990 cur_h_data.handle = vibrate_info->handle;
991 cur_h_data.level = vibrate_info->level;
992 cur_h_data.priority = vibrate_info->priority;
993 cur_h_data.stop = false;
994 _I("Handle(%d) play=%s pri=%d %s", cur_h_data.handle, conf->pattern, cur_h_data.priority,
995 cur_h_data.unlimit ? "Unlimit" : "Once");
997 if (conf->pattern_duration <= 0)
1000 if (!cur_h_data.unlimit && conf->pattern_duration > 0) {
1001 ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration);
1002 if (ret != DEVICE_ERROR_NONE)
1003 _E("Failed to request power lock.");
1005 haptic_duration_play((void *)cur_h_data.vibration_data);
1008 _E("Handle(%d) %s is not supported.", vibrate_info->handle, pattern);
1011 free(vibrate_info->pattern);
1015 GVariant *hdbus_vibrate_pattern(GDBusConnection *conn,
1016 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1017 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1019 struct vibrate_pattern_info *vibrate_info;
1020 unsigned int handle;
1021 char *pattern = NULL;
1022 int level, priority, ret = 0;
1024 if (!CHECK_VALID_OPS(h_ops, ret))
1027 if (haptic_disabled)
1030 g_variant_get(param, "(usii)", &handle, &pattern, &level, &priority);
1037 if (priority < PRIORITY_MIN)
1038 priority = PRIORITY_MIN;
1039 else if (priority > PRIORITY_TOP)
1040 priority = PRIORITY_TOP;
1042 vibrate_info = calloc(1, sizeof(struct vibrate_pattern_info));
1043 if (!vibrate_info) {
1044 _E("Failed to allocate memory for vibrate_info.");
1048 vibrate_info->handle = handle;
1049 vibrate_info->pattern = pattern;
1051 if (!vibrate_info->pattern) {
1052 _E("Failed to allocate memory for pattern.");
1057 vibrate_info->level = level;
1058 vibrate_info->priority = priority;
1060 ret = add_idle_request(vibrate_pattern_idler_cb, (void *)vibrate_info);
1064 return g_variant_new("(i)", ret);
1067 GVariant *hdbus_stop_device(GDBusConnection *conn,
1068 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1069 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1071 unsigned int handle;
1074 if (!CHECK_VALID_OPS(h_ops, ret))
1077 if (haptic_disabled) {
1078 _I("Haptic disabled.");
1082 g_variant_get(param, "(u)", &handle);
1084 if (cur_h_data.handle != handle) {
1085 _D("Not the request from current vibration handle(%d). Skip.", handle);
1089 ret = h_ops->stop_device(handle);
1090 _I("Stop the device(handle=%u) :%d", handle, ret);
1092 /* Remove duration_timer for vibrate_effect */
1093 clear_current_data();
1096 return g_variant_new("(i)", ret);
1099 GVariant *hdbus_show_handle_list(GDBusConnection *conn,
1100 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1101 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1105 struct haptic_info *info;
1107 _D("Sender Handle");
1108 DD_LIST_FOREACH(haptic_handle_list, n, info) {
1109 for (elem = info->handle_list; elem; elem = elem->next)
1110 _D("%s %d", info->sender, (int)(long)elem->data);
1113 return g_variant_new_tuple(NULL, 0);
1116 int pattern_is_supported(const char *pattern)
1119 struct vibration_config *conf;
1126 DD_LIST_FOREACH(vib_conf_list, elem, conf) {
1129 if (!strcmp(conf->pattern, pattern)) {
1138 GVariant *hdbus_pattern_is_supported(GDBusConnection *conn,
1139 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1140 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1146 if (!CHECK_VALID_OPS(h_ops, ret))
1149 if (haptic_disabled)
1152 g_variant_get(param, "(s)", &data);
1154 ret = pattern_is_supported(data);
1156 _I("%s is supported: %d", data, ret);
1160 return g_variant_new("(i)", ret);
1163 static int haptic_internal_init(void)
1166 if (!CHECK_VALID_OPS(h_ops, r))
1168 return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle);
1171 static int haptic_internal_exit(void)
1174 if (!CHECK_VALID_OPS(h_ops, r))
1176 return h_ops->close_device(g_handle);
1179 static void haptic_poweroff_cb(GDBusConnection *conn,
1180 const gchar *sender,
1187 int type = POWER_OFF_NONE;
1189 struct timespec time = {0,};
1191 if (!g_variant_get_safe(param, "(i)", &type)) {
1192 _E("Failed to get params from gvariant. expected:%s, type:%s", "(i)", g_variant_get_type_string(param));
1196 if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART)
1199 _D("Poweroff: %d", type);
1201 if (!CHECK_VALID_OPS(h_ops, ret)) {
1202 ret = haptic_module_load();
1208 haptic_internal_init();
1210 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
1211 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' vconf value.");
1214 level = (level/2) + 1;
1216 /* power off vibration */
1217 _I("Handle=%d dur=%dms pri=%d level=%d intensity=%d frequency=0",
1218 g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, level,
1219 POWER_VIB_FEEDBACK * 100);
1220 ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, 0, 0,
1221 level, POWER_VIB_FEEDBACK * 100, PRIORITY_HIGH);
1223 _E("Failed to vibrate_monotone: %d", ret);
1227 /* sleep for vibration */
1228 time.tv_nsec = POWER_OFF_VIB_DURATION * NANO_SECOND_MULTIPLIER;
1229 nanosleep(&time, NULL);
1233 static void sound_capturing_cb(keynode_t *key, void *data)
1237 status = vconf_keynode_get_int(key);
1239 /* if sound capture is in use, this value is 1(true). */
1240 if (status == VCONFKEY_RECORDER_STATE_RECORDING)
1246 static int parse_section(struct parse_result *result, void *user_data, int index)
1248 struct haptic_config *conf = (struct haptic_config *)user_data;
1253 if (!result->section || !result->name || !result->value)
1256 if (MATCH(result->name, "sound_capture")) {
1257 conf->sound_capture = atoi(result->value);
1258 } else if (MATCH(result->name, "level")) {
1259 conf->level = atoi(result->value);
1260 if (conf->level < 0 || conf->level >= INT_MAX - 1) {
1261 _E("You must set level with positive number in integer range.");
1264 conf->level_arr = calloc(sizeof(int), conf->level);
1265 if (!conf->level_arr) {
1266 _E("Failed to allocate memory for level.");
1269 } else if (MATCH(result->name, "value")) {
1272 conf->level_arr[index] = atoi(result->value);
1278 static int haptic_load_config(struct parse_result *result, void *user_data)
1280 struct haptic_config *conf = (struct haptic_config *)user_data;
1281 char name[NAME_MAX];
1288 if (!result->section || !result->name || !result->value)
1291 // Parsing 'Haptic' section
1292 if (MATCH(result->section, "Haptic")) {
1293 ret = parse_section(result, user_data, -1);
1295 _E("Failed to parse 'Haptic' section: %d", ret);
1301 // Parsing 'level' section
1302 for (index = 0; index < conf->level; ++index) {
1303 snprintf(name, sizeof(name), "level%d", index);
1304 if (MATCH(result->section, name)) {
1305 ret = parse_section(result, user_data, index);
1307 _E("Failed to parse 'level' section: %d", ret);
1318 static const dbus_method_s hdbus_methods[] = {
1319 { "GetCount", NULL, "i", hdbus_get_count }, // device_haptic_get_count
1320 { "OpenDevice", "i", "i", hdbus_open_device }, // device_haptic_open, feedback_initialize
1321 { "CloseDevice", "u", "i", hdbus_close_device }, // device_haptic_close, feedback_deinitialize
1322 { "StopDevice", "u", "i", hdbus_stop_device }, // device_haptic_stop, feedback_stop
1323 { "VibrateMonotone", "uiii", "i", hdbus_vibrate_monotone }, // device_haptic_vibrate
1324 { "VibratePattern", "usii", "i", hdbus_vibrate_pattern }, // feedback_play*
1325 { "ShowHandleList", NULL, NULL, hdbus_show_handle_list },
1326 { "IsSupported", "s", "i", hdbus_pattern_is_supported }, // feedback_is_supported_pattern
1327 /* Add methods here */
1330 static const dbus_interface_u dbus_interface = {
1331 .name = VIBRATOR_INTERFACE_HAPTIC,
1332 .methods = hdbus_methods,
1333 .nr_methods = ARRAY_SIZE(hdbus_methods),
1336 int haptic_probe(void)
1339 * load haptic module.
1340 * if there is no haptic module,
1341 * feedbackd does not activate a haptic interface.
1343 return haptic_module_load();
1346 static guint id_sig_pwr_off_state;
1348 void haptic_init(void)
1352 /* get haptic data from configuration file */
1353 r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
1355 _E("Failed to load configuration file(%s): %d", HAPTIC_CONF_PATH, r);
1356 safe_free(haptic_conf.level_arr);
1359 /* init dbus interface */
1360 r = dbus_handle_register_dbus_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface);
1362 _E("Failed to init hdbus interface and method: %d", r);
1364 id_sig_pwr_off_state = subscribe_dbus_signal(NULL,
1365 DEVICED_PATH_POWEROFF,
1366 DEVICED_INTERFACE_POWEROFF,
1367 SIGNAL_POWEROFF_STATE,
1371 if (id_sig_pwr_off_state <= 0) {
1372 _E("Failed to register signal handler: %d", r);
1376 dbus_handle_emit_dbus_signal(NULL,
1377 VIBRATOR_PATH_HAPTIC,
1378 VIBRATOR_INTERFACE_HAPTIC,
1379 SIGNAL_VIBRATOR_INITIATED,
1382 /* add watch for sound capturing value */
1383 if (haptic_conf.sound_capture) {
1384 r = vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL);
1386 _W("Add watch for VCONFKEY_RECORDER_STATE failed.");
1389 /* Initialize vibration_handle (Use vibration now) */
1390 cur_h_data.handle = INVALID_HANDLE;
1391 cur_h_data.priority = PRIORITY_MIN;
1394 void haptic_exit(void)
1396 struct haptic_ops *ops;
1401 if (haptic_conf.sound_capture) {
1402 r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
1404 _W("Remove watch for VCONFKEY_RECORDER_STATE failed.");
1407 /* unregister notifier for below each event */
1408 unsubscribe_dbus_signal(NULL, id_sig_pwr_off_state);
1410 /* release haptic data memory */
1411 safe_free(haptic_conf.level_arr);
1413 if (!CHECK_VALID_OPS(h_ops, r))
1416 /* haptic exit for feedbackd */
1417 haptic_internal_exit();
1419 /* release plugin */
1420 DD_LIST_FOREACH(h_head, elem, ops) {
1421 if (ops->is_valid && ops->is_valid()) {
1430 static int haptic_start(void)
1433 haptic_disabled = false;
1437 static int haptic_stop(void)
1440 haptic_disabled = true;