4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include "core/list.h"
28 #include "core/common.h"
29 #include "core/devices.h"
30 #include "core/edbus-handler.h"
31 #include "core/device-notifier.h"
32 #include "core/config-parser.h"
33 #include "powersaver/powersaver.h"
37 #define DATADIR "/usr/share/deviced"
40 #define HAPTIC_CONF_PATH "/etc/deviced/haptic.conf"
42 /* hardkey vibration variable */
43 #define HARDKEY_VIB_ITERATION 1
44 #define HARDKEY_VIB_FEEDBACK 3
45 #define HARDKEY_VIB_PRIORITY 2
46 #define HARDKEY_VIB_DURATION 300
47 #define HAPTIC_FEEDBACK_STEP 20
49 /* power on, power off vibration variable */
50 #define POWER_ON_VIB_DURATION 300
51 #define POWER_OFF_VIB_DURATION 300
52 #define POWER_VIB_FEEDBACK 100
54 #define MAX_EFFECT_BUFFER (64*1024)
56 #ifndef VCONFKEY_RECORDER_STATE
57 #define VCONFKEY_RECORDER_STATE "memory/recorder/state"
58 #define VCONFKEY_RECORDER_STATE_RECORDING 2
61 #define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV))
66 /* haptic operation variable */
67 static dd_list *h_head;
68 static const struct haptic_plugin_ops *h_ops;
69 static enum haptic_type h_type;
70 static bool haptic_disabled;
71 static int powersaver_on = 0;
73 struct haptic_config {
78 static struct haptic_config haptic_conf;
80 static int haptic_start(void);
81 static int haptic_stop(void);
82 static int haptic_internal_init(void);
84 void add_haptic(const struct haptic_ops *ops)
86 DD_LIST_APPEND(h_head, (void*)ops);
89 void remove_haptic(const struct haptic_ops *ops)
91 DD_LIST_REMOVE(h_head, (void*)ops);
94 static int haptic_module_load(void)
96 struct haptic_ops *ops;
100 /* find valid plugin */
101 DD_LIST_FOREACH(h_head, elem, ops) {
102 if (ops->is_valid && ops->is_valid()) {
110 if (!CHECK_VALID_OPS(h_ops, r)) {
111 _E("Can't find the valid haptic device");
116 * we do not use internal vibration except power off.
117 * if the last handle is closed during the playing of vibration,
118 * solution makes unlimited vibration.
119 * so we need at least one handle. */
120 haptic_internal_init();
125 static int convert_magnitude_by_conf(int level)
129 assert(level >= 0 && level <= 100);
131 step = 100 / (haptic_conf.level-1);
132 for (i = 0; i < haptic_conf.level; ++i) {
133 if (level <= i*step) {
134 _D("level changed : %d -> %d", level, haptic_conf.level_arr[i]);
135 return haptic_conf.level_arr[i];
142 static DBusMessage *edbus_get_count(E_DBus_Object *obj, DBusMessage *msg)
144 DBusMessageIter iter;
148 if (!CHECK_VALID_OPS(h_ops, ret))
151 ret = h_ops->get_device_count(&val);
156 reply = dbus_message_new_method_return(msg);
157 dbus_message_iter_init_append(reply, &iter);
158 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
162 static DBusMessage *edbus_open_device(E_DBus_Object *obj, DBusMessage *msg)
164 DBusMessageIter iter;
166 int index, handle, ret;
168 /* Load haptic module before booting done */
169 if (!CHECK_VALID_OPS(h_ops, ret)) {
170 ret = haptic_module_load();
175 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) {
180 ret = h_ops->open_device(index, &handle);
185 reply = dbus_message_new_method_return(msg);
186 dbus_message_iter_init_append(reply, &iter);
187 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
191 static DBusMessage *edbus_close_device(E_DBus_Object *obj, DBusMessage *msg)
193 DBusMessageIter iter;
198 if (!CHECK_VALID_OPS(h_ops, ret))
201 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) {
206 ret = h_ops->close_device(handle);
209 reply = dbus_message_new_method_return(msg);
210 dbus_message_iter_init_append(reply, &iter);
211 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
215 static DBusMessage *edbus_vibrate_monotone(E_DBus_Object *obj, DBusMessage *msg)
217 DBusMessageIter iter;
220 int duration, level, priority, e_handle, ret = 0;
222 if (!CHECK_VALID_OPS(h_ops, ret))
228 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
229 DBUS_TYPE_INT32, &duration,
230 DBUS_TYPE_INT32, &level,
231 DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) {
236 /* convert as per conf value */
237 level = convert_magnitude_by_conf(level);
243 ret = h_ops->vibrate_monotone(handle, duration, level, priority, &e_handle);
248 reply = dbus_message_new_method_return(msg);
249 dbus_message_iter_init_append(reply, &iter);
250 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
255 static DBusMessage *edbus_vibrate_buffer(E_DBus_Object *obj, DBusMessage *msg)
257 DBusMessageIter iter;
261 int size, iteration, level, priority, e_handle, ret = 0;
263 if (!CHECK_VALID_OPS(h_ops, ret))
269 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
270 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
271 DBUS_TYPE_INT32, &iteration,
272 DBUS_TYPE_INT32, &level,
273 DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) {
278 /* convert as per conf value */
279 level = convert_magnitude_by_conf(level);
285 ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle);
290 reply = dbus_message_new_method_return(msg);
291 dbus_message_iter_init_append(reply, &iter);
292 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
296 static DBusMessage *edbus_stop_device(E_DBus_Object *obj, DBusMessage *msg)
298 DBusMessageIter iter;
303 if (!CHECK_VALID_OPS(h_ops, ret))
309 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) {
314 ret = h_ops->stop_device(handle);
317 reply = dbus_message_new_method_return(msg);
318 dbus_message_iter_init_append(reply, &iter);
319 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
323 static DBusMessage *edbus_get_state(E_DBus_Object *obj, DBusMessage *msg)
325 DBusMessageIter iter;
327 int index, state, ret;
329 if (!CHECK_VALID_OPS(h_ops, ret))
332 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) {
337 ret = h_ops->get_device_state(index, &state);
342 reply = dbus_message_new_method_return(msg);
343 dbus_message_iter_init_append(reply, &iter);
344 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
348 static DBusMessage *edbus_create_effect(E_DBus_Object *obj, DBusMessage *msg)
350 static unsigned char data[MAX_EFFECT_BUFFER];
351 static unsigned char *p = data;
352 DBusMessageIter iter, arr;
354 haptic_module_effect_element *elem_arr;
355 int i, size, cnt, ret, bufsize = sizeof(data);
357 if (!CHECK_VALID_OPS(h_ops, ret))
360 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &bufsize,
361 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &elem_arr, &size,
362 DBUS_TYPE_INT32, &cnt, DBUS_TYPE_INVALID)) {
367 if (bufsize > MAX_EFFECT_BUFFER) {
372 for (i = 0; i < cnt; ++i)
373 _D("[%2d] %d %d", i, elem_arr[i].haptic_duration, elem_arr[i].haptic_level);
375 memset(data, 0, MAX_EFFECT_BUFFER);
376 ret = h_ops->create_effect(data, bufsize, elem_arr, cnt);
379 reply = dbus_message_new_method_return(msg);
380 dbus_message_iter_init_append(reply, &iter);
381 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr);
382 dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &p, bufsize);
383 dbus_message_iter_close_container(&iter, &arr);
384 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
388 static DBusMessage *edbus_get_duration(E_DBus_Object *obj, DBusMessage *msg)
390 DBusMessageIter iter;
394 int size, duration, ret;
396 if (!CHECK_VALID_OPS(h_ops, ret))
399 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
400 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
401 DBUS_TYPE_INVALID)) {
406 ret = h_ops->get_buffer_duration(handle, data, &duration);
411 reply = dbus_message_new_method_return(msg);
412 dbus_message_iter_init_append(reply, &iter);
413 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
417 static DBusMessage *edbus_save_binary(E_DBus_Object *obj, DBusMessage *msg)
419 DBusMessageIter iter;
425 if (!CHECK_VALID_OPS(h_ops, ret))
428 if (!dbus_message_get_args(msg, NULL,
429 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
430 DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) {
435 _D("file path : %s", path);
436 ret = h_ops->convert_binary(data, size, path);
439 reply = dbus_message_new_method_return(msg);
440 dbus_message_iter_init_append(reply, &iter);
441 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
445 static unsigned char* convert_file_to_buffer(const char *file_name, int *size)
449 unsigned char *pdata = NULL;
454 /* Get File Stream Pointer */
455 pf = fopen(file_name, "rb");
457 _E("fopen failed : %s", strerror(errno));
461 if (fseek(pf, 0, SEEK_END))
464 file_size = ftell(pf);
465 if (fseek(pf, 0, SEEK_SET))
471 pdata = (unsigned char*)malloc(file_size);
475 if (fread(pdata, 1, file_size, pf) != file_size)
488 _E("failed to convert file to buffer (%s)", strerror(errno));
492 static int haptic_internal_init(void)
495 if (!CHECK_VALID_OPS(h_ops, r))
497 return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle);
500 static int haptic_internal_exit(void)
503 if (!CHECK_VALID_OPS(h_ops, r))
505 return h_ops->close_device(g_handle);
508 static int haptic_hardkey_changed_cb(void *data)
510 int size, level, status, e_handle, ret;
513 if (!CHECK_VALID_OPS(h_ops, ret)) {
514 ret = haptic_module_load();
520 haptic_internal_init();
522 /* if haptic is stopped, do not play vibration */
523 if (haptic_disabled || powersaver_on)
526 if (vconf_get_bool(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, &status) < 0) {
527 _E("fail to get VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL");
531 /* when turn off haptic feedback option */
535 ret = vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &level);
537 _E("fail to get VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT");
538 level = HARDKEY_VIB_FEEDBACK;
541 ret = h_ops->vibrate_monotone(g_handle, HARDKEY_VIB_DURATION,
542 level*HAPTIC_FEEDBACK_STEP, HARDKEY_VIB_PRIORITY, &e_handle);
544 _E("fail to vibrate buffer : %d", ret);
549 static int haptic_poweroff_cb(void *data)
553 if (!CHECK_VALID_OPS(h_ops, ret)) {
554 ret = haptic_module_load();
560 haptic_internal_init();
562 /* power off vibration */
563 ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION,
564 POWER_VIB_FEEDBACK, HARDKEY_VIB_PRIORITY, &e_handle);
566 _E("fail to vibrate_monotone : %d", ret);
570 /* sleep for vibration */
571 usleep(POWER_OFF_VIB_DURATION*1000);
575 static int haptic_powersaver_cb(void *data)
577 int mode = (int)data;
581 powersaver_on = false;
583 case POWERSAVER_BASIC:
584 case POWERSAVER_ENHANCED:
585 powersaver_on = true;
591 _I("changed powersaver %d", powersaver_on);
595 static void sound_capturing_cb(keynode_t *key, void *data)
599 status = vconf_keynode_get_int(key);
601 /* if sound capture is in use, this value is 1(true). */
602 if (status == VCONFKEY_RECORDER_STATE_RECORDING)
608 static int parse_section(struct parse_result *result, void *user_data, int index)
610 struct haptic_config *conf = (struct haptic_config*)user_data;
613 assert(result->section && result->name && result->value);
615 if (MATCH(result->name, "level")) {
616 conf->level = atoi(result->value);
617 conf->level_arr = calloc(sizeof(int), conf->level);
618 if (!conf->level_arr) {
619 _E("failed to allocate memory for level");
622 } else if (MATCH(result->name, "value")) {
625 conf->level_arr[index] = atoi(result->value);
631 static int haptic_load_config(struct parse_result *result, void *user_data)
633 struct haptic_config *conf = (struct haptic_config*)user_data;
636 static int index = 0;
641 if (!result->section || !result->name || !result->value)
644 /* Parsing 'Haptic' section */
645 if (MATCH(result->section, "Haptic")) {
646 ret = parse_section(result, user_data, -1);
648 _E("failed to parse [Haptic] section : %d", ret);
654 /* Parsing 'Level' section */
655 for (index = 0; index < conf->level; ++index) {
656 snprintf(name, sizeof(name), "level%d", index);
657 if (MATCH(result->section, name)) {
658 ret = parse_section(result, user_data, index);
660 _E("failed to parse [level] section : %d", ret);
671 static const struct edbus_method edbus_methods[] = {
672 { "GetCount", NULL, "i", edbus_get_count },
673 { "OpenDevice", "i", "i", edbus_open_device },
674 { "CloseDevice", "u", "i", edbus_close_device },
675 { "StopDevice", "u", "i", edbus_stop_device },
676 { "VibrateMonotone", "uiii", "i", edbus_vibrate_monotone },
677 { "VibrateBuffer", "uayiii", "i", edbus_vibrate_buffer },
678 { "GetState", "i", "i", edbus_get_state },
679 { "GetDuration", "uay", "i", edbus_get_duration },
680 { "CreateEffect", "iayi", "ayi", edbus_create_effect },
681 { "SaveBinary", "ays", "i", edbus_save_binary },
682 /* Add methods here */
685 static void haptic_init(void *data)
689 /* Load haptic module */
690 haptic_module_load();
692 /* get haptic data from configuration file */
693 r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf);
695 _E("failed to load configuration file(%s) : %d", HAPTIC_CONF_PATH, r);
696 safe_free(haptic_conf.level_arr);
699 /* init dbus interface */
700 r = register_edbus_method(DEVICED_PATH_HAPTIC, edbus_methods, ARRAY_SIZE(edbus_methods));
702 _E("fail to init edbus method(%d)", r);
704 /* register notifier for below each event */
705 register_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb);
706 register_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb);
707 register_notifier(DEVICE_NOTIFIER_PMQOS_ULTRAPOWERSAVING,
708 haptic_powersaver_cb);
710 /* add watch for sound capturing value */
711 vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL);
714 static void haptic_exit(void *data)
716 struct haptic_ops *ops;
721 vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb);
723 /* unregister notifier for below each event */
724 unregister_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb);
725 unregister_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb);
726 unregister_notifier(DEVICE_NOTIFIER_PMQOS_ULTRAPOWERSAVING,
727 haptic_powersaver_cb);
729 /* release haptic data memory */
730 safe_free(haptic_conf.level_arr);
732 if (!CHECK_VALID_OPS(h_ops, r))
735 /* haptic exit for deviced */
736 haptic_internal_exit();
739 DD_LIST_FOREACH(h_head, elem, ops) {
740 if (ops->is_valid && ops->is_valid()) {
749 static int haptic_start(void)
752 haptic_disabled = false;
756 static int haptic_stop(void)
759 haptic_disabled = true;
763 static const struct device_ops haptic_device_ops = {
764 .priority = DEVICE_PRIORITY_NORMAL,
770 DEVICE_OPS_REGISTER(&haptic_device_ops)