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.
25 #include <sys/types.h>
32 #include "feedback-internal.h"
33 #include "feedback-file.h"
34 #include "feedback-str.h"
35 #include "feedback-log.h"
36 #include "xmlparser.h"
38 #define FEEDBACK_RETRY_CNT 1
39 #define MAX_FILE_PATH 512
41 #define DEFAULT_FEEDBACK_HANDLE 0x0F
43 #define VIBRATION_XML "/usr/share/feedback/vibration.xml"
46 haptic_device_h v_handle;
52 static int noti_level;
55 static void feedback_vibstatus_cb(keynode_t *key, void* data)
57 vibstatus = vconf_keynode_get_bool(key);
60 static void feedback_vib_cb(keynode_t *key, void* data)
62 vib_level = vconf_keynode_get_int(key);
65 static void feedback_noti_cb(keynode_t *key, void* data)
67 noti_level = vconf_keynode_get_int(key);
70 static void feedback_callstatus_cb(keynode_t *key, void* data)
72 callstatus = vconf_keynode_get_int(key);
75 feedback_pattern_e feedback_get_alert_on_call_key(feedback_pattern_e pattern)
78 case FEEDBACK_PATTERN_MESSAGE:
79 case FEEDBACK_PATTERN_EMAIL:
80 case FEEDBACK_PATTERN_WAKEUP:
81 case FEEDBACK_PATTERN_SCHEDULE:
82 case FEEDBACK_PATTERN_TIMER:
83 case FEEDBACK_PATTERN_GENERAL:
84 case FEEDBACK_PATTERN_CHARGERCONN:
85 case FEEDBACK_PATTERN_FULLCHARGED:
86 case FEEDBACK_PATTERN_LOWBATT:
87 return (feedback_pattern_e)(pattern+1);
95 static haptic_priority_e feedback_get_priority(feedback_pattern_e pattern)
97 if (pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD)
98 return HAPTIC_PRIORITY_MIN;
100 return HAPTIC_PRIORITY_MIDDLE;
103 static int feedback_get_haptic_level(feedback_pattern_e pattern)
107 if (pattern >= FEEDBACK_PATTERN_MESSAGE && pattern <= FEEDBACK_PATTERN_GENERAL_ON_CALL)
112 FEEDBACK_LOG("Call status : %d, pattern : %s, level : %d", callstatus, str_pattern[pattern], level);
113 if (callstatus != VCONFKEY_CALL_OFF) {
114 // if call status is ON, vibration magnitude is 20%
115 level = (int)(level*0.2f);
116 level = (level < 1) ? 1 : level;
117 FEEDBACK_LOG("level changed : %d", level);
124 static bool feedback_get_always_alert_case(feedback_pattern_e pattern)
127 case FEEDBACK_PATTERN_WAKEUP:
128 case FEEDBACK_PATTERN_WAKEUP_ON_CALL:
136 static int feedback_get_data(xmlDocPtr doc, feedback_pattern_e pattern, struct xmlData **data)
139 struct xmlData *retData;
141 cur = xml_find(doc, (const xmlChar*)str_pattern[pattern]);
143 FEEDBACK_ERROR("xml_find fail");
147 retData = xml_parse(doc, cur);
148 if (retData == NULL) {
149 FEEDBACK_ERROR("xml_parse fail");
157 static void feedback_release_data(struct xmlData *data)
165 static int feedback_change_symlink(const char *sym_path, const char *new_path)
169 if (sym_path == NULL || strlen(sym_path) == 0) {
170 FEEDBACK_ERROR("Invalid parameter : sym_path(NULL)");
171 return FEEDBACK_ERROR_INVALID_PARAMETER;
174 if (new_path == NULL || strlen(new_path) == 0) {
175 FEEDBACK_ERROR("Invalid paramter : new_path(NULL)");
176 return FEEDBACK_ERROR_INVALID_PARAMETER;
179 // check symbolic link file existence
180 if (stat(sym_path, &buf)) {
181 FEEDBACK_ERROR("file(%s) is not presents", sym_path);
182 return FEEDBACK_ERROR_OPERATION_FAILED;
185 if (unlink(sym_path) < 0) {
186 FEEDBACK_LOG("unlink(%s) : %s", sym_path, strerror(errno));
189 if (symlink(new_path, sym_path) < 0) {
190 FEEDBACK_ERROR("symlink(%s) : %s", sym_path, strerror(errno));
191 return FEEDBACK_ERROR_OPERATION_FAILED;
194 return FEEDBACK_ERROR_NONE;
197 static int feedback_restore_default_file(feedback_type_e type, feedback_pattern_e pattern)
199 const char *cur_path = NULL;
200 char default_path[MAX_FILE_PATH] = {0,};
204 if (type <= FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END) {
205 FEEDBACK_ERROR("Invalid parameter : type(%s)", str_type[type]);
206 return FEEDBACK_ERROR_INVALID_PARAMETER;
209 if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= FEEDBACK_PATTERN_END) {
210 FEEDBACK_ERROR("Invalid parameter : pattern(%s)", str_pattern[pattern]);
211 return FEEDBACK_ERROR_INVALID_PARAMETER;
214 if (type == FEEDBACK_TYPE_VIBRATION) {
215 cur_path = haptic_file[pattern];
218 // if there isn't cur_path, it already returns before calling this api
219 if (cur_path == NULL || strlen(cur_path) == 0) {
220 FEEDBACK_ERROR("Invalid parameter : cur_path(NULL)");
221 return FEEDBACK_ERROR_OPERATION_FAILED;
224 temp = strcat(default_path, FEEDBACK_ORIGIN_DATA_DIR);
225 strcat(temp, cur_path+strlen(FEEDBACK_DATA_DIR));
226 FEEDBACK_LOG("default_path : %s", default_path);
228 ret = feedback_change_symlink(cur_path, default_path);
229 if (FEEDBACK_FAILED(ret)) {
230 FEEDBACK_ERROR("change_symlink is failed");
231 return FEEDBACK_ERROR_OPERATION_FAILED;
234 return FEEDBACK_ERROR_NONE;
237 int feedback_init(feedback_h *handle)
239 FEEDBACK_HANDLE *phandle;
240 haptic_device_h v_handle;
244 /* check vibration status */
245 if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) < 0) {
246 FEEDBACK_ERROR("vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) ==> FAIL!!");
247 return FEEDBACK_ERROR_OPERATION_FAILED;
250 /* check vib_level */
251 if (vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) < 0) {
252 FEEDBACK_ERROR("vconf_get_int(VCONFKEY_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) ==> FAIL!!");
253 return FEEDBACK_ERROR_OPERATION_FAILED;
256 /* check noti_level */
257 if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) < 0) {
258 FEEDBACK_ERROR("vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) ==> FAIL!!");
259 return FEEDBACK_ERROR_OPERATION_FAILED;
262 /* check call status */
263 if (vconf_get_int(VCONFKEY_CALL_STATE, &callstatus) < 0) {
264 FEEDBACK_ERROR("vconf_get_int(VCONFKEY_CALL_STATE, &callstatus) ==> FAIL!!");
265 return FEEDBACK_ERROR_OPERATION_FAILED;
269 v_doc = xml_open(VIBRATION_XML);
271 FEEDBACK_ERROR("xml_open(%s) fail", VIBRATION_XML);
272 return FEEDBACK_ERROR_OPERATION_FAILED;
276 ret = haptic_open(HAPTIC_DEVICE_ALL, &v_handle);
277 if (ret != HAPTIC_ERROR_NONE) {
278 FEEDBACK_ERROR("haptic_open(HAPTIC_DEVICE_ALL, &v_handle) ==> FAIL!! : %d", ret);
279 v_handle = (haptic_device_h)DEFAULT_FEEDBACK_HANDLE;
282 /* add watch for status value */
283 vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, feedback_vibstatus_cb, NULL);
284 vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb, NULL);
285 vconf_notify_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb, NULL);
286 vconf_notify_key_changed(VCONFKEY_CALL_STATE, feedback_callstatus_cb, NULL);
288 FEEDBACK_LOG("vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) ==> %d", vibstatus);
289 FEEDBACK_LOG("vconf_get_int(VCONFKEY_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) ==> %d", vib_level);
290 FEEDBACK_LOG("vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) ==> %d", noti_level);
291 FEEDBACK_LOG("vconf_get_int(VCONFKEY_CALL_STATUS, &callstatus) ==> %d", callstatus);
293 phandle = (FEEDBACK_HANDLE *)malloc(sizeof(FEEDBACK_HANDLE));
294 phandle->v_handle = v_handle;
295 phandle->v_doc = v_doc;
296 *handle = (feedback_h)phandle;
297 FEEDBACK_LOG("handle value : %x", handle);
298 return FEEDBACK_ERROR_NONE;
301 int feedback_fini(feedback_h handle)
303 FEEDBACK_HANDLE *phandle = (FEEDBACK_HANDLE *)handle;
307 FEEDBACK_ERROR("Invalid parameter : handle(NULL)");
308 return FEEDBACK_ERROR_INVALID_PARAMETER;
311 if (phandle->v_handle != DEFAULT_FEEDBACK_HANDLE) {
312 ret = haptic_close(phandle->v_handle);
313 if (ret != HAPTIC_ERROR_NONE) {
314 FEEDBACK_ERROR("haptic_close is failed : %d", ret);
318 if (phandle->v_doc) {
319 xml_close(phandle->v_doc);
324 vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, feedback_vibstatus_cb);
325 vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb);
326 vconf_ignore_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb);
327 vconf_ignore_key_changed(VCONFKEY_CALL_STATE, feedback_callstatus_cb);
329 return FEEDBACK_ERROR_NONE;
332 int feedback_play_vibration(feedback_h handle, feedback_pattern_e pattern)
334 FEEDBACK_HANDLE *phandle = (FEEDBACK_HANDLE *)handle;
337 struct xmlData *data;
340 FEEDBACK_ERROR("Invalid parameter : handle(NULL)");
341 return FEEDBACK_ERROR_INVALID_PARAMETER;
344 if (handle == DEFAULT_FEEDBACK_HANDLE) {
345 FEEDBACK_ERROR("haptic is not initialized");
346 return FEEDBACK_ERROR_OPERATION_FAILED;
349 if (vibstatus == 0 && !feedback_get_always_alert_case(pattern)) {
350 FEEDBACK_LOG("Vibration condition is OFF (vibstatus : %d)", vibstatus);
351 return FEEDBACK_ERROR_NONE;
354 if (callstatus != VCONFKEY_CALL_OFF) {
355 pattern = feedback_get_alert_on_call_key(pattern);
356 FEEDBACK_LOG("Call status is connected or connecting. pattern changed : %s", str_pattern[pattern]);
359 ret = feedback_get_data(phandle->v_doc, pattern, &data);
361 FEEDBACK_ERROR("feedback_get_vibration_data fail");
362 return FEEDBACK_ERROR_OPERATION_FAILED;
365 if (data->data == NULL) {
366 FEEDBACK_LOG("This case(%s) does not play vibration", str_pattern[pattern]);
367 feedback_release_data(data);
368 return FEEDBACK_ERROR_NONE;
371 /* play haptic buffer */
372 ret = haptic_vibrate_buffer_with_detail(phandle->v_handle, data->data, HAPTIC_ITERATION_ONCE,
373 feedback_get_haptic_level(pattern), feedback_get_priority(pattern), NULL);
374 if (ret != HAPTIC_ERROR_NONE) {
375 FEEDBACK_ERROR("haptic_vibrate_buffer_with_detail is failed");
376 feedback_release_data(data);
377 return FEEDBACK_ERROR_OPERATION_FAILED;
380 feedback_release_data(data);
381 return FEEDBACK_ERROR_NONE;
384 int feedback_set_path(feedback_type_e type, feedback_pattern_e pattern, char* path)
386 const char* cur_path = NULL;
389 if (type <= FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END) {
390 FEEDBACK_ERROR("Invalid parameter : type(%s)", str_type[type]);
391 return FEEDBACK_ERROR_INVALID_PARAMETER;
394 if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= FEEDBACK_PATTERN_END) {
395 FEEDBACK_ERROR("Invalid parameter : pattern(%s)", str_pattern[pattern]);
396 return FEEDBACK_ERROR_INVALID_PARAMETER;
400 FEEDBACK_ERROR("Invalid parameter : path(NULL)");
401 return FEEDBACK_ERROR_INVALID_PARAMETER;
404 if (access(path, F_OK) != 0) {
405 FEEDBACK_ERROR("Invalid parameter : path does not exist");
406 return FEEDBACK_ERROR_INVALID_PARAMETER;
409 if (type == FEEDBACK_TYPE_VIBRATION) {
410 cur_path = haptic_file[pattern];
413 if (cur_path == NULL) {
414 FEEDBACK_ERROR("This pattern(%s) in this type(%s) is not supported to play", str_pattern[pattern], str_type[type]);
415 return FEEDBACK_ERROR_OPERATION_FAILED;
418 ret = feedback_change_symlink(cur_path, path);
419 if (FEEDBACK_FAILED(ret)) {
420 FEEDBACK_ERROR("change_symlink is failed");
421 return FEEDBACK_ERROR_OPERATION_FAILED;
424 return FEEDBACK_ERROR_NONE;
427 int feedback_get_path(feedback_type_e type, feedback_pattern_e pattern, char* buf, unsigned int buflen)
429 const char* cur_path = NULL;
430 int retry = FEEDBACK_RETRY_CNT;
432 if (type <= FEEDBACK_TYPE_NONE || type >= FEEDBACK_TYPE_END) {
433 FEEDBACK_ERROR("Invalid parameter : type(%s)", str_type[type]);
434 return FEEDBACK_ERROR_INVALID_PARAMETER;
437 if (pattern <= FEEDBACK_PATTERN_NONE || pattern >= FEEDBACK_PATTERN_END) {
438 FEEDBACK_ERROR("Invalid parameter : pattern(%s)", str_pattern[pattern]);
439 return FEEDBACK_ERROR_INVALID_PARAMETER;
442 if (buf == NULL || buflen <= 0) {
443 FEEDBACK_ERROR("Invalid parameter : buf(NULL) or bufLen(%d)", buflen);
444 return FEEDBACK_ERROR_INVALID_PARAMETER;
447 if (type == FEEDBACK_TYPE_VIBRATION) {
448 cur_path = haptic_file[pattern];
451 if (cur_path == NULL) {
452 FEEDBACK_ERROR("This pattern(%s) in this type(%s) is not supported to play", str_pattern[pattern], str_type[type]);
453 snprintf(buf, buflen, "NULL");
454 return FEEDBACK_ERROR_OPERATION_FAILED;
458 if(readlink(cur_path, buf, buflen) < 0) {
459 FEEDBACK_ERROR("readlink is failed : %s", strerror(errno));
460 return FEEDBACK_ERROR_OPERATION_FAILED;
464 return FEEDBACK_ERROR_NONE;