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/libgdbus.h>
28 #include <libsyscommon/list.h>
29 #include <libsyscommon/ini-parser.h>
30 #include <hal/device/hal-haptic.h>
32 #include "shared/log.h"
33 #include "shared/common.h"
34 #include "shared/device-idler.h"
37 #define FEEDBACK_BASE_PATH "/usr/share/feedback/"
38 #define STANDARD_FILE_PATH FEEDBACK_BASE_PATH"vibration/"
39 #define VIBRATION_CONF_PATH FEEDBACK_BASE_PATH"vibration.conf"
41 #define HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf"
42 #define SIGNAL_POWEROFF_STATE "ChangeState"
43 #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator"
45 /* hardkey vibration variable */
46 #define HARDKEY_VIB_ITERATION 1
47 #define HARDKEY_VIB_FEEDBACK 3
48 #define HARDKEY_VIB_DURATION 30
49 #define HAPTIC_FEEDBACK_STEP 20
50 #define DEFAULT_FEEDBACK_LEVEL 3
51 #define HIGH_FEEDBACK_LEVEL 100
52 #define LOW_FEEDBACK_LEVEL 0
54 /* power on, power off vibration variable */
55 #define POWER_ON_VIB_DURATION 300
56 #define POWER_OFF_VIB_DURATION 300
57 #define POWER_VIB_FEEDBACK 100
59 #define MAX_EFFECT_BUFFER (64*1024)
61 #ifndef VCONFKEY_RECORDER_STATE
62 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
63 #define VCONFKEY_RECORDER_STATE_RECORDING 2
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 GList *data; /* duration_data list */
84 unsigned int pattern_duration;
88 struct duration_data {
109 struct vibrate_pattern_info {
116 struct vibrate_monotone_info {
127 /* pattern configuration list */
128 static GList *vib_conf_list;
130 static guint duration_timer;
132 /* haptic operation variable */
133 static GList *haptic_handle_list;
135 static bool haptic_disabled;
137 struct haptic_config {
143 static struct haptic_config haptic_conf;
145 static int haptic_start(void);
146 static int haptic_stop(void);
147 static int remove_haptic_info(struct haptic_info *info);
149 struct haptic_data cur_h_data;
151 static int insert_conf_data(GList **conf_data, struct duration_data *update)
153 struct duration_data *data;
155 data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
157 _E("Not enough memory.");
160 memcpy(data, update, sizeof(struct duration_data));
161 /* insert vibration pattern data */
163 // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdrive, data->wait);
164 SYS_G_LIST_APPEND(*conf_data, data);
168 static void get_pattern_property(char **iter, char property, int *value)
171 unsigned long int val;
173 check = strchr(*iter, property);
178 val = strtoul(*iter, NULL, 10);
179 if (errno == EINVAL || errno == ERANGE) {
181 _E("Failed to get value of %s: %d", *iter, errno);
183 if (val > VIB_LOCK_TIMEOUT_MAX)
184 val = VIB_LOCK_TIMEOUT_MAX;
191 /* [A]xxxDxxxIxxxFxxxOxxxW format */
192 static int insert_raw_data_format(GList **conf_data, char *value)
194 struct duration_data update = {0, };
197 int pattern_duration = 0;
200 return insert_conf_data(conf_data, &update);
202 _E("Invalid parameter: Configuration list is null");
207 end = iter + strlen(iter);
209 memset(&update, 0, sizeof(struct duration_data));
211 get_pattern_property(&iter, 'D', &update.duration);
212 get_pattern_property(&iter, 'I', &update.intensity);
213 if (update.intensity > INTENSITY_BASE_RATE)
214 update.intensity = INTENSITY_BASE_RATE;
215 get_pattern_property(&iter, 'F', &update.frequency);
216 get_pattern_property(&iter, 'W', &update.wait);
218 if (update.duration == 0 && update.wait == 0) {
219 _D("Pattern duration is zero.");
223 pattern_duration += (update.duration + update.wait);
224 if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
225 _D("Max pattern duration.");
226 pattern_duration = VIB_LOCK_TIMEOUT_MAX;
229 if (insert_conf_data(conf_data, &update) < 0)
233 return pattern_duration;
236 static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
238 static int duration = 0;
239 static int intensity = 0;
243 if (count > 4 || count <= 0) {
244 _E("Invalid parameter: count is invalid");
248 if (!packed || !val || !pattern_duration || !update) {
249 _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
253 get_pattern_property(&val, 'C', &value);
259 *pattern_duration += duration;
260 if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
261 _D("Max pattern duration.");
262 *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
266 if (value > INTENSITY_BASE_RATE)
267 value = INTENSITY_BASE_RATE;
269 if (*packed == false) {
270 update->duration = duration;
271 update->intensity = intensity;
274 /* if intensity is 0, duration use for wait(off) time */
276 update->wait = duration;
286 update->frequency = value;
289 if (intensity != 0) {
290 update->overdrive = value;
302 duration, intensity, frequency, overdrive
303 waiting duration, intensity=0, frequency, overdrive
309 static int load_standard_format(const char *pattern)
311 struct duration_data update = {0, };
313 struct vibration_config *conf;
314 int ret = 0, count = 0, end = 2;
317 char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
319 snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
320 fd = open(path, O_RDONLY);
324 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
326 _E("Failed to alloc.");
331 conf->pattern = strdup(pattern);
332 if (!conf->pattern) {
333 _E("Failed to copy pattern data(%s).", pattern);
338 /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
339 while (read(fd, &elem, 1) != 0) {
341 if (insert_conf_data(&conf->data, &update) < 0)
345 if (elem == 'e' || elem == 'n' || elem == 'd') {
358 ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
362 if (insert_conf_data(&conf->data, &update) < 0)
364 memset(&update, 0, sizeof(struct duration_data));
368 if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
371 _E("Pattern(%s) is out of bound: %s", pattern, val);
375 SYS_G_LIST_APPEND(vib_conf_list, conf);
389 static int vibration_load_config(struct parse_result *result, void *user_data)
391 struct vibration_config *conf;
400 if (!MATCH(result->section, "Vibration"))
404 if (!result->name || !result->value)
407 conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
409 _E("Failed to alloc.");
413 conf->pattern_duration = 0;
414 conf->pattern = strdup(result->name);
415 if (!conf->pattern) {
416 _E("Failed to copy pattern data(%s).", result->name);
420 value = result->value;
424 if (insert_raw_data_format(&conf->data, NULL) < 0)
426 SYS_G_LIST_APPEND(vib_conf_list, conf);
430 /* Load Standard Pattern Name */
431 /* value: 1,A_W or A,A_W */
432 if ((check = strchr(value, ','))) {
434 if (strncmp(value, "A", 1) == 0)
437 conf->standard = strdup(value);
438 if (!conf->standard) {
439 _E("Failed to copy standard name.");
442 SYS_G_LIST_APPEND(vib_conf_list, conf);
446 /* value : A100D or 100D0W or 250D250W250D750W */
447 /* Load Vibration Pattern Data */
448 check = strchr(value, 'A');
455 len = len - strlen(value) - 1;
458 duration = insert_raw_data_format(&conf->data, value);
460 conf->pattern_duration = 0;
463 conf->pattern_duration = duration;
464 SYS_G_LIST_APPEND(vib_conf_list, conf);
473 free(conf->standard);
478 static void load_standard_vibration_patterns(void)
484 dir = opendir(STANDARD_FILE_PATH);
486 _E("Failed to load '%s' Use default value.", STANDARD_FILE_PATH);
489 while ((dent = readdir(dir))) {
490 if (dent->d_type == DT_DIR)
492 ret = load_standard_format(dent->d_name);
494 _E("Failed to parse %s: %d", dent->d_name, ret);
497 _D("Success to load '%s'", STANDARD_FILE_PATH);
500 void pattern_config_parse(void)
504 ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
506 _E("Failed to load '%s'. Use default value: %d", VIBRATION_CONF_PATH, ret);
508 load_standard_vibration_patterns();
511 static int haptic_module_load(void)
515 pattern_config_parse();
517 r = hal_device_haptic_get_backend();
519 _E("Failed to load device. ret=%d", r);
524 * we do not use internal vibration except power off.
525 * if the last handle is closed during the playing of vibration,
526 * solution makes unlimited vibration.
527 * so we need at least one handle. */
528 r = hal_device_haptic_open_device(&g_handle);
530 _E("Failed to open device. ret=%d", r);
538 static int convert_magnitude_by_conf(int level)
542 if (level < LOW_FEEDBACK_LEVEL)
543 level = LOW_FEEDBACK_LEVEL;
544 else if (level > HIGH_FEEDBACK_LEVEL)
545 level = HIGH_FEEDBACK_LEVEL;
547 step = 100 / (haptic_conf.level-1);
548 for (i = 0; i < haptic_conf.level; ++i) {
549 if (level <= i*step) {
550 _D("Level changed. %d -> %d", level, haptic_conf.level_arr[i]);
551 return haptic_conf.level_arr[i];
555 _D("Play default level.");
556 return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP;
559 GVariant *hdbus_get_count(GDBusConnection *conn,
560 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
561 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
565 ret = hal_device_haptic_get_device_count(&val);
569 return g_variant_new("(i)", ret);
572 void haptic_name_owner_changed(GDBusConnection *connection,
577 struct haptic_info *info = user_data;
580 _I("%s (sender=%s)", __func__, name);
585 for (n = info->handle_list; n; n = n->next) {
586 handle = (int)(long)n->data;
587 hal_device_haptic_stop_device(handle);
588 hal_device_haptic_close_device(handle);
591 remove_haptic_info(info);
594 static struct haptic_info *add_haptic_info(const char *sender)
596 struct haptic_info *info;
600 info = calloc(1, sizeof(struct haptic_info));
604 info->sender = strdup(sender);
610 SYS_G_LIST_APPEND(haptic_handle_list, info);
612 info->id_watch = gdbus_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL);
617 static int remove_haptic_info(struct haptic_info *info)
621 gdbus_unwatch_name(info->id_watch);
623 SYS_G_LIST_REMOVE(haptic_handle_list, info);
624 SYS_G_LIST_FREE_LIST(info->handle_list);
633 static struct haptic_info *get_matched_haptic_info(const char *sender)
636 struct haptic_info *info;
641 len = strlen(sender) + 1;
642 SYS_G_LIST_FOREACH(haptic_handle_list, n, info) {
643 if (!strncmp(info->sender, sender, len))
650 GVariant *hdbus_open_device(GDBusConnection *conn,
651 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
652 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
654 int index, handle, ret;
655 struct haptic_info *info;
657 /* Load haptic module before booting done */
658 if (hal_device_haptic_check_backend() < 0) {
659 ret = hal_device_haptic_get_backend();
664 g_variant_get(param, "(i)", &index);
666 ret = hal_device_haptic_open_device(&handle);
672 hal_device_haptic_close_device(handle);
676 info = get_matched_haptic_info(sender);
678 info = add_haptic_info(sender);
680 _E("Failed to create haptic information.");
682 hal_device_haptic_close_device(handle);
687 SYS_G_LIST_APPEND(info->handle_list, (gpointer)(long)handle);
692 return g_variant_new("(i)", ret);
695 int clear_current_data(void)
697 cur_h_data.handle = INVALID_HANDLE;
698 cur_h_data.priority = PRIORITY_MIN;
700 if (duration_timer) {
701 _I("Remove duration_timer.");
702 g_source_remove(duration_timer);
709 GVariant *hdbus_close_device(GDBusConnection *conn,
710 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
711 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
715 struct haptic_info *info;
718 g_variant_get(param, "(u)", &handle);
721 _E("Failed to get sender from dbus message.");
726 ret = hal_device_haptic_close_device(handle);
730 if (cur_h_data.handle == handle) {
731 /* Remove duration_timer for vibrate_effect */
732 clear_current_data();
735 info = get_matched_haptic_info(sender);
737 _E("Failed to find the matched haptic info.");
741 SYS_G_LIST_REMOVE(info->handle_list, (gpointer)(long)handle);
742 cnt = SYS_G_LIST_LENGTH(info->handle_list);
744 remove_haptic_info(info);
747 return g_variant_new("(i)", ret);
750 static gboolean _cb(void *data)
752 if (duration_timer) {
753 g_source_remove(duration_timer);
757 cur_h_data.handle = INVALID_HANDLE;
758 cur_h_data.priority = PRIORITY_MIN;
760 return G_SOURCE_REMOVE;
763 static void vibrate_monotone_idler_cb(void *data)
765 struct vibrate_monotone_info *vibrate_info;
771 vibrate_info = (struct vibrate_monotone_info *)data;
773 if (vibrate_info->priority < cur_h_data.priority) {
774 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
779 if (duration_timer) {
780 g_source_remove(duration_timer);
784 cur_h_data.vibration_data = NULL;
785 cur_h_data.handle = vibrate_info->handle;
786 cur_h_data.level = vibrate_info->level;
787 cur_h_data.priority = vibrate_info->priority;
788 cur_h_data.stop = false;
789 cur_h_data.unlimit = false;
791 ret = device_power_request_lock(POWER_LOCK_CPU, vibrate_info->duration);
792 if (ret != DEVICE_ERROR_NONE)
793 _E("Failed to request power lock.");
795 _D("Handle(%d) play=%dms, level=%d, intensity=%d, frequency=0)",
796 cur_h_data.handle, vibrate_info->duration, cur_h_data.level,
797 vibrate_info->intensity);
799 duration_timer = g_timeout_add(vibrate_info->duration, _cb, NULL);
800 hal_device_haptic_vibrate(cur_h_data.handle, vibrate_info->duration, 0, 0, cur_h_data.level, vibrate_info->intensity, cur_h_data.priority);
805 GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
806 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
807 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
809 struct vibrate_monotone_info *vibrate_info;
811 int duration, level, intensity, priority, ret = 0;
813 if ((ret = hal_device_haptic_check_backend()) < 0)
819 g_variant_get(param, "(uiii)", &handle, &duration, &intensity, &priority);
820 _D("param (uiii): handle=%u, duration=%d, intensity=%d, priority=%d", handle, duration, intensity, priority);
827 if (priority < PRIORITY_MIN)
828 priority = PRIORITY_MIN;
829 else if (priority > PRIORITY_TOP)
830 priority = PRIORITY_TOP;
833 _E("Skip vibrate handle(%d) requested less than 0.", handle);
838 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
839 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' value.");
844 vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
846 _E("Failed to allocate memory for vibrate_info.");
851 vibrate_info->handle = handle;
852 vibrate_info->duration = duration;
853 vibrate_info->level = (level/2) + 1;
854 vibrate_info->intensity = intensity * 100; // 1~100 (API spec)
855 vibrate_info->priority = priority;
857 ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
859 return g_variant_new("(i)", ret);
862 static gboolean haptic_duration_play(void *data)
864 GList *head, *n, *next;
865 struct duration_data *node;
868 if (duration_timer) {
869 g_source_remove(duration_timer);
874 if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
875 head = cur_h_data.vibration_data;
877 cur_h_data.handle = INVALID_HANDLE;
878 cur_h_data.priority = PRIORITY_MIN;
882 head = (GList *)data;
884 if (cur_h_data.stop) {
885 _I("Stop currunt vibration.");
886 cur_h_data.stop = false;
887 cur_h_data.handle = INVALID_HANDLE;
888 cur_h_data.priority = PRIORITY_MIN;
892 SYS_G_LIST_FOREACH_SAFE(head, n, next, node) {
893 _I("Handle(%d) play=%dms and Wait=%dms %s type. (level=%d, intensity=%d, frequency=%d)",
894 cur_h_data.handle, node->duration, node->wait,
895 cur_h_data.unlimit ? "Unlimit" : "Once", cur_h_data.level, node->intensity, node->frequency);
896 if ((node->duration + node->wait) <= 0) {
897 if (!cur_h_data.unlimit) {
898 cur_h_data.handle = INVALID_HANDLE;
899 cur_h_data.priority = PRIORITY_MIN;
902 next = cur_h_data.vibration_data;
907 duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
909 ret = hal_device_haptic_vibrate(cur_h_data.handle, node->duration, node->frequency, node->overdrive, cur_h_data.level, node->intensity, cur_h_data.priority);
914 _D("Auto stop vibration.");
915 cur_h_data.stop = true;
918 return G_SOURCE_REMOVE;
921 static void vibrate_pattern_idler_cb(void *data)
923 struct vibrate_pattern_info *vibrate_info;
925 struct vibration_config *conf;
926 char pattern[PATH_MAX];
933 vibrate_info = (struct vibrate_pattern_info *)data;
935 if (!(vibrate_info->pattern)) {
940 /* Same or higher priority pattern should be played */
941 if (vibrate_info->priority < cur_h_data.priority) {
942 _I("Handle(%d) skip low priority. pre=%d now=%d", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
946 snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
947 SYS_G_LIST_FOREACH(vib_conf_list, elem, conf) {
950 if (strcmp(conf->pattern, pattern))
952 if (conf->standard) {
953 unlimit = conf->unlimit;
954 snprintf(pattern, sizeof(pattern), "%s", conf->standard);
959 cur_h_data.unlimit = unlimit;
961 cur_h_data.unlimit = conf->unlimit;
962 cur_h_data.vibration_data = conf->data;
963 cur_h_data.handle = vibrate_info->handle;
964 cur_h_data.level = vibrate_info->level;
965 cur_h_data.priority = vibrate_info->priority;
966 cur_h_data.stop = false;
967 _I("Handle(%d) play=%s pri=%d %s", cur_h_data.handle, conf->pattern, cur_h_data.priority,
968 cur_h_data.unlimit ? "Unlimit" : "Once");
970 if (conf->pattern_duration <= 0)
973 if (!cur_h_data.unlimit && conf->pattern_duration > 0) {
974 ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration);
975 if (ret != DEVICE_ERROR_NONE)
976 _E("Failed to request power lock.");
978 haptic_duration_play((void *)cur_h_data.vibration_data);
981 _E("Handle(%d) %s is not supported.", vibrate_info->handle, pattern);
984 free(vibrate_info->pattern);
988 GVariant *hdbus_vibrate_pattern(GDBusConnection *conn,
989 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
990 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
992 struct vibrate_pattern_info *vibrate_info;
994 char *pattern = NULL;
995 int level, priority, ret = 0;
997 if ((ret = hal_device_haptic_check_backend()) < 0)
1000 if (haptic_disabled)
1003 g_variant_get(param, "(usii)", &handle, &pattern, &level, &priority);
1010 if (priority < PRIORITY_MIN)
1011 priority = PRIORITY_MIN;
1012 else if (priority > PRIORITY_TOP)
1013 priority = PRIORITY_TOP;
1015 vibrate_info = calloc(1, sizeof(struct vibrate_pattern_info));
1016 if (!vibrate_info) {
1017 _E("Failed to allocate memory for vibrate_info.");
1021 vibrate_info->handle = handle;
1022 vibrate_info->pattern = pattern;
1024 if (!vibrate_info->pattern) {
1025 _E("Failed to allocate memory for pattern.");
1030 vibrate_info->level = level;
1031 vibrate_info->priority = priority;
1033 ret = add_idle_request(vibrate_pattern_idler_cb, (void *)vibrate_info);
1037 return g_variant_new("(i)", ret);
1040 GVariant *hdbus_stop_device(GDBusConnection *conn,
1041 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1042 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1044 unsigned int handle;
1047 if ((ret = hal_device_haptic_check_backend()) < 0)
1050 if (haptic_disabled) {
1051 _I("Haptic disabled.");
1055 g_variant_get(param, "(u)", &handle);
1057 if (cur_h_data.handle != handle) {
1058 _D("Not the request from current vibration handle(%d). Skip.", handle);
1062 ret = hal_device_haptic_stop_device(handle);
1063 _I("Stop the device(handle=%u) :%d", handle, ret);
1065 /* Remove duration_timer for vibrate_effect */
1066 clear_current_data();
1069 return g_variant_new("(i)", ret);
1072 GVariant *hdbus_show_handle_list(GDBusConnection *conn,
1073 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1074 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1078 struct haptic_info *info;
1080 _D("Sender Handle");
1081 SYS_G_LIST_FOREACH(haptic_handle_list, n, info) {
1082 for (elem = info->handle_list; elem; elem = elem->next)
1083 _D("%s %d", info->sender, (int)(long)elem->data);
1086 return g_variant_new_tuple(NULL, 0);
1089 int pattern_is_supported(const char *pattern)
1092 struct vibration_config *conf;
1099 SYS_G_LIST_FOREACH(vib_conf_list, elem, conf) {
1102 if (!strcmp(conf->pattern, pattern)) {
1111 GVariant *hdbus_pattern_is_supported(GDBusConnection *conn,
1112 const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
1113 GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
1119 if ((ret = hal_device_haptic_check_backend()) < 0)
1122 if (haptic_disabled)
1125 g_variant_get(param, "(s)", &data);
1127 ret = pattern_is_supported(data);
1129 _I("%s is supported: %d", data, ret);
1133 return g_variant_new("(i)", ret);
1136 static void haptic_poweroff_cb(GDBusConnection *conn,
1137 const gchar *sender,
1144 int type = POWER_OFF_NONE;
1146 struct timespec time = {0,};
1148 if (!g_variant_get_safe(param, "(i)", &type)) {
1149 _E("Failed to get params from gvariant. expected:%s, type:%s", "(i)", g_variant_get_type_string(param));
1153 if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART)
1156 _D("Poweroff: %d", type);
1158 if (hal_device_haptic_check_backend() < 0) {
1159 if (haptic_module_load() < 0)
1164 if (hal_device_haptic_open_device(&g_handle) < 0)
1168 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
1169 _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' vconf value.");
1172 level = (level/2) + 1;
1174 /* power off vibration */
1175 _I("Handle=%d dur=%dms pri=%d level=%d intensity=%d frequency=0",
1176 g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, level,
1177 POWER_VIB_FEEDBACK * 100);
1178 ret = hal_device_haptic_vibrate(g_handle, POWER_OFF_VIB_DURATION, 0, 0,
1179 level, POWER_VIB_FEEDBACK * 100, PRIORITY_HIGH);
1181 _E("Failed to vibrate_monotone: %d", ret);
1185 /* sleep for vibration */
1186 time.tv_nsec = POWER_OFF_VIB_DURATION * NANO_SECOND_MULTIPLIER;
1187 nanosleep(&time, NULL);
1191 static void sound_capturing_cb(keynode_t *key, void *data)
1195 status = vconf_keynode_get_int(key);
1197 /* if sound capture is in use, this value is 1(true). */
1198 if (status == VCONFKEY_RECORDER_STATE_RECORDING)
1204 static int parse_section(struct parse_result *result, void *user_data, int index)
1206 struct haptic_config *conf = (struct haptic_config *)user_data;
1211 if (!result->section || !result->name || !result->value)
1214 if (MATCH(result->name, "sound_capture")) {
1215 conf->sound_capture = atoi(result->value);
1216 } else if (MATCH(result->name, "level")) {
1217 conf->level = atoi(result->value);
1218 if (conf->level < 0 || conf->level >= INT_MAX - 1) {
1219 _E("You must set level with positive number in integer range.");
1222 conf->level_arr = calloc(sizeof(int), conf->level);
1223 if (!conf->level_arr) {
1224 _E("Failed to allocate memory for level.");
1227 } else if (MATCH(result->name, "value")) {
1230 conf->level_arr[index] = atoi(result->value);
1236 static int haptic_load_config(struct parse_result *result, void *user_data)
1238 struct haptic_config *conf = (struct haptic_config *)user_data;
1239 char name[NAME_MAX];
1246 if (!result->section || !result->name || !result->value)
1249 // Parsing 'Haptic' section
1250 if (MATCH(result->section, "Haptic")) {
1251 ret = parse_section(result, user_data, -1);
1253 _E("Failed to parse 'Haptic' section: %d", ret);
1259 // Parsing 'level' section
1260 for (index = 0; index < conf->level; ++index) {
1261 snprintf(name, sizeof(name), "level%d", index);
1262 if (MATCH(result->section, name)) {
1263 ret = parse_section(result, user_data, index);
1265 _E("Failed to parse 'level' section: %d", ret);
1276 static const dbus_method_s hdbus_methods[] = {
1277 { "GetCount", NULL, "i", hdbus_get_count }, // device_haptic_get_count
1278 { "OpenDevice", "i", "i", hdbus_open_device }, // device_haptic_open, feedback_initialize
1279 { "CloseDevice", "u", "i", hdbus_close_device }, // device_haptic_close, feedback_deinitialize
1280 { "StopDevice", "u", "i", hdbus_stop_device }, // device_haptic_stop, feedback_stop
1281 { "VibrateMonotone", "uiii", "i", hdbus_vibrate_monotone }, // device_haptic_vibrate
1282 { "VibratePattern", "usii", "i", hdbus_vibrate_pattern }, // feedback_play*
1283 { "ShowHandleList", NULL, NULL, hdbus_show_handle_list },
1284 { "IsSupported", "s", "i", hdbus_pattern_is_supported }, // feedback_is_supported_pattern
1285 /* Add methods here */
1288 static const dbus_interface_u dbus_interface = {
1289 .name = VIBRATOR_INTERFACE_HAPTIC,
1290 .methods = hdbus_methods,
1291 .nr_methods = ARRAY_SIZE(hdbus_methods),
1294 int haptic_probe(void)
1297 * load haptic module.
1298 * if there is no haptic module,
1299 * feedbackd does not activate a haptic interface.
1301 return haptic_module_load();
1304 static guint id_sig_pwr_off_state;
1306 void haptic_init(void)
1310 /* get haptic data from configuration file */
1311 r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
1313 _E("Failed to load configuration file(%s): %d", HAPTIC_CONF_PATH, r);
1314 safe_free(haptic_conf.level_arr);
1317 /* init dbus interface */
1318 r = gdbus_register_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface);
1320 _E("Failed to init hdbus interface and method: %d", r);
1322 id_sig_pwr_off_state = gdbus_signal_subscribe(NULL,
1323 DEVICED_PATH_POWEROFF,
1324 DEVICED_INTERFACE_POWEROFF,
1325 SIGNAL_POWEROFF_STATE,
1329 if (id_sig_pwr_off_state <= 0) {
1330 _E("Failed to register signal handler: %d", r);
1334 gdbus_signal_emit(NULL,
1335 VIBRATOR_PATH_HAPTIC,
1336 VIBRATOR_INTERFACE_HAPTIC,
1337 SIGNAL_VIBRATOR_INITIATED,
1340 /* add watch for sound capturing value */
1341 if (haptic_conf.sound_capture) {
1342 r = vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL);
1344 _W("Add watch for VCONFKEY_RECORDER_STATE failed.");
1347 /* Initialize vibration_handle (Use vibration now) */
1348 cur_h_data.handle = INVALID_HANDLE;
1349 cur_h_data.priority = PRIORITY_MIN;
1352 void haptic_exit(void)
1357 if (haptic_conf.sound_capture) {
1358 r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
1360 _W("Remove watch for VCONFKEY_RECORDER_STATE failed.");
1363 /* unregister notifier for below each event */
1364 gdbus_signal_unsubscribe(NULL, id_sig_pwr_off_state);
1366 /* release haptic data memory */
1367 safe_free(haptic_conf.level_arr);
1369 /* haptic exit for feedbackd */
1370 hal_device_haptic_close_device(g_handle);
1371 hal_device_haptic_put_backend();
1374 static int haptic_start(void)
1377 haptic_disabled = false;
1381 static int haptic_stop(void)
1384 haptic_disabled = true;