dbus: Add signature checking before using g_variant_get()
[platform/core/system/feedbackd.git] / src / haptic / haptic.c
1 /*
2  * feedbackd
3  *
4  * Copyright (c) 2012 - 2017 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdio.h>
21 #include <stdbool.h>
22 #include <dlfcn.h>
23 #include <assert.h>
24 #include <vconf.h>
25 #include <time.h>
26 #include <string.h>
27 #include <libsyscommon/dbus-system.h>
28
29 #include "core/log.h"
30 #include "core/list.h"
31 #include "core/common.h"
32 #include "core/device-idler.h"
33 #include "core/config-parser.h"
34 #include "haptic.h"
35
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"
39
40 #define PATTERN_DEFAULT_MONOTONE        "FEEDBACK_PATTERN_DEFAULT"
41
42 #define HAPTIC_CONF_PATH                "/etc/feedbackd/haptic.conf"
43 #define SIGNAL_POWEROFF_STATE           "ChangeState"
44 #define SIGNAL_VIBRATOR_INITIATED       "InitiateVibrator"
45
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
54
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
59
60 #define MAX_EFFECT_BUFFER                       (64*1024)
61
62 #ifndef VCONFKEY_RECORDER_STATE
63 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
64 #define VCONFKEY_RECORDER_STATE_RECORDING       2
65 #endif
66
67 #define CHECK_VALID_OPS(ops, r)         ((ops) ? true : !(r = -ENODEV))
68 #define RETRY_CNT       3
69
70 #define INTENSITY_BASE_RATE        (10000)
71 #define VALUE_MAX_LEN              10
72 #define VIB_LOCK_TIMEOUT_MAX       (300000) /* 5minutes */
73
74 /*
75                 1,A_W or A,A_W or 250D250W250D750W
76
77                 85,10000,
78                 90,0,
79                 105,10000,
80                 0,end
81 */
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;
87         int unlimit;
88 };
89
90 struct duration_data {
91         int duration;
92         int intensity;
93         int frequency;
94         int overdrive;
95         int wait;
96 };
97
98 enum poweroff_type {
99         POWER_OFF_NONE = 0,
100         POWER_OFF_POPUP,
101         POWER_OFF_DIRECT,
102         POWER_OFF_RESTART,
103 };
104
105 struct haptic_info {
106         char *sender;
107         dd_list *handle_list;
108         guint id_watch;
109 };
110
111 struct vibrate_pattern_info {
112         unsigned int handle;
113         char *pattern;
114         int level;
115         int priority;
116 };
117
118 struct vibrate_monotone_info {
119         unsigned int handle;
120         int duration;
121         int level;
122         int intensity;
123         int priority;
124 };
125
126 /* for playing */
127 static int g_handle;
128
129 /* pattern configuration list */
130 static dd_list *vib_conf_list;
131
132 guint duration_timer;
133
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;
140
141 struct haptic_config {
142         int level;
143         int *level_arr;
144         int sound_capture;
145 };
146
147 static struct haptic_config haptic_conf;
148 static struct duration_data haptic_default_data;
149
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);
154
155 struct haptic_data cur_h_data;
156
157 void add_haptic(const struct haptic_ops *ops)
158 {
159         DD_LIST_APPEND(h_head, (void *)ops);
160 }
161
162 void remove_haptic(const struct haptic_ops *ops)
163 {
164         DD_LIST_REMOVE(h_head, (void *)ops);
165 }
166
167 static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
168 {
169         struct duration_data *data;
170
171         data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
172         if (!data) {
173                 _E("Not enough memory.");
174                 return -ENOMEM;
175         }
176         memcpy(data, update, sizeof(struct duration_data));
177         /* insert vibration pattern data */
178         // to debug :
179         // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdrive, data->wait);
180         DD_LIST_APPEND(*conf_data, data);
181         return 0;
182 }
183
184 static void get_pattern_property(char **iter, char property, int *value)
185 {
186         char *check;
187         unsigned long int val;
188
189         check = strchr(*iter, property);
190         if (!check)
191                 return;
192
193         *check = '\0';
194         val = strtoul(*iter, NULL, 10);
195         if (errno == EINVAL || errno == ERANGE) {
196                 val = 0;
197                 _E("Failed to get value of %s: %d", *iter, errno);
198         }
199         if (val > VIB_LOCK_TIMEOUT_MAX)
200                 val = VIB_LOCK_TIMEOUT_MAX;
201
202         *value = (int)val;
203
204         *iter = check + 1;
205 }
206
207 /* [A]xxxDxxxIxxxFxxxOxxxW format */
208 static int insert_raw_data_format(dd_list **conf_data, char *value)
209 {
210         struct duration_data update = {0, };
211         char *iter;
212         char *end;
213         int pattern_duration = 0;
214
215         if (!value)
216                 return insert_conf_data(conf_data, &update);
217         if (!conf_data) {
218                 _E("Invalid parameter: Configuration list is null");
219                 return -EINVAL;
220         }
221
222         iter = value;
223         end = iter + strlen(iter);
224         while (iter < end) {
225                 memset(&update, 0, sizeof(struct duration_data));
226
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);
233
234                 if (update.duration == 0 && update.wait == 0) {
235                         _D("Pattern duration is zero.");
236                         break;
237                 }
238
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;
243                 }
244
245                 if (insert_conf_data(conf_data, &update) < 0)
246                         return -EINVAL;
247         }
248
249         return pattern_duration;
250 }
251
252 static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
253 {
254         static int duration = 0;
255         static int intensity = 0;
256         int value;
257         int ret;
258
259         if (count > 4 || count <= 0) {
260                 _E("Invalid parameter: count is invalid");
261                 return -EINVAL;
262         }
263
264         if (!packed || !val || !pattern_duration || !update) {
265                 _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
266                 return -EINVAL;
267         }
268
269         get_pattern_property(&val, 'C', &value);
270
271         ret = count;
272         switch (count) {
273         case 1: /* D */
274                 duration = 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;
279                 }
280                 break;
281         case 2: /* I or W */
282                 if (value > INTENSITY_BASE_RATE)
283                         value = INTENSITY_BASE_RATE;
284                 intensity = value;
285                 if (*packed == false) {
286                         update->duration = duration;
287                         update->intensity = intensity;
288                         break;
289                 }
290                  /* if intensity is 0, duration use for wait(off) time */
291                 if (intensity == 0)
292                         update->wait = duration;
293                 else
294                         update->wait = 0;
295                 *packed = false;
296                 duration = 0;
297                 intensity = 0;
298                 ret = -1;
299                 break;
300         case 3: /* F */
301                 if (intensity != 0)
302                         update->frequency = value;
303                 break;
304         case 4:  /* O */
305                 if (intensity != 0) {
306                         update->overdrive = value;
307                         *packed = true;
308                 }
309                 ret = 0;
310                 break;
311         default:
312                 break;
313         }
314         return ret;
315 }
316
317 /*
318         duration, intensity, frequency, overdrive
319         waiting duration, intensity=0, frequency, overdrive
320         85,10000,
321         90,0,
322         105,10000,
323         0,end
324 */
325 static int load_standard_format(const char *pattern)
326 {
327         struct duration_data update = {0, };
328         bool packed = false;
329         struct vibration_config *conf;
330         int ret = 0, count = 0, end = 2;
331         int index = 0;
332         int fd;
333         char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
334
335         snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
336         fd = open(path, O_RDONLY);
337         if (fd < 0)
338                 return -ENOENT;
339
340         conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
341         if (!conf) {
342                 _E("Failed to alloc.");
343                 ret = -errno;
344                 goto error_out;
345         }
346
347         conf->pattern = strdup(pattern);
348         if (!conf->pattern) {
349                 _E("Failed to copy pattern data(%s).", pattern);
350                 ret = -errno;
351                 goto error_out;
352         }
353
354         /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
355         while (read(fd, &elem, 1) != 0) {
356                 if (end == 0) {
357                         if (insert_conf_data(&conf->data, &update) < 0)
358                                 goto error_out;
359                         break;
360                 }
361                 if (elem == 'e' || elem == 'n' || elem == 'd') {
362                         end--;
363                         continue;
364                 }
365                 if (elem == '\n') {
366                         count = 0;
367                         continue;
368                 }
369                 if (elem == ',') {
370                         count++;
371                         val[index] = 'C';
372                         index = 0;
373
374                         ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
375                         if (ret < 0) {
376                                 if (ret == -EINVAL)
377                                         break;
378                                 if (insert_conf_data(&conf->data, &update) < 0)
379                                         goto error_out;
380                                 memset(&update, 0, sizeof(struct duration_data));
381                         } else
382                                 count = ret;
383                 } else {
384                         if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
385                                 val[index++] = elem;
386                         else
387                                 _E("Pattern(%s) is out of bound: %s", pattern, val);
388                 }
389         }
390         close(fd);
391         DD_LIST_APPEND(vib_conf_list, conf);
392         return ret;
393
394 error_out:
395         if (fd >= 0)
396                 close(fd);
397         if (conf) {
398                 if (conf->pattern)
399                         free(conf->pattern);
400                 free(conf);
401         }
402         return -ENOENT;
403 }
404
405 static int vibration_load_config(struct parse_result *result, void *user_data)
406 {
407         struct vibration_config *conf;
408         char *value;
409         char *check;
410         int len;
411         int duration;
412
413         if (!result)
414                 return 0;
415
416         if (!MATCH(result->section, "Vibration"))
417                 return 0;
418
419
420         if (!result->name || !result->value)
421                 return 0;
422
423         conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
424         if (!conf) {
425                 _E("Failed to alloc.");
426                 return -ENOMEM;
427         }
428
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);
433                 goto error_out;
434         }
435
436         value = result->value;
437         len = strlen(value);
438
439         if (len == 0) {
440                 if (insert_raw_data_format(&conf->data, NULL) < 0)
441                         goto error_out;
442                 DD_LIST_APPEND(vib_conf_list, conf);
443                 return 0;
444         }
445
446         /* Load Standard Pattern Name */
447         /* value: 1,A_W or A,A_W */
448         if ((check = strchr(value, ','))) {
449                 *check = '\0';
450                 if (strncmp(value, "A", 1) == 0)
451                         conf->unlimit = 1;
452                 value = check + 1;
453                 conf->standard = strdup(value);
454                 if (!conf->standard) {
455                         _E("Failed to copy standard name.");
456                         goto error_out;
457                 }
458                 DD_LIST_APPEND(vib_conf_list, conf);
459                 return 0;
460         }
461
462         /* value : A100D or 100D0W or 250D250W250D750W */
463         /* Load Vibration Pattern Data */
464         check = strchr(value, 'A');
465         if (check) {
466                 *check = '\0';
467                 conf->unlimit = 1;
468                 if (!value)
469                         len = len - 1;
470                 else
471                         len = len - strlen(value) - 1;
472                 value = check + 1;
473         }
474         duration = insert_raw_data_format(&conf->data, value);
475         if (duration < 0) {
476                 conf->pattern_duration = 0;
477                 goto error_out;
478         } else
479                 conf->pattern_duration = duration;
480         DD_LIST_APPEND(vib_conf_list, conf);
481
482         return 0;
483
484 error_out:
485         if (conf) {
486                 if (conf->pattern)
487                         free(conf->pattern);
488                 if (conf->standard)
489                         free(conf->standard);
490         }
491         return -ENOMEM;
492 }
493
494 static void load_standard_vibration_patterns(void)
495 {
496         DIR *dir;
497         struct dirent *dent;
498         int ret;
499
500         dir = opendir(STANDARD_FILE_PATH);
501         if (!dir) {
502                 _E("Failed to load '%s' Use default value.", STANDARD_FILE_PATH);
503                 return;
504         }
505         while ((dent = readdir(dir))) {
506                 if (dent->d_type == DT_DIR)
507                         continue;
508                 ret = load_standard_format(dent->d_name);
509                 if (ret < 0)
510                         _E("Failed to parse %s: %d", dent->d_name, ret);
511         }
512         closedir(dir);
513         _D("Success to load '%s'", STANDARD_FILE_PATH);
514 }
515
516 void pattern_config_parse(void)
517 {
518         int ret;
519
520         ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
521         if (ret < 0)
522                 _E("Failed to load '%s'. Use default value: %d", VIBRATION_CONF_PATH, ret);
523
524         load_standard_vibration_patterns();
525 }
526
527 static void get_default_haptic_data()
528 {
529         dd_list *elem;
530         struct vibration_config *conf;
531         char pattern[PATH_MAX] = {0,};
532
533         memset(&haptic_default_data, 0, sizeof(struct duration_data));
534
535         snprintf(pattern, sizeof(pattern), "%s", PATTERN_DEFAULT_MONOTONE);
536         DD_LIST_FOREACH(vib_conf_list, elem, conf) {
537                 if (!conf->pattern)
538                         continue;
539                 if (strcmp(conf->pattern, pattern))
540                         continue;
541
542                 if (conf->standard) {
543                         snprintf(pattern, sizeof(pattern), "%s", conf->standard);
544                         continue;
545                 }
546
547                 if (conf->data)
548                         memcpy(&haptic_default_data, conf->data->data, sizeof(struct duration_data));
549
550                 break;
551         }
552         _D("Default haptic data: intensity=%d, frequency=%d", haptic_default_data.intensity, haptic_default_data.frequency);
553 }
554
555 static int haptic_module_load(void)
556 {
557         struct haptic_ops *ops;
558         dd_list *elem;
559         int r;
560
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()) {
566                         if (ops->load)
567                                 h_ops = ops->load();
568                         h_type = ops->type;
569                         break;
570                 }
571         }
572
573         if (!CHECK_VALID_OPS(h_ops, r)) {
574                 _E("Can't find the valid haptic device.");
575                 return r;
576         }
577
578         /* solution bug
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();
584
585         return 0;
586 }
587
588 /*
589 static int convert_magnitude_by_conf(int level)
590 {
591         int i, step;
592
593         if (level < LOW_FEEDBACK_LEVEL)
594                 level = LOW_FEEDBACK_LEVEL;
595         else if (level > HIGH_FEEDBACK_LEVEL)
596                 level = HIGH_FEEDBACK_LEVEL;
597
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];
603                 }
604         }
605
606         _D("Play default level.");
607         return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP;
608 }
609 */
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)
613 {
614         int ret, val;
615
616         if (!CHECK_VALID_OPS(h_ops, ret))
617                 goto exit;
618
619         ret = h_ops->get_device_count(&val);
620         if (ret >= 0)
621                 ret = val;
622
623 exit:
624         return g_variant_new("(i)", ret);
625 }
626
627 void haptic_name_owner_changed(GDBusConnection *connection,
628         const gchar     *name,
629         gpointer         user_data)
630 {
631         dd_list *n;
632         struct haptic_info *info = user_data;
633         int handle;
634
635         _I("%s (sender=%s)", __func__, name);
636
637         if (!info)
638                 return;
639
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);
644         }
645
646         remove_haptic_info(info);
647 }
648
649 static struct haptic_info *add_haptic_info(const char *sender)
650 {
651         struct haptic_info *info;
652
653         assert(sender);
654
655         info = calloc(1, sizeof(struct haptic_info));
656         if (!info)
657                 return NULL;
658
659         info->sender = strdup(sender);
660         if (!info->sender) {
661                 free(info);
662                 return NULL;
663         }
664
665         DD_LIST_APPEND(haptic_handle_list, info);
666
667         info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL);
668
669         return info;
670 }
671
672 static int remove_haptic_info(struct haptic_info *info)
673 {
674         assert(info);
675
676         dbus_handle_unwatch_name(info->id_watch);
677
678         DD_LIST_REMOVE(haptic_handle_list, info);
679         DD_LIST_FREE_LIST(info->handle_list);
680         if (info->sender) {
681                 free(info->sender);
682         }
683         free(info);
684
685         return 0;
686 }
687
688 static struct haptic_info *get_matched_haptic_info(const char *sender)
689 {
690         dd_list *n;
691         struct haptic_info *info;
692         int len;
693
694         assert(sender);
695
696         len = strlen(sender) + 1;
697         DD_LIST_FOREACH(haptic_handle_list, n, info) {
698                 if (!strncmp(info->sender, sender, len))
699                         return info;
700         }
701
702         return NULL;
703 }
704
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)
708
709 {
710         int index, handle, ret;
711         struct haptic_info *info;
712
713         /* Load haptic module before booting done */
714         if (!CHECK_VALID_OPS(h_ops, ret)) {
715                 ret = haptic_module_load();
716                 if (ret < 0)
717                         goto exit;
718         }
719
720         g_variant_get(param, "(i)", &index);
721
722         ret = h_ops->open_device(index, &handle);
723         if (ret < 0)
724                 goto exit;
725
726         if (!sender) {
727                 ret = -EPERM;
728                 h_ops->close_device(handle);
729                 goto exit;
730         }
731
732         info = get_matched_haptic_info(sender);
733         if (!info) {
734                 info = add_haptic_info(sender);
735                 if (!info) {
736                         _E("Failed to create haptic information.");
737                         ret = -EPERM;
738                         h_ops->close_device(handle);
739                         goto exit;
740                 }
741         }
742
743         DD_LIST_APPEND(info->handle_list, (gpointer)(long)handle);
744
745         ret = handle;
746
747 exit:
748         return g_variant_new("(i)", ret);
749 }
750
751 int clear_current_data(void)
752 {
753         cur_h_data.handle = INVALID_HANDLE;
754         cur_h_data.priority = PRIORITY_MIN;
755
756         if (duration_timer) {
757                 _I("Remove duration_timer.");
758                 g_source_remove(duration_timer);
759                 duration_timer = 0;
760         }
761
762         return 0;
763 }
764
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)
768 {
769         unsigned int handle;
770         int ret;
771         struct haptic_info *info;
772         int cnt;
773
774         if (!CHECK_VALID_OPS(h_ops, ret))
775                 goto exit;
776
777         g_variant_get(param, "(u)", &handle);
778
779         if (!sender) {
780                 _E("Failed to get sender from dbus message.");
781                 ret = -EPERM;
782                 goto exit;
783         }
784
785         ret = h_ops->close_device(handle);
786         if (ret < 0)
787                 goto exit;
788
789         if (cur_h_data.handle == handle) {
790                 /* Remove duration_timer for vibrate_effect */
791                 clear_current_data();
792         }
793
794         info = get_matched_haptic_info(sender);
795         if (!info) {
796                 _E("Failed to find the matched haptic info.");
797                 goto exit;
798         }
799
800         DD_LIST_REMOVE(info->handle_list, (gpointer)(long)handle);
801         cnt = DD_LIST_LENGTH(info->handle_list);
802         if (cnt == 0)
803                 remove_haptic_info(info);
804
805 exit:
806         return g_variant_new("(i)", ret);
807 }
808
809 static gboolean _cb(void *data)
810 {
811         if (duration_timer) {
812                 g_source_remove(duration_timer);
813                 duration_timer = 0;
814         }
815
816         cur_h_data.handle = INVALID_HANDLE;
817         cur_h_data.priority = PRIORITY_MIN;
818
819         return G_SOURCE_REMOVE;
820 }
821
822 static void vibrate_monotone_idler_cb(void *data)
823 {
824         struct vibrate_monotone_info *vibrate_info;
825         int ret;
826
827         if (!data)
828                 return;
829
830         vibrate_info = (struct vibrate_monotone_info *)data;
831
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);
834                 free(vibrate_info);
835                 return;
836         }
837
838         if (duration_timer) {
839                 g_source_remove(duration_timer);
840                 duration_timer = 0;
841         }
842
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;
849
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.");
853
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);
857
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);
860
861         free(vibrate_info);
862 }
863
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)
867 {
868         struct vibrate_monotone_info *vibrate_info;
869         unsigned int handle;
870         int duration, level, intensity, priority, ret = 0;
871
872         if (!CHECK_VALID_OPS(h_ops, ret))
873                 goto exit;
874
875         if (haptic_disabled)
876                 goto exit;
877
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);
880
881         if (intensity < 0) {
882                 ret = -EINVAL;
883                 goto exit;
884         }
885
886         if (priority < PRIORITY_MIN)
887                 priority = PRIORITY_MIN;
888         else if (priority > PRIORITY_TOP)
889                 priority = PRIORITY_TOP;
890
891         if (duration <= 0) {
892                 _E("Skip vibrate handle(%d) requested less than 0.", handle);
893                 ret = -EINVAL;
894                 goto exit;
895         }
896
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.");
899                 ret = -EINVAL;
900                 goto exit;
901         }
902
903         vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
904         if (!vibrate_info) {
905                 _E("Failed to allocate memory for vibrate_info.");
906                 ret = -errno;
907                 goto exit;
908         }
909
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;
915
916         ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
917 exit:
918         return g_variant_new("(i)", ret);
919 }
920
921 static gboolean haptic_duration_play(void *data)
922 {
923         dd_list *head, *n, *next;
924         struct duration_data *node;
925         int ret = 0;
926
927         if (duration_timer) {
928                 g_source_remove(duration_timer);
929                 duration_timer = 0;
930         }
931
932         if (!data) {
933                 if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
934                         head = cur_h_data.vibration_data;
935                 else {
936                         cur_h_data.handle = INVALID_HANDLE;
937                         cur_h_data.priority = PRIORITY_MIN;
938                         goto out;
939                 }
940         } else
941                 head = (dd_list *)data;
942
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;
948                 goto out;
949         }
950
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;
959                                 break;
960                         } else {
961                                 next = cur_h_data.vibration_data;
962                                 continue;
963                         }
964                 }
965
966                 duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
967
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);
969
970                 break;
971         }
972         if (ret != 0) {
973                 _D("Auto stop vibration.");
974                 cur_h_data.stop = true;
975         }
976 out:
977         return G_SOURCE_REMOVE;
978 }
979
980 static void vibrate_pattern_idler_cb(void *data)
981 {
982         struct vibrate_pattern_info *vibrate_info;
983         dd_list *elem;
984         struct vibration_config *conf;
985         char pattern[PATH_MAX];
986         int ret;
987         int unlimit = 0;
988
989         if (!data)
990                 return;
991
992         vibrate_info = (struct vibrate_pattern_info *)data;
993
994         if (!(vibrate_info->pattern)) {
995                 free(vibrate_info);
996                 return;
997         }
998
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);
1002                 goto out;
1003         }
1004
1005         snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
1006         DD_LIST_FOREACH(vib_conf_list, elem, conf) {
1007                 if (!conf->pattern)
1008                         continue;
1009                 if (strcmp(conf->pattern, pattern))
1010                         continue;
1011                 if (conf->standard) {
1012                         unlimit = conf->unlimit;
1013                         snprintf(pattern, sizeof(pattern), "%s", conf->standard);
1014                         continue;
1015                 }
1016
1017                 if (unlimit)
1018                         cur_h_data.unlimit = unlimit;
1019                 else
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");
1028
1029                 if (conf->pattern_duration <= 0)
1030                         break;
1031
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.");
1036                 }
1037                 haptic_duration_play((void *)cur_h_data.vibration_data);
1038                 goto out;
1039         }
1040         _E("Handle(%d) %s is not supported.", vibrate_info->handle, pattern);
1041
1042 out:
1043         free(vibrate_info->pattern);
1044         free(vibrate_info);
1045 }
1046
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)
1050 {
1051         struct vibrate_pattern_info *vibrate_info;
1052         unsigned int handle;
1053         char *pattern = NULL;
1054         int level, priority, ret = 0;
1055
1056         if (!CHECK_VALID_OPS(h_ops, ret))
1057                 goto exit;
1058
1059         if (haptic_disabled)
1060                 goto exit;
1061
1062         g_variant_get(param, "(usii)",  &handle, &pattern, &level, &priority);
1063
1064         if (level < 0) {
1065                 ret = -EINVAL;
1066                 goto exit;
1067         }
1068
1069         if (priority < PRIORITY_MIN)
1070                 priority = PRIORITY_MIN;
1071         else if (priority > PRIORITY_TOP)
1072                 priority = PRIORITY_TOP;
1073
1074         vibrate_info = calloc(1, sizeof(struct vibrate_pattern_info));
1075         if (!vibrate_info) {
1076                 _E("Failed to allocate memory for vibrate_info.");
1077                 ret = -errno;
1078                 goto exit;
1079         }
1080         vibrate_info->handle = handle;
1081         vibrate_info->pattern = pattern;
1082         pattern = NULL;
1083         if (!vibrate_info->pattern) {
1084                 _E("Failed to allocate memory for pattern.");
1085                 ret = -errno;
1086                 free(vibrate_info);
1087                 goto exit;
1088         }
1089         vibrate_info->level = level;
1090         vibrate_info->priority = priority;
1091
1092         ret = add_idle_request(vibrate_pattern_idler_cb, (void *)vibrate_info);
1093
1094 exit:
1095         g_free(pattern);
1096         return g_variant_new("(i)", ret);
1097 }
1098
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)
1102 {
1103         unsigned int handle;
1104         int ret = 0;
1105
1106         if (!CHECK_VALID_OPS(h_ops, ret))
1107                 goto exit;
1108
1109         if (haptic_disabled) {
1110                 _I("Haptic disabled.");
1111                 goto exit;
1112         }
1113
1114         g_variant_get(param, "(u)", &handle);
1115
1116         if (cur_h_data.handle != handle) {
1117                 _D("Not the request from current vibration handle(%d). Skip.", handle);
1118                 goto exit;
1119         }
1120
1121         ret = h_ops->stop_device(handle);
1122         _I("Stop the device(handle=%u) :%d", handle, ret);
1123
1124         /* Remove duration_timer for vibrate_effect */
1125         clear_current_data();
1126
1127 exit:
1128         return g_variant_new("(i)", ret);
1129 }
1130
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)
1134 {
1135         dd_list *n;
1136         dd_list *elem;
1137         struct haptic_info *info;
1138
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);
1143         }
1144
1145         return g_variant_new_tuple(NULL, 0);
1146 }
1147
1148 int pattern_is_supported(const char *pattern)
1149 {
1150         dd_list *elem;
1151         struct vibration_config *conf;
1152         int ret;
1153
1154         if (!pattern)
1155                 return -EINVAL;
1156
1157         ret = 0;
1158         DD_LIST_FOREACH(vib_conf_list, elem, conf) {
1159                 if (!conf->pattern)
1160                         continue;
1161                 if (!strcmp(conf->pattern, pattern)) {
1162                         ret = true;
1163                         break;
1164                 }
1165         }
1166
1167         return ret;
1168 }
1169
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)
1173
1174 {
1175         char *data = NULL;
1176         int ret = 0;
1177
1178         if (!CHECK_VALID_OPS(h_ops, ret))
1179                 goto exit;
1180
1181         if (haptic_disabled)
1182                 goto exit;
1183
1184         g_variant_get(param, "(s)", &data);
1185
1186         ret = pattern_is_supported(data);
1187
1188         _I("%s is supported: %d", data, ret);
1189
1190 exit:
1191         g_free(data);
1192         return g_variant_new("(i)", ret);
1193 }
1194
1195 static int haptic_internal_init(void)
1196 {
1197         int r;
1198         if (!CHECK_VALID_OPS(h_ops, r))
1199                 return r;
1200         return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle);
1201 }
1202
1203 static int haptic_internal_exit(void)
1204 {
1205         int r;
1206         if (!CHECK_VALID_OPS(h_ops, r))
1207                 return r;
1208         return h_ops->close_device(g_handle);
1209 }
1210
1211 static void haptic_poweroff_cb(GDBusConnection  *conn,
1212         const gchar      *sender,
1213         const gchar      *path,
1214         const gchar      *iface,
1215         const gchar      *name,
1216         GVariant         *param,
1217         gpointer          data)
1218 {
1219         int type = POWER_OFF_NONE;
1220         int ret, level;
1221         struct timespec time = {0,};
1222
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));
1225                 return;
1226         }
1227
1228         if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART)
1229                 return;
1230
1231         _D("Poweroff: %d", type);
1232
1233         if (!CHECK_VALID_OPS(h_ops, ret)) {
1234                 ret = haptic_module_load();
1235                 if (ret < 0)
1236                         return;
1237         }
1238
1239         if (!g_handle)
1240                 haptic_internal_init();
1241
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.");
1244                 return;
1245         }
1246         level = (level/2) + 1;
1247
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);
1254         if (ret < 0) {
1255                 _E("Failed to vibrate_monotone: %d", ret);
1256                 return;
1257         }
1258
1259         /* sleep for vibration */
1260         time.tv_nsec = POWER_OFF_VIB_DURATION * NANO_SECOND_MULTIPLIER;
1261         nanosleep(&time, NULL);
1262         return;
1263 }
1264
1265 static void sound_capturing_cb(keynode_t *key, void *data)
1266 {
1267         int status;
1268
1269         status = vconf_keynode_get_int(key);
1270
1271         /* if sound capture is in use, this value is 1(true). */
1272         if (status == VCONFKEY_RECORDER_STATE_RECORDING)
1273                 haptic_stop();
1274         else
1275                 haptic_start();
1276 }
1277
1278 static int parse_section(struct parse_result *result, void *user_data, int index)
1279 {
1280         struct haptic_config *conf = (struct haptic_config *)user_data;
1281
1282         if (!result)
1283                 return 0;
1284
1285         if (!result->section || !result->name || !result->value)
1286                 return 0;
1287
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.");
1294                         return -EINVAL;
1295                 }
1296                 conf->level_arr = calloc(sizeof(int), conf->level);
1297                 if (!conf->level_arr) {
1298                         _E("Failed to allocate memory for level.");
1299                         return -errno;
1300                 }
1301         } else if (MATCH(result->name, "value")) {
1302                 if (index < 0)
1303                         return -EINVAL;
1304                 conf->level_arr[index] = atoi(result->value);
1305         }
1306
1307         return 0;
1308 }
1309
1310 static int haptic_load_config(struct parse_result *result, void *user_data)
1311 {
1312         struct haptic_config *conf = (struct haptic_config *)user_data;
1313         char name[NAME_MAX];
1314         int ret;
1315         static int index;
1316
1317         if (!result)
1318                 return 0;
1319
1320         if (!result->section || !result->name || !result->value)
1321                 return 0;
1322
1323         // Parsing 'Haptic' section
1324         if (MATCH(result->section, "Haptic")) {
1325                 ret = parse_section(result, user_data, -1);
1326                 if (ret < 0) {
1327                         _E("Failed to parse 'Haptic' section: %d", ret);
1328                         return ret;
1329                 }
1330                 goto out;
1331         }
1332
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);
1338                         if (ret < 0) {
1339                                 _E("Failed to parse 'level' section: %d", ret);
1340                                 return ret;
1341                         }
1342                         goto out;
1343                 }
1344         }
1345
1346 out:
1347         return 0;
1348 }
1349
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 */
1360 };
1361
1362 static const dbus_interface_u dbus_interface = {
1363         .name = VIBRATOR_INTERFACE_HAPTIC,
1364         .methods = hdbus_methods,
1365         .nr_methods = ARRAY_SIZE(hdbus_methods),
1366 };
1367
1368 int haptic_probe(void)
1369 {
1370         /**
1371          * load haptic module.
1372          * if there is no haptic module,
1373          * feedbackd does not activate a haptic interface.
1374          */
1375         return haptic_module_load();
1376 }
1377
1378 guint id_sig_pwr_off_state;
1379
1380 void haptic_init(void)
1381 {
1382         int r;
1383
1384         /* get haptic data from configuration file */
1385         r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
1386         if (r < 0) {
1387                 _E("Failed to load configuration file(%s): %d", HAPTIC_CONF_PATH, r);
1388                 safe_free(haptic_conf.level_arr);
1389         }
1390
1391         /* init dbus interface */
1392         r = dbus_handle_register_dbus_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface);
1393         if (r < 0)
1394                 _E("Failed to init hdbus interface and method: %d", r);
1395
1396         id_sig_pwr_off_state = subscribe_dbus_signal(NULL,
1397                         DEVICED_PATH_POWEROFF,
1398                         DEVICED_INTERFACE_POWEROFF,
1399                         SIGNAL_POWEROFF_STATE,
1400                         haptic_poweroff_cb,
1401                         NULL,
1402                         NULL);
1403         if (id_sig_pwr_off_state <= 0) {
1404                 _E("Failed to register signal handler: %d", r);
1405                 return;
1406         }
1407
1408         dbus_handle_emit_dbus_signal(NULL,
1409                         VIBRATOR_PATH_HAPTIC,
1410                         VIBRATOR_INTERFACE_HAPTIC,
1411                         SIGNAL_VIBRATOR_INITIATED,
1412                         NULL);
1413
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);
1417                 if (r != 0)
1418                         _W("Add watch for VCONFKEY_RECORDER_STATE failed.");
1419         }
1420
1421         /* Initialize vibration_handle (Use vibration now) */
1422         cur_h_data.handle = INVALID_HANDLE;
1423         cur_h_data.priority = PRIORITY_MIN;
1424 }
1425
1426 void haptic_exit(void)
1427 {
1428         struct haptic_ops *ops;
1429         dd_list *elem;
1430         int r;
1431
1432         /* remove watch */
1433         if (haptic_conf.sound_capture) {
1434                 r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
1435                 if (r != 0)
1436                         _W("Remove watch for VCONFKEY_RECORDER_STATE failed.");
1437         }
1438
1439         /* unregister notifier for below each event */
1440         unsubscribe_dbus_signal(NULL, id_sig_pwr_off_state);
1441
1442         /* release haptic data memory */
1443         safe_free(haptic_conf.level_arr);
1444
1445         if (!CHECK_VALID_OPS(h_ops, r))
1446                 return;
1447
1448         /* haptic exit for feedbackd */
1449         haptic_internal_exit();
1450
1451         /* release plugin */
1452         DD_LIST_FOREACH(h_head, elem, ops) {
1453                 if (ops->is_valid && ops->is_valid()) {
1454                         if (ops->release)
1455                                 ops->release();
1456                         h_ops = NULL;
1457                         break;
1458                 }
1459         }
1460 }
1461
1462 static int haptic_start(void)
1463 {
1464         _I("Start");
1465         haptic_disabled = false;
1466         return 0;
1467 }
1468
1469 static int haptic_stop(void)
1470 {
1471         _I("Stop");
1472         haptic_disabled = true;
1473         return 0;
1474 }