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.
26 #include "core/list.h"
27 #include "core/common.h"
28 #include "core/devices.h"
29 #include "core/edbus-handler.h"
30 #include "core/device-notifier.h"
34 #define DATADIR "/usr/share/deviced"
37 /* hardkey vibration variable */
38 #define HARDKEY_VIB_RESOURCE DATADIR"/HW_touch_30ms_sharp.ivt"
39 #define HARDKEY_VIB_ITERATION 1
40 #define HARDKEY_VIB_FEEDBACK 3
41 #define HARDKEY_VIB_PRIORITY 2
42 #define HAPTIC_FEEDBACK_STEP 20
44 /* power on, power off vibration variable */
45 #define POWER_ON_VIB_DURATION 300
46 #define POWER_OFF_VIB_DURATION 300
47 #define POWER_VIB_FEEDBACK 100
49 #define MAX_EFFECT_BUFFER (64*1024)
53 #define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV))
58 /* haptic operation variable */
59 static dd_list *h_head;
60 static const struct haptic_plugin_ops *h_ops;
61 static bool haptic_disabled;
63 static int haptic_start(void);
64 static int haptic_stop(void);
65 static int haptic_internal_init(void);
67 void add_haptic(const struct haptic_ops *ops)
69 DD_LIST_APPEND(h_head, (void*)ops);
72 void remove_haptic(const struct haptic_ops *ops)
74 DD_LIST_REMOVE(h_head, (void*)ops);
77 static int haptic_module_load(void)
79 struct haptic_ops *ops;
83 /* find valid plugin */
84 DD_LIST_FOREACH(h_head, elem, ops) {
85 if (ops->is_valid && ops->is_valid()) {
92 if (!CHECK_VALID_OPS(h_ops, r)) {
93 _E("Can't find the valid haptic device");
98 we do not use internal vibration except power off
99 but module does not stop vibrating, although called terminate function */
100 haptic_internal_init();
105 static DBusMessage *edbus_get_count(E_DBus_Object *obj, DBusMessage *msg)
107 DBusMessageIter iter;
111 if (!CHECK_VALID_OPS(h_ops, ret))
114 ret = h_ops->get_device_count(&val);
119 reply = dbus_message_new_method_return(msg);
120 dbus_message_iter_init_append(reply, &iter);
121 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
125 static DBusMessage *edbus_open_device(E_DBus_Object *obj, DBusMessage *msg)
127 DBusMessageIter iter;
129 int index, handle, ret;
131 if (!CHECK_VALID_OPS(h_ops, ret))
134 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) {
139 ret = h_ops->open_device(index, &handle);
144 reply = dbus_message_new_method_return(msg);
145 dbus_message_iter_init_append(reply, &iter);
146 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
150 static DBusMessage *edbus_close_device(E_DBus_Object *obj, DBusMessage *msg)
152 DBusMessageIter iter;
157 if (!CHECK_VALID_OPS(h_ops, ret))
160 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) {
165 ret = h_ops->close_device(handle);
168 reply = dbus_message_new_method_return(msg);
169 dbus_message_iter_init_append(reply, &iter);
170 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
174 static DBusMessage *edbus_vibrate_monotone(E_DBus_Object *obj, DBusMessage *msg)
176 DBusMessageIter iter;
179 int duration, level, priority, e_handle, ret;
181 if (!CHECK_VALID_OPS(h_ops, ret))
184 if (haptic_disabled) {
189 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
190 DBUS_TYPE_INT32, &duration,
191 DBUS_TYPE_INT32, &level,
192 DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) {
197 ret = h_ops->vibrate_monotone(handle, duration, level, priority, &e_handle);
202 reply = dbus_message_new_method_return(msg);
203 dbus_message_iter_init_append(reply, &iter);
204 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
209 static DBusMessage *edbus_vibrate_buffer(E_DBus_Object *obj, DBusMessage *msg)
211 DBusMessageIter iter;
215 int size, iteration, level, priority, e_handle, ret;
217 if (!CHECK_VALID_OPS(h_ops, ret))
220 if (haptic_disabled) {
225 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
226 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
227 DBUS_TYPE_INT32, &iteration,
228 DBUS_TYPE_INT32, &level,
229 DBUS_TYPE_INT32, &priority, DBUS_TYPE_INVALID)) {
234 ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle);
239 reply = dbus_message_new_method_return(msg);
240 dbus_message_iter_init_append(reply, &iter);
241 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
245 static DBusMessage *edbus_stop_device(E_DBus_Object *obj, DBusMessage *msg)
247 DBusMessageIter iter;
252 if (!CHECK_VALID_OPS(h_ops, ret))
255 if (haptic_disabled) {
260 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) {
265 ret = h_ops->stop_device(handle);
268 reply = dbus_message_new_method_return(msg);
269 dbus_message_iter_init_append(reply, &iter);
270 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
274 static DBusMessage *edbus_get_state(E_DBus_Object *obj, DBusMessage *msg)
276 DBusMessageIter iter;
278 int index, state, ret;
280 if (!CHECK_VALID_OPS(h_ops, ret))
283 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &index, DBUS_TYPE_INVALID)) {
288 ret = h_ops->get_device_state(index, &state);
293 reply = dbus_message_new_method_return(msg);
294 dbus_message_iter_init_append(reply, &iter);
295 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
299 static DBusMessage *edbus_create_effect(E_DBus_Object *obj, DBusMessage *msg)
301 static unsigned char data[MAX_EFFECT_BUFFER];
302 static unsigned char *p = data;
303 DBusMessageIter iter, arr;
305 haptic_module_effect_element *elem_arr;
306 int i, size, cnt, ret, bufsize = sizeof(data);
308 if (!CHECK_VALID_OPS(h_ops, ret))
311 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_INT32, &bufsize,
312 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &elem_arr, &size,
313 DBUS_TYPE_INT32, &cnt, DBUS_TYPE_INVALID)) {
318 if (bufsize > MAX_EFFECT_BUFFER) {
323 for (i = 0; i < cnt; ++i)
324 _D("[%2d] %d %d", i, elem_arr[i].haptic_duration, elem_arr[i].haptic_level);
326 memset(data, 0, MAX_EFFECT_BUFFER);
327 ret = h_ops->create_effect(data, bufsize, elem_arr, cnt);
330 reply = dbus_message_new_method_return(msg);
331 dbus_message_iter_init_append(reply, &iter);
332 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &arr);
333 dbus_message_iter_append_fixed_array(&arr, DBUS_TYPE_BYTE, &p, bufsize);
334 dbus_message_iter_close_container(&iter, &arr);
335 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
339 static DBusMessage *edbus_get_duration(E_DBus_Object *obj, DBusMessage *msg)
341 DBusMessageIter iter;
345 int size, duration, ret;
347 if (!CHECK_VALID_OPS(h_ops, ret))
350 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &handle,
351 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
352 DBUS_TYPE_INVALID)) {
357 ret = h_ops->get_buffer_duration(handle, data, &duration);
362 reply = dbus_message_new_method_return(msg);
363 dbus_message_iter_init_append(reply, &iter);
364 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
368 static DBusMessage *edbus_save_binary(E_DBus_Object *obj, DBusMessage *msg)
370 DBusMessageIter iter;
376 if (!CHECK_VALID_OPS(h_ops, ret))
379 if (!dbus_message_get_args(msg, NULL,
380 DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, &size,
381 DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID)) {
386 _D("file path : %s", path);
387 ret = h_ops->convert_binary(data, size, path);
390 reply = dbus_message_new_method_return(msg);
391 dbus_message_iter_init_append(reply, &iter);
392 dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret);
396 static unsigned char* convert_file_to_buffer(const char *file_name, int *size)
400 unsigned char *pdata = NULL;
405 /* Get File Stream Pointer */
406 pf = fopen(file_name, "rb");
408 _E("fopen failed : %s", strerror(errno));
412 if (fseek(pf, 0, SEEK_END))
415 file_size = ftell(pf);
416 if (fseek(pf, 0, SEEK_SET))
422 pdata = (unsigned char*)malloc(file_size);
426 if (fread(pdata, 1, file_size, pf) != file_size)
439 _E("failed to convert file to buffer (%s)", strerror(errno));
443 static int haptic_internal_init(void)
446 if (!CHECK_VALID_OPS(h_ops, r))
448 return h_ops->open_device(HAPTIC_MODULE_DEVICE_ALL, &g_handle);
451 static int haptic_internal_exit(void)
454 if (!CHECK_VALID_OPS(h_ops, r))
456 return h_ops->close_device(g_handle);
459 static int haptic_booting_done_cb(void *data)
461 return haptic_module_load();
464 static int haptic_hardkey_changed_cb(void *data)
466 int size, level, status, e_handle, ret, cnt = RETRY_CNT;
469 while (!CHECK_VALID_OPS(h_ops, ret) && cnt--) {
470 haptic_module_load();
476 haptic_internal_init();
478 if (vconf_get_bool(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, &status) < 0) {
479 _E("fail to get VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL");
483 /* when turn off haptic feedback option */
487 buf = convert_file_to_buffer(HARDKEY_VIB_RESOURCE, &size);
491 ret = vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &level);
493 _E("fail to get VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT");
494 level = HARDKEY_VIB_FEEDBACK;
497 ret = h_ops->vibrate_buffer(g_handle, buf, HARDKEY_VIB_ITERATION,
498 level*HAPTIC_FEEDBACK_STEP, HARDKEY_VIB_PRIORITY, &e_handle);
500 _E("fail to vibrate buffer : %d", ret);
506 static int haptic_poweroff_cb(void *data)
508 int e_handle, ret, cnt = RETRY_CNT;
510 while (!CHECK_VALID_OPS(h_ops, ret) && cnt--) {
511 haptic_module_load();
517 haptic_internal_init();
519 /* power off vibration */
520 ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION,
521 POWER_VIB_FEEDBACK, HARDKEY_VIB_PRIORITY, &e_handle);
523 _E("fail to vibrate_monotone : %d", ret);
527 /* sleep for vibration */
528 usleep(POWER_OFF_VIB_DURATION*1000);
532 static int haptic_powersaver_cb(void *data)
534 int powersaver_on = (int)data;
544 static const struct edbus_method edbus_methods[] = {
545 { "GetCount", NULL, "i", edbus_get_count },
546 { "OpenDevice", "i", "i", edbus_open_device },
547 { "CloseDevice", "u", "i", edbus_close_device },
548 { "StopDevice", "u", "i", edbus_stop_device },
549 { "VibrateMonotone", "uiii", "i", edbus_vibrate_monotone },
550 { "VibrateBuffer", "uayiii", "i", edbus_vibrate_buffer },
551 { "GetState", "i", "i", edbus_get_state },
552 { "GetDuration", "uay", "i", edbus_get_duration },
553 { "CreateEffect", "iayi", "ayi", edbus_create_effect },
554 { "SaveBinary", "ays", "i", edbus_save_binary },
555 /* Add methods here */
558 static void haptic_init(void *data)
562 /* init dbus interface */
563 r = register_edbus_method(DEVICED_PATH_HAPTIC, edbus_methods, ARRAY_SIZE(edbus_methods));
565 _E("fail to init edbus method(%d)", r);
567 /* register notifier for below each event */
568 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, haptic_booting_done_cb);
569 register_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb);
570 register_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb);
571 register_notifier(DEVICE_NOTIFIER_POWERSAVER, haptic_powersaver_cb);
574 static void haptic_exit(void *data)
576 struct haptic_ops *ops;
580 /* unregister notifier for below each event */
581 unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, haptic_booting_done_cb);
582 unregister_notifier(DEVICE_NOTIFIER_TOUCH_HARDKEY, haptic_hardkey_changed_cb);
583 unregister_notifier(DEVICE_NOTIFIER_POWEROFF_HAPTIC, haptic_poweroff_cb);
584 unregister_notifier(DEVICE_NOTIFIER_POWERSAVER, haptic_powersaver_cb);
586 if (!CHECK_VALID_OPS(h_ops, r))
589 /* haptic exit for deviced */
590 haptic_internal_exit();
593 DD_LIST_FOREACH(h_head, elem, ops) {
594 if (ops->is_valid && ops->is_valid()) {
603 static int haptic_start(void)
606 haptic_disabled = false;
610 static int haptic_stop(void)
613 haptic_disabled = true;
617 static const struct device_ops haptic_device_ops = {
618 .priority = DEVICE_PRIORITY_NORMAL,
624 DEVICE_OPS_REGISTER(&haptic_device_ops)