3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
28 #include "feedback-ids.h"
32 #include "xmlparser.h"
35 #define DEFAULT_VIB_LEVEL 3
36 #define HAPTIC_FEEDBACK_STEP 20 /**< feedback max / slider step */
38 #define HAPTIC_DEVICE 0
42 HAPTIC_PRIORITY_MIN = 0,
43 HAPTIC_PRIORITY_MIDDLE,
49 HAPTIC_ITERATION_ONCE = 1,
50 HAPTIC_ITERATION_INFINITE = 256,
53 #define VIBRATION_XML "/usr/share/feedback/vibration.xml"
55 #define METHOD_OPEN "OpenDevice"
56 #define METHOD_CLOSE "CloseDevice"
57 #define METHOD_VIBRATE_BUFFER "VibrateBuffer"
58 #define METHOD_STOP "StopDevice"
61 static int noti_vibstatus;
63 static int noti_level;
64 static int feedbackstatus;
66 static unsigned int v_handle;
67 static xmlDocPtr v_doc;
69 static char haptic_file[FEEDBACK_PATTERN_END][NAME_MAX];
71 static int haptic_open(void)
76 snprintf(buf_index, sizeof(buf_index), "%d", HAPTIC_DEVICE);
79 return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_HAPTIC,
80 DEVICED_INTERFACE_HAPTIC, METHOD_OPEN,
84 static int haptic_close(unsigned int handle)
89 snprintf(buf_handle, sizeof(buf_handle), "%u", handle);
92 return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_HAPTIC,
93 DEVICED_INTERFACE_HAPTIC, METHOD_CLOSE,
97 static int haptic_vibrate_buffer(unsigned int handle,
98 const unsigned char *buffer,
106 char buf_iteration[32];
107 char buf_feedback[32];
108 char buf_priority[32];
109 struct dbus_byte bytes;
111 snprintf(buf_handle, sizeof(buf_handle), "%u", handle);
115 arr[2] = (char*)&bytes;
116 snprintf(buf_iteration, sizeof(buf_iteration), "%d", iteration);
117 arr[3] = buf_iteration;
118 snprintf(buf_feedback, sizeof(buf_feedback), "%d", feedback);
119 arr[4] = buf_feedback;
120 snprintf(buf_priority, sizeof(buf_priority), "%d", priority);
121 arr[5] = buf_priority;
123 return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_HAPTIC,
124 DEVICED_INTERFACE_HAPTIC, METHOD_VIBRATE_BUFFER,
128 static int haptic_vibrate_stop(unsigned int handle)
133 snprintf(buf_handle, sizeof(buf_handle), "%u", handle);
136 return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_HAPTIC,
137 DEVICED_INTERFACE_HAPTIC, METHOD_STOP,
141 static unsigned char* convert_file_to_buffer(const char *file_name, int *size)
145 unsigned char *pdata = NULL;
150 /* Get File Stream Pointer */
151 pf = fopen(file_name, "rb");
153 _E("fopen failed : %d", errno);
157 if (fseek(pf, 0, SEEK_END))
160 file_size = ftell(pf);
161 if (fseek(pf, 0, SEEK_SET))
167 pdata = (unsigned char*)malloc(file_size);
171 if (fread(pdata, 1, file_size, pf) != file_size)
184 _E("failed to convert file to buffer (%d)", errno);
188 static void feedback_noti_vibstatus_cb(keynode_t *key, void* data)
190 noti_vibstatus = vconf_keynode_get_bool(key);
193 static void feedback_vib_cb(keynode_t *key, void* data)
195 vib_level = vconf_keynode_get_int(key);
198 static void feedback_noti_cb(keynode_t *key, void* data)
200 noti_level = vconf_keynode_get_int(key);
203 static void feedback_feedbackstatus_cb(keynode_t *key, void* data)
205 feedbackstatus = vconf_keynode_get_bool(key);
208 static int get_priority(feedback_pattern_e pattern)
210 if (pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD)
211 return HAPTIC_PRIORITY_MIN;
213 return HAPTIC_PRIORITY_MIDDLE;
216 static int get_haptic_level(feedback_pattern_e pattern)
220 if (pattern >= FEEDBACK_PATTERN_MESSAGE && pattern <= FEEDBACK_PATTERN_SMART_ALERT)
221 level = noti_level * HAPTIC_FEEDBACK_STEP;
223 level = vib_level * HAPTIC_FEEDBACK_STEP;
225 _D("Call status : %d, pattern : %s, level : %d", callstatus, str_pattern[pattern], level);
226 if (callstatus == VCONFKEY_CALL_VOICE_ACTIVE
227 || callstatus == VCONFKEY_CALL_VIDEO_ACTIVE) {
228 // if call status is ON, vibration magnitude is 20%
230 _D("level changed : %d", level);
236 static bool get_always_alert_case(feedback_pattern_e pattern)
239 case FEEDBACK_PATTERN_KEY0 ... FEEDBACK_PATTERN_KEY_BACK:
240 case FEEDBACK_PATTERN_HOLD:
244 case FEEDBACK_PATTERN_SIP:
245 case FEEDBACK_PATTERN_SIP_BACKSPACE:
246 case FEEDBACK_PATTERN_SIP_FUNCTION:
247 case FEEDBACK_PATTERN_SIP_FJKEY:
249 case FEEDBACK_PATTERN_TIMER:
250 case FEEDBACK_PATTERN_TIMER_ON_CALL:
251 case FEEDBACK_PATTERN_WAKEUP:
252 case FEEDBACK_PATTERN_WAKEUP_ON_CALL:
254 case FEEDBACK_PATTERN_MESSAGE_ON_CALL:
255 case FEEDBACK_PATTERN_EMAIL_ON_CALL:
256 case FEEDBACK_PATTERN_GENERAL_ON_CALL:
257 if (alert_callstatus)
260 case FEEDBACK_PATTERN_MESSAGE:
261 case FEEDBACK_PATTERN_EMAIL:
265 case FEEDBACK_PATTERN_3RD_APPLICATION:
266 case FEEDBACK_PATTERN_SMART_ALERT:
267 case FEEDBACK_PATTERN_SEND_SOS_MESSAGE:
268 case FEEDBACK_PATTERN_END_SOS_MESSAGE:
269 case FEEDBACK_PATTERN_CMAS:
270 case FEEDBACK_PATTERN_OUTGOING_CALL:
271 case FEEDBACK_PATTERN_MMS:
272 case FEEDBACK_PATTERN_HOURLY_ALERT:
274 case FEEDBACK_PATTERN_SPEED_UP:
275 case FEEDBACK_PATTERN_SLOW_DOWN:
276 case FEEDBACK_PATTERN_KEEP_THIS_PACE:
277 case FEEDBACK_PATTERN_GOAL_ACHIEVED:
278 case FEEDBACK_PATTERN_EXERCISE_COUNT:
279 case FEEDBACK_PATTERN_START_CUE:
280 /* except mute case */
281 if (is_sound_mode() || vibstatus)
284 case FEEDBACK_PATTERN_CHARGERCONN_ON_CALL:
285 case FEEDBACK_PATTERN_CHARGING_ERROR_ON_CALL:
286 case FEEDBACK_PATTERN_LOWBATT_ON_CALL:
287 /* no matter sound profile */
295 static bool get_always_off_case(feedback_pattern_e pattern)
298 case FEEDBACK_PATTERN_KEY0 ... FEEDBACK_PATTERN_KEY_BACK:
299 case FEEDBACK_PATTERN_HOLD:
309 static int get_xml_data(xmlDocPtr doc, feedback_pattern_e pattern, struct xmlData **data)
312 struct xmlData *retData;
314 cur = xml_find(doc, VIBRATION_STR, (const xmlChar*)str_pattern[pattern]);
315 /* This pattern does not have sound file to play */
319 retData = xml_parse(doc, cur);
320 if (retData == NULL) {
321 _E("xml_parse fail");
329 static void release_xml_data(struct xmlData *data)
337 static void vibrator_init(void)
342 v_doc = xml_open(VIBRATION_XML);
344 _E("xml_open(%s) fail", VIBRATION_XML);
351 _E("haptic_open ==> FAIL!! : %d", ret);
357 /* Set vibration handle */
358 v_handle = (unsigned int)ret;
360 /* check vibration status */
361 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, ¬i_vibstatus) < 0)
362 _W("VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL ==> FAIL!!");
364 /* check vib_level */
365 if (vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) < 0)
366 _W("VCONFKEY_FEEDBACK_VIBRATION_LEVEL_INT ==> FAIL!!");
368 /* check noti_level */
369 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) < 0)
370 _W("VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT ==> FAIL!!");
373 if(vconf_get_bool(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, &feedbackstatus) < 0)
374 _W("VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL ==> FAIL!!");
376 /* add watch for status value */
377 vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, feedback_noti_vibstatus_cb, NULL);
378 vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb, NULL);
379 vconf_notify_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb, NULL);
380 vconf_notify_key_changed(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, feedback_feedbackstatus_cb, NULL);
383 static void vibrator_exit(void)
388 vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, feedback_noti_vibstatus_cb);
389 vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb);
390 vconf_ignore_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb);
391 vconf_ignore_key_changed(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, feedback_feedbackstatus_cb);
394 ret = haptic_close(v_handle);
396 _E("haptic_close is failed : %d", ret);
406 static int vibrator_play(feedback_pattern_e pattern)
409 struct xmlData *data;
413 if (!v_handle || !v_doc) {
414 _E("Not initialize");
418 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) < 0) {
419 _D("fail to get vibration status, will work as turning off");
423 if (vibstatus == 0 && !get_always_alert_case(pattern)) {
424 _D("Vibration condition is OFF (vibstatus : %d)", vibstatus);
428 if (vibstatus && get_always_off_case(pattern)) {
429 _D("Vibration always off condition");
433 /* if there is a file path user defined */
434 path = haptic_file[pattern];
436 buf = convert_file_to_buffer(path, &size);
438 _E("convert_file_to_buffer is failed");
442 ret = haptic_vibrate_buffer(v_handle, buf, size, HAPTIC_ITERATION_ONCE,
443 get_haptic_level(pattern), get_priority(pattern));
445 _E("haptic_vibrate_buffer is failed");
454 ret = get_xml_data(v_doc, pattern, &data);
455 if (ret == -ENOENT) {
456 _D("No vibration case(%s)", str_pattern[pattern]);
461 _E("get_xml_data fail");
465 if (data->data == NULL) {
466 _D("No vibration case(%s)", str_pattern[pattern]);
467 release_xml_data(data);
471 /* play haptic buffer */
472 ret = haptic_vibrate_buffer(v_handle, (unsigned char*)data->data, data->size, HAPTIC_ITERATION_ONCE,
473 get_haptic_level(pattern), get_priority(pattern));
475 _E("haptic_vibrate_buffer is failed");
476 release_xml_data(data);
480 release_xml_data(data);
484 static int vibrator_stop(void)
488 if (!v_handle || !v_doc) {
489 _E("Not initialize");
493 /* stop haptic device */
494 ret = haptic_vibrate_stop(v_handle);
496 _E("haptic_vibrate_stop is failed");
503 static int vibrator_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
505 const char *cur_path;
507 assert(buf != NULL && buflen > 0);
509 cur_path = haptic_file[pattern];
511 _E("This pattern(%s) in vibrator type is not supported to play", str_pattern[pattern]);
512 snprintf(buf, buflen, "NULL");
516 snprintf(buf, buflen, "%s", cur_path);
520 static int vibrator_set_path(feedback_pattern_e pattern, char *path)
526 * check the path is valid
527 * if path is null, below operation is ignored
529 if (path && stat(path, &buf)) {
530 _E("%s is not presents", path);
534 ppath = haptic_file[pattern];
536 /* if path is NULL, this pattern set to default file */
538 snprintf(ppath, NAME_MAX, "%s", path);
540 memset(ppath, 0, NAME_MAX);
542 _D("The file of pattern(%s) is changed to [%s]", str_pattern[pattern], path);
546 static const struct device_ops vibrator_device_ops = {
547 .type = FEEDBACK_TYPE_VIBRATION,
548 .init = vibrator_init,
549 .exit = vibrator_exit,
550 .play = vibrator_play,
551 .stop = vibrator_stop,
552 .get_path = vibrator_get_path,
553 .set_path = vibrator_set_path,
556 DEVICE_OPS_REGISTER(&vibrator_device_ops);