Change dbus function name
[platform/core/system/feedbackd.git] / src / core / 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/libgdbus.h>
28 #include <libsyscommon/list.h>
29 #include <libsyscommon/ini-parser.h>
30 #include <hal/device/hal-haptic.h>
31
32 #include "shared/log.h"
33 #include "shared/common.h"
34 #include "shared/device-idler.h"
35 #include "haptic.h"
36
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"
40
41 #define HAPTIC_CONF_PATH                "/etc/feedbackd/haptic.conf"
42 #define SIGNAL_POWEROFF_STATE           "ChangeState"
43 #define SIGNAL_VIBRATOR_INITIATED       "InitiateVibrator"
44
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
53
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
58
59 #define MAX_EFFECT_BUFFER                       (64*1024)
60
61 #ifndef VCONFKEY_RECORDER_STATE
62 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
63 #define VCONFKEY_RECORDER_STATE_RECORDING       2
64 #endif
65
66 #define RETRY_CNT       3
67
68 #define INTENSITY_BASE_RATE        (10000)
69 #define VALUE_MAX_LEN              10
70 #define VIB_LOCK_TIMEOUT_MAX       (300000) /* 5minutes */
71
72 /*
73                 1,A_W or A,A_W or 250D250W250D750W
74
75                 85,10000,
76                 90,0,
77                 105,10000,
78                 0,end
79 */
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;
85         int unlimit;
86 };
87
88 struct duration_data {
89         int duration;
90         int intensity;
91         int frequency;
92         int overdrive;
93         int wait;
94 };
95
96 enum poweroff_type {
97         POWER_OFF_NONE = 0,
98         POWER_OFF_POPUP,
99         POWER_OFF_DIRECT,
100         POWER_OFF_RESTART,
101 };
102
103 struct haptic_info {
104         char *sender;
105         GList *handle_list;
106         guint id_watch;
107 };
108
109 struct vibrate_pattern_info {
110         unsigned int handle;
111         char *pattern;
112         int level;
113         int priority;
114 };
115
116 struct vibrate_monotone_info {
117         unsigned int handle;
118         int duration;
119         int level;
120         int intensity;
121         int priority;
122 };
123
124 /* for playing */
125 static int g_handle;
126
127 /* pattern configuration list */
128 static GList *vib_conf_list;
129
130 static guint duration_timer;
131
132 /* haptic operation variable */
133 static GList *haptic_handle_list;
134
135 static bool haptic_disabled;
136
137 struct haptic_config {
138         int level;
139         int *level_arr;
140         int sound_capture;
141 };
142
143 static struct haptic_config haptic_conf;
144
145 static int haptic_start(void);
146 static int haptic_stop(void);
147 static int remove_haptic_info(struct haptic_info *info);
148
149 struct haptic_data cur_h_data;
150
151 static int insert_conf_data(GList **conf_data, struct duration_data *update)
152 {
153         struct duration_data *data;
154
155         data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
156         if (!data) {
157                 _E("Not enough memory.");
158                 return -ENOMEM;
159         }
160         memcpy(data, update, sizeof(struct duration_data));
161         /* insert vibration pattern data */
162         // to debug :
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);
165         return 0;
166 }
167
168 static void get_pattern_property(char **iter, char property, int *value)
169 {
170         char *check;
171         unsigned long int val;
172
173         check = strchr(*iter, property);
174         if (!check)
175                 return;
176
177         *check = '\0';
178         val = strtoul(*iter, NULL, 10);
179         if (errno == EINVAL || errno == ERANGE) {
180                 val = 0;
181                 _E("Failed to get value of %s: %d", *iter, errno);
182         }
183         if (val > VIB_LOCK_TIMEOUT_MAX)
184                 val = VIB_LOCK_TIMEOUT_MAX;
185
186         *value = (int)val;
187
188         *iter = check + 1;
189 }
190
191 /* [A]xxxDxxxIxxxFxxxOxxxW format */
192 static int insert_raw_data_format(GList **conf_data, char *value)
193 {
194         struct duration_data update = {0, };
195         char *iter;
196         char *end;
197         int pattern_duration = 0;
198
199         if (!value)
200                 return insert_conf_data(conf_data, &update);
201         if (!conf_data) {
202                 _E("Invalid parameter: Configuration list is null");
203                 return -EINVAL;
204         }
205
206         iter = value;
207         end = iter + strlen(iter);
208         while (iter < end) {
209                 memset(&update, 0, sizeof(struct duration_data));
210
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);
217
218                 if (update.duration == 0 && update.wait == 0) {
219                         _D("Pattern duration is zero.");
220                         break;
221                 }
222
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;
227                 }
228
229                 if (insert_conf_data(conf_data, &update) < 0)
230                         return -EINVAL;
231         }
232
233         return pattern_duration;
234 }
235
236 static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
237 {
238         static int duration = 0;
239         static int intensity = 0;
240         int value;
241         int ret;
242
243         if (count > 4 || count <= 0) {
244                 _E("Invalid parameter: count is invalid");
245                 return -EINVAL;
246         }
247
248         if (!packed || !val || !pattern_duration || !update) {
249                 _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
250                 return -EINVAL;
251         }
252
253         get_pattern_property(&val, 'C', &value);
254
255         ret = count;
256         switch (count) {
257         case 1: /* D */
258                 duration = 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;
263                 }
264                 break;
265         case 2: /* I or W */
266                 if (value > INTENSITY_BASE_RATE)
267                         value = INTENSITY_BASE_RATE;
268                 intensity = value;
269                 if (*packed == false) {
270                         update->duration = duration;
271                         update->intensity = intensity;
272                         break;
273                 }
274                  /* if intensity is 0, duration use for wait(off) time */
275                 if (intensity == 0)
276                         update->wait = duration;
277                 else
278                         update->wait = 0;
279                 *packed = false;
280                 duration = 0;
281                 intensity = 0;
282                 ret = -1;
283                 break;
284         case 3: /* F */
285                 if (intensity != 0)
286                         update->frequency = value;
287                 break;
288         case 4:  /* O */
289                 if (intensity != 0) {
290                         update->overdrive = value;
291                         *packed = true;
292                 }
293                 ret = 0;
294                 break;
295         default:
296                 break;
297         }
298         return ret;
299 }
300
301 /*
302         duration, intensity, frequency, overdrive
303         waiting duration, intensity=0, frequency, overdrive
304         85,10000,
305         90,0,
306         105,10000,
307         0,end
308 */
309 static int load_standard_format(const char *pattern)
310 {
311         struct duration_data update = {0, };
312         bool packed = false;
313         struct vibration_config *conf;
314         int ret = 0, count = 0, end = 2;
315         int index = 0;
316         int fd;
317         char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
318
319         snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
320         fd = open(path, O_RDONLY);
321         if (fd < 0)
322                 return -ENOENT;
323
324         conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
325         if (!conf) {
326                 _E("Failed to alloc.");
327                 ret = -errno;
328                 goto error_out;
329         }
330
331         conf->pattern = strdup(pattern);
332         if (!conf->pattern) {
333                 _E("Failed to copy pattern data(%s).", pattern);
334                 ret = -errno;
335                 goto error_out;
336         }
337
338         /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
339         while (read(fd, &elem, 1) != 0) {
340                 if (end == 0) {
341                         if (insert_conf_data(&conf->data, &update) < 0)
342                                 goto error_out;
343                         break;
344                 }
345                 if (elem == 'e' || elem == 'n' || elem == 'd') {
346                         end--;
347                         continue;
348                 }
349                 if (elem == '\n') {
350                         count = 0;
351                         continue;
352                 }
353                 if (elem == ',') {
354                         count++;
355                         val[index] = 'C';
356                         index = 0;
357
358                         ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
359                         if (ret < 0) {
360                                 if (ret == -EINVAL)
361                                         break;
362                                 if (insert_conf_data(&conf->data, &update) < 0)
363                                         goto error_out;
364                                 memset(&update, 0, sizeof(struct duration_data));
365                         } else
366                                 count = ret;
367                 } else {
368                         if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
369                                 val[index++] = elem;
370                         else
371                                 _E("Pattern(%s) is out of bound: %s", pattern, val);
372                 }
373         }
374         close(fd);
375         SYS_G_LIST_APPEND(vib_conf_list, conf);
376         return ret;
377
378 error_out:
379         if (fd >= 0)
380                 close(fd);
381         if (conf) {
382                 if (conf->pattern)
383                         free(conf->pattern);
384                 free(conf);
385         }
386         return -ENOENT;
387 }
388
389 static int vibration_load_config(struct parse_result *result, void *user_data)
390 {
391         struct vibration_config *conf;
392         char *value;
393         char *check;
394         int len;
395         int duration;
396
397         if (!result)
398                 return 0;
399
400         if (!MATCH(result->section, "Vibration"))
401                 return 0;
402
403
404         if (!result->name || !result->value)
405                 return 0;
406
407         conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
408         if (!conf) {
409                 _E("Failed to alloc.");
410                 return -ENOMEM;
411         }
412
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);
417                 goto error_out;
418         }
419
420         value = result->value;
421         len = strlen(value);
422
423         if (len == 0) {
424                 if (insert_raw_data_format(&conf->data, NULL) < 0)
425                         goto error_out;
426                 SYS_G_LIST_APPEND(vib_conf_list, conf);
427                 return 0;
428         }
429
430         /* Load Standard Pattern Name */
431         /* value: 1,A_W or A,A_W */
432         if ((check = strchr(value, ','))) {
433                 *check = '\0';
434                 if (strncmp(value, "A", 1) == 0)
435                         conf->unlimit = 1;
436                 value = check + 1;
437                 conf->standard = strdup(value);
438                 if (!conf->standard) {
439                         _E("Failed to copy standard name.");
440                         goto error_out;
441                 }
442                 SYS_G_LIST_APPEND(vib_conf_list, conf);
443                 return 0;
444         }
445
446         /* value : A100D or 100D0W or 250D250W250D750W */
447         /* Load Vibration Pattern Data */
448         check = strchr(value, 'A');
449         if (check) {
450                 *check = '\0';
451                 conf->unlimit = 1;
452                 if (!value)
453                         len = len - 1;
454                 else
455                         len = len - strlen(value) - 1;
456                 value = check + 1;
457         }
458         duration = insert_raw_data_format(&conf->data, value);
459         if (duration < 0) {
460                 conf->pattern_duration = 0;
461                 goto error_out;
462         } else
463                 conf->pattern_duration = duration;
464         SYS_G_LIST_APPEND(vib_conf_list, conf);
465
466         return 0;
467
468 error_out:
469         if (conf) {
470                 if (conf->pattern)
471                         free(conf->pattern);
472                 if (conf->standard)
473                         free(conf->standard);
474         }
475         return -ENOMEM;
476 }
477
478 static void load_standard_vibration_patterns(void)
479 {
480         DIR *dir;
481         struct dirent *dent;
482         int ret;
483
484         dir = opendir(STANDARD_FILE_PATH);
485         if (!dir) {
486                 _E("Failed to load '%s' Use default value.", STANDARD_FILE_PATH);
487                 return;
488         }
489         while ((dent = readdir(dir))) {
490                 if (dent->d_type == DT_DIR)
491                         continue;
492                 ret = load_standard_format(dent->d_name);
493                 if (ret < 0)
494                         _E("Failed to parse %s: %d", dent->d_name, ret);
495         }
496         closedir(dir);
497         _D("Success to load '%s'", STANDARD_FILE_PATH);
498 }
499
500 void pattern_config_parse(void)
501 {
502         int ret;
503
504         ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
505         if (ret < 0)
506                 _E("Failed to load '%s'. Use default value: %d", VIBRATION_CONF_PATH, ret);
507
508         load_standard_vibration_patterns();
509 }
510
511 static int haptic_module_load(void)
512 {
513         int r;
514
515         pattern_config_parse();
516
517         r = hal_device_haptic_get_backend();
518         if (r < 0) {
519                 _E("Failed to load device. ret=%d", r);
520                 return r;
521         }
522
523         /* solution bug
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);
529         if (r < 0) {
530                 _E("Failed to open device. ret=%d", r);
531                 return r;
532         }
533
534         return 0;
535 }
536
537 /*
538 static int convert_magnitude_by_conf(int level)
539 {
540         int i, step;
541
542         if (level < LOW_FEEDBACK_LEVEL)
543                 level = LOW_FEEDBACK_LEVEL;
544         else if (level > HIGH_FEEDBACK_LEVEL)
545                 level = HIGH_FEEDBACK_LEVEL;
546
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];
552                 }
553         }
554
555         _D("Play default level.");
556         return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP;
557 }
558 */
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)
562 {
563         int ret, val;
564
565         ret = hal_device_haptic_get_device_count(&val);
566         if (ret >= 0)
567                 ret = val;
568
569         return g_variant_new("(i)", ret);
570 }
571
572 void haptic_name_owner_changed(GDBusConnection *connection,
573         const gchar     *name,
574         gpointer         user_data)
575 {
576         GList *n;
577         struct haptic_info *info = user_data;
578         int handle;
579
580         _I("%s (sender=%s)", __func__, name);
581
582         if (!info)
583                 return;
584
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);
589         }
590
591         remove_haptic_info(info);
592 }
593
594 static struct haptic_info *add_haptic_info(const char *sender)
595 {
596         struct haptic_info *info;
597
598         assert(sender);
599
600         info = calloc(1, sizeof(struct haptic_info));
601         if (!info)
602                 return NULL;
603
604         info->sender = strdup(sender);
605         if (!info->sender) {
606                 free(info);
607                 return NULL;
608         }
609
610         SYS_G_LIST_APPEND(haptic_handle_list, info);
611
612         info->id_watch = gdbus_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL);
613
614         return info;
615 }
616
617 static int remove_haptic_info(struct haptic_info *info)
618 {
619         assert(info);
620
621         gdbus_unwatch_name(info->id_watch);
622
623         SYS_G_LIST_REMOVE(haptic_handle_list, info);
624         SYS_G_LIST_FREE_LIST(info->handle_list);
625         if (info->sender) {
626                 free(info->sender);
627         }
628         free(info);
629
630         return 0;
631 }
632
633 static struct haptic_info *get_matched_haptic_info(const char *sender)
634 {
635         GList *n;
636         struct haptic_info *info;
637         int len;
638
639         assert(sender);
640
641         len = strlen(sender) + 1;
642         SYS_G_LIST_FOREACH(haptic_handle_list, n, info) {
643                 if (!strncmp(info->sender, sender, len))
644                         return info;
645         }
646
647         return NULL;
648 }
649
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)
653 {
654         int index, handle, ret;
655         struct haptic_info *info;
656
657         /* Load haptic module before booting done */
658         if (hal_device_haptic_check_backend() < 0) {
659                 ret = hal_device_haptic_get_backend();
660                 if (ret < 0)
661                         goto exit;
662         }
663
664         g_variant_get(param, "(i)", &index);
665
666         ret = hal_device_haptic_open_device(&handle);
667         if (ret < 0)
668                 goto exit;
669
670         if (!sender) {
671                 ret = -EPERM;
672                 hal_device_haptic_close_device(handle);
673                 goto exit;
674         }
675
676         info = get_matched_haptic_info(sender);
677         if (!info) {
678                 info = add_haptic_info(sender);
679                 if (!info) {
680                         _E("Failed to create haptic information.");
681                         ret = -EPERM;
682                         hal_device_haptic_close_device(handle);
683                         goto exit;
684                 }
685         }
686
687         SYS_G_LIST_APPEND(info->handle_list, (gpointer)(long)handle);
688
689         ret = handle;
690
691 exit:
692         return g_variant_new("(i)", ret);
693 }
694
695 int clear_current_data(void)
696 {
697         cur_h_data.handle = INVALID_HANDLE;
698         cur_h_data.priority = PRIORITY_MIN;
699
700         if (duration_timer) {
701                 _I("Remove duration_timer.");
702                 g_source_remove(duration_timer);
703                 duration_timer = 0;
704         }
705
706         return 0;
707 }
708
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)
712 {
713         unsigned int handle;
714         int ret;
715         struct haptic_info *info;
716         int cnt;
717
718         g_variant_get(param, "(u)", &handle);
719
720         if (!sender) {
721                 _E("Failed to get sender from dbus message.");
722                 ret = -EPERM;
723                 goto exit;
724         }
725
726         ret = hal_device_haptic_close_device(handle);
727         if (ret < 0)
728                 goto exit;
729
730         if (cur_h_data.handle == handle) {
731                 /* Remove duration_timer for vibrate_effect */
732                 clear_current_data();
733         }
734
735         info = get_matched_haptic_info(sender);
736         if (!info) {
737                 _E("Failed to find the matched haptic info.");
738                 goto exit;
739         }
740
741         SYS_G_LIST_REMOVE(info->handle_list, (gpointer)(long)handle);
742         cnt = SYS_G_LIST_LENGTH(info->handle_list);
743         if (cnt == 0)
744                 remove_haptic_info(info);
745
746 exit:
747         return g_variant_new("(i)", ret);
748 }
749
750 static gboolean _cb(void *data)
751 {
752         if (duration_timer) {
753                 g_source_remove(duration_timer);
754                 duration_timer = 0;
755         }
756
757         cur_h_data.handle = INVALID_HANDLE;
758         cur_h_data.priority = PRIORITY_MIN;
759
760         return G_SOURCE_REMOVE;
761 }
762
763 static void vibrate_monotone_idler_cb(void *data)
764 {
765         struct vibrate_monotone_info *vibrate_info;
766         int ret;
767
768         if (!data)
769                 return;
770
771         vibrate_info = (struct vibrate_monotone_info *)data;
772
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);
775                 free(vibrate_info);
776                 return;
777         }
778
779         if (duration_timer) {
780                 g_source_remove(duration_timer);
781                 duration_timer = 0;
782         }
783
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;
790
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.");
794
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);
798
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);
801
802         free(vibrate_info);
803 }
804
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)
808 {
809         struct vibrate_monotone_info *vibrate_info;
810         unsigned int handle;
811         int duration, level, intensity, priority, ret = 0;
812
813         if ((ret = hal_device_haptic_check_backend()) < 0)
814                 goto exit;
815
816         if (haptic_disabled)
817                 goto exit;
818
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);
821
822         if (intensity < 0) {
823                 ret = -EINVAL;
824                 goto exit;
825         }
826
827         if (priority < PRIORITY_MIN)
828                 priority = PRIORITY_MIN;
829         else if (priority > PRIORITY_TOP)
830                 priority = PRIORITY_TOP;
831
832         if (duration <= 0) {
833                 _E("Skip vibrate handle(%d) requested less than 0.", handle);
834                 ret = -EINVAL;
835                 goto exit;
836         }
837
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.");
840                 ret = -EINVAL;
841                 goto exit;
842         }
843
844         vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
845         if (!vibrate_info) {
846                 _E("Failed to allocate memory for vibrate_info.");
847                 ret = -errno;
848                 goto exit;
849         }
850
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;
856
857         ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
858 exit:
859         return g_variant_new("(i)", ret);
860 }
861
862 static gboolean haptic_duration_play(void *data)
863 {
864         GList *head, *n, *next;
865         struct duration_data *node;
866         int ret = 0;
867
868         if (duration_timer) {
869                 g_source_remove(duration_timer);
870                 duration_timer = 0;
871         }
872
873         if (!data) {
874                 if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
875                         head = cur_h_data.vibration_data;
876                 else {
877                         cur_h_data.handle = INVALID_HANDLE;
878                         cur_h_data.priority = PRIORITY_MIN;
879                         goto out;
880                 }
881         } else
882                 head = (GList *)data;
883
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;
889                 goto out;
890         }
891
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;
900                                 break;
901                         } else {
902                                 next = cur_h_data.vibration_data;
903                                 continue;
904                         }
905                 }
906
907                 duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
908
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);
910
911                 break;
912         }
913         if (ret != 0) {
914                 _D("Auto stop vibration.");
915                 cur_h_data.stop = true;
916         }
917 out:
918         return G_SOURCE_REMOVE;
919 }
920
921 static void vibrate_pattern_idler_cb(void *data)
922 {
923         struct vibrate_pattern_info *vibrate_info;
924         GList *elem;
925         struct vibration_config *conf;
926         char pattern[PATH_MAX];
927         int ret;
928         int unlimit = 0;
929
930         if (!data)
931                 return;
932
933         vibrate_info = (struct vibrate_pattern_info *)data;
934
935         if (!(vibrate_info->pattern)) {
936                 free(vibrate_info);
937                 return;
938         }
939
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);
943                 goto out;
944         }
945
946         snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
947         SYS_G_LIST_FOREACH(vib_conf_list, elem, conf) {
948                 if (!conf->pattern)
949                         continue;
950                 if (strcmp(conf->pattern, pattern))
951                         continue;
952                 if (conf->standard) {
953                         unlimit = conf->unlimit;
954                         snprintf(pattern, sizeof(pattern), "%s", conf->standard);
955                         continue;
956                 }
957
958                 if (unlimit)
959                         cur_h_data.unlimit = unlimit;
960                 else
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");
969
970                 if (conf->pattern_duration <= 0)
971                         break;
972
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.");
977                 }
978                 haptic_duration_play((void *)cur_h_data.vibration_data);
979                 goto out;
980         }
981         _E("Handle(%d) %s is not supported.", vibrate_info->handle, pattern);
982
983 out:
984         free(vibrate_info->pattern);
985         free(vibrate_info);
986 }
987
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)
991 {
992         struct vibrate_pattern_info *vibrate_info;
993         unsigned int handle;
994         char *pattern = NULL;
995         int level, priority, ret = 0;
996
997         if ((ret = hal_device_haptic_check_backend()) < 0)
998                 goto exit;
999
1000         if (haptic_disabled)
1001                 goto exit;
1002
1003         g_variant_get(param, "(usii)",  &handle, &pattern, &level, &priority);
1004
1005         if (level < 0) {
1006                 ret = -EINVAL;
1007                 goto exit;
1008         }
1009
1010         if (priority < PRIORITY_MIN)
1011                 priority = PRIORITY_MIN;
1012         else if (priority > PRIORITY_TOP)
1013                 priority = PRIORITY_TOP;
1014
1015         vibrate_info = calloc(1, sizeof(struct vibrate_pattern_info));
1016         if (!vibrate_info) {
1017                 _E("Failed to allocate memory for vibrate_info.");
1018                 ret = -errno;
1019                 goto exit;
1020         }
1021         vibrate_info->handle = handle;
1022         vibrate_info->pattern = pattern;
1023         pattern = NULL;
1024         if (!vibrate_info->pattern) {
1025                 _E("Failed to allocate memory for pattern.");
1026                 ret = -errno;
1027                 free(vibrate_info);
1028                 goto exit;
1029         }
1030         vibrate_info->level = level;
1031         vibrate_info->priority = priority;
1032
1033         ret = add_idle_request(vibrate_pattern_idler_cb, (void *)vibrate_info);
1034
1035 exit:
1036         g_free(pattern);
1037         return g_variant_new("(i)", ret);
1038 }
1039
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)
1043 {
1044         unsigned int handle;
1045         int ret = 0;
1046
1047         if ((ret = hal_device_haptic_check_backend()) < 0)
1048                 goto exit;
1049
1050         if (haptic_disabled) {
1051                 _I("Haptic disabled.");
1052                 goto exit;
1053         }
1054
1055         g_variant_get(param, "(u)", &handle);
1056
1057         if (cur_h_data.handle != handle) {
1058                 _D("Not the request from current vibration handle(%d). Skip.", handle);
1059                 goto exit;
1060         }
1061
1062         ret = hal_device_haptic_stop_device(handle);
1063         _I("Stop the device(handle=%u) :%d", handle, ret);
1064
1065         /* Remove duration_timer for vibrate_effect */
1066         clear_current_data();
1067
1068 exit:
1069         return g_variant_new("(i)", ret);
1070 }
1071
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)
1075 {
1076         GList *n;
1077         GList *elem;
1078         struct haptic_info *info;
1079
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);
1084         }
1085
1086         return g_variant_new_tuple(NULL, 0);
1087 }
1088
1089 int pattern_is_supported(const char *pattern)
1090 {
1091         GList *elem;
1092         struct vibration_config *conf;
1093         int ret;
1094
1095         if (!pattern)
1096                 return -EINVAL;
1097
1098         ret = 0;
1099         SYS_G_LIST_FOREACH(vib_conf_list, elem, conf) {
1100                 if (!conf->pattern)
1101                         continue;
1102                 if (!strcmp(conf->pattern, pattern)) {
1103                         ret = true;
1104                         break;
1105                 }
1106         }
1107
1108         return ret;
1109 }
1110
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)
1114
1115 {
1116         char *data = NULL;
1117         int ret = 0;
1118
1119         if ((ret = hal_device_haptic_check_backend()) < 0)
1120                 goto exit;
1121
1122         if (haptic_disabled)
1123                 goto exit;
1124
1125         g_variant_get(param, "(s)", &data);
1126
1127         ret = pattern_is_supported(data);
1128
1129         _I("%s is supported: %d", data, ret);
1130
1131 exit:
1132         g_free(data);
1133         return g_variant_new("(i)", ret);
1134 }
1135
1136 static void haptic_poweroff_cb(GDBusConnection  *conn,
1137         const gchar      *sender,
1138         const gchar      *path,
1139         const gchar      *iface,
1140         const gchar      *name,
1141         GVariant         *param,
1142         gpointer          data)
1143 {
1144         int type = POWER_OFF_NONE;
1145         int ret, level;
1146         struct timespec time = {0,};
1147
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));
1150                 return;
1151         }
1152
1153         if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART)
1154                 return;
1155
1156         _D("Poweroff: %d", type);
1157
1158         if (hal_device_haptic_check_backend() < 0) {
1159                 if (haptic_module_load() < 0)
1160                         return ;
1161         }
1162
1163         if (!g_handle) {
1164                 if (hal_device_haptic_open_device(&g_handle) < 0)
1165                         return ;
1166         }
1167
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.");
1170                 return;
1171         }
1172         level = (level/2) + 1;
1173
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);
1180         if (ret < 0) {
1181                 _E("Failed to vibrate_monotone: %d", ret);
1182                 return;
1183         }
1184
1185         /* sleep for vibration */
1186         time.tv_nsec = POWER_OFF_VIB_DURATION * NANO_SECOND_MULTIPLIER;
1187         nanosleep(&time, NULL);
1188         return;
1189 }
1190
1191 static void sound_capturing_cb(keynode_t *key, void *data)
1192 {
1193         int status;
1194
1195         status = vconf_keynode_get_int(key);
1196
1197         /* if sound capture is in use, this value is 1(true). */
1198         if (status == VCONFKEY_RECORDER_STATE_RECORDING)
1199                 haptic_stop();
1200         else
1201                 haptic_start();
1202 }
1203
1204 static int parse_section(struct parse_result *result, void *user_data, int index)
1205 {
1206         struct haptic_config *conf = (struct haptic_config *)user_data;
1207
1208         if (!result)
1209                 return 0;
1210
1211         if (!result->section || !result->name || !result->value)
1212                 return 0;
1213
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.");
1220                         return -EINVAL;
1221                 }
1222                 conf->level_arr = calloc(sizeof(int), conf->level);
1223                 if (!conf->level_arr) {
1224                         _E("Failed to allocate memory for level.");
1225                         return -errno;
1226                 }
1227         } else if (MATCH(result->name, "value")) {
1228                 if (index < 0)
1229                         return -EINVAL;
1230                 conf->level_arr[index] = atoi(result->value);
1231         }
1232
1233         return 0;
1234 }
1235
1236 static int haptic_load_config(struct parse_result *result, void *user_data)
1237 {
1238         struct haptic_config *conf = (struct haptic_config *)user_data;
1239         char name[NAME_MAX];
1240         int ret;
1241         static int index;
1242
1243         if (!result)
1244                 return 0;
1245
1246         if (!result->section || !result->name || !result->value)
1247                 return 0;
1248
1249         // Parsing 'Haptic' section
1250         if (MATCH(result->section, "Haptic")) {
1251                 ret = parse_section(result, user_data, -1);
1252                 if (ret < 0) {
1253                         _E("Failed to parse 'Haptic' section: %d", ret);
1254                         return ret;
1255                 }
1256                 goto out;
1257         }
1258
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);
1264                         if (ret < 0) {
1265                                 _E("Failed to parse 'level' section: %d", ret);
1266                                 return ret;
1267                         }
1268                         goto out;
1269                 }
1270         }
1271
1272 out:
1273         return 0;
1274 }
1275
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 */
1286 };
1287
1288 static const dbus_interface_u dbus_interface = {
1289         .name = VIBRATOR_INTERFACE_HAPTIC,
1290         .methods = hdbus_methods,
1291         .nr_methods = ARRAY_SIZE(hdbus_methods),
1292 };
1293
1294 int haptic_probe(void)
1295 {
1296         /**
1297          * load haptic module.
1298          * if there is no haptic module,
1299          * feedbackd does not activate a haptic interface.
1300          */
1301         return haptic_module_load();
1302 }
1303
1304 static guint id_sig_pwr_off_state;
1305
1306 void haptic_init(void)
1307 {
1308         int r;
1309
1310         /* get haptic data from configuration file */
1311         r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
1312         if (r < 0) {
1313                 _E("Failed to load configuration file(%s): %d", HAPTIC_CONF_PATH, r);
1314                 safe_free(haptic_conf.level_arr);
1315         }
1316
1317         /* init dbus interface */
1318         r = gdbus_register_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface);
1319         if (r < 0)
1320                 _E("Failed to init hdbus interface and method: %d", r);
1321
1322         id_sig_pwr_off_state = gdbus_signal_subscribe(NULL,
1323                         DEVICED_PATH_POWEROFF,
1324                         DEVICED_INTERFACE_POWEROFF,
1325                         SIGNAL_POWEROFF_STATE,
1326                         haptic_poweroff_cb,
1327                         NULL,
1328                         NULL);
1329         if (id_sig_pwr_off_state <= 0) {
1330                 _E("Failed to register signal handler: %d", r);
1331                 return;
1332         }
1333
1334         gdbus_signal_emit(NULL,
1335                         VIBRATOR_PATH_HAPTIC,
1336                         VIBRATOR_INTERFACE_HAPTIC,
1337                         SIGNAL_VIBRATOR_INITIATED,
1338                         NULL);
1339
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);
1343                 if (r != 0)
1344                         _W("Add watch for VCONFKEY_RECORDER_STATE failed.");
1345         }
1346
1347         /* Initialize vibration_handle (Use vibration now) */
1348         cur_h_data.handle = INVALID_HANDLE;
1349         cur_h_data.priority = PRIORITY_MIN;
1350 }
1351
1352 void haptic_exit(void)
1353 {
1354         int r;
1355
1356         /* remove watch */
1357         if (haptic_conf.sound_capture) {
1358                 r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
1359                 if (r != 0)
1360                         _W("Remove watch for VCONFKEY_RECORDER_STATE failed.");
1361         }
1362
1363         /* unregister notifier for below each event */
1364         gdbus_signal_unsubscribe(NULL, id_sig_pwr_off_state);
1365
1366         /* release haptic data memory */
1367         safe_free(haptic_conf.level_arr);
1368
1369         /* haptic exit for feedbackd */
1370         hal_device_haptic_close_device(g_handle);
1371         hal_device_haptic_put_backend();
1372 }
1373
1374 static int haptic_start(void)
1375 {
1376         _I("Start");
1377         haptic_disabled = false;
1378         return 0;
1379 }
1380
1381 static int haptic_stop(void)
1382 {
1383         _I("Stop");
1384         haptic_disabled = true;
1385         return 0;
1386 }