#include <stdio.h>
+#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include "feedback-ids.h"
-#include "common.h"
-#include "log.h"
+#include "profiles.h"
+#include "parser.h"
#include "devices.h"
-#include "xmlparser.h"
+#include "log.h"
#include "dbus.h"
-
-#define DEFAULT_VIB_LEVEL 3
-#define HAPTIC_FEEDBACK_STEP 20 /**< feedback max / slider step */
+#ifdef MOBILE
+#include "feedback-ids-mobile.h"
+#endif
+#ifdef WEARABLE
+#include "feedback-ids-wearable.h"
+#endif
#define HAPTIC_DEVICE 0
-enum haptic_priority
-{
+enum haptic_priority {
HAPTIC_PRIORITY_MIN = 0,
HAPTIC_PRIORITY_MIDDLE,
HAPTIC_PRIORITY_HIGH,
};
-enum haptic_iteration
-{
+enum haptic_iteration {
HAPTIC_ITERATION_ONCE = 1,
HAPTIC_ITERATION_INFINITE = 256,
};
-#define VIBRATION_XML "/usr/share/feedback/vibration.xml"
+#define VIBRATION_CONF_FILE "/usr/share/feedback/vibration.conf"
-#define METHOD_OPEN "OpenDevice"
-#define METHOD_CLOSE "CloseDevice"
-#define METHOD_VIBRATE_BUFFER "VibrateBuffer"
-#define METHOD_STOP "StopDevice"
+#define METHOD_OPEN "OpenDevice"
+#define METHOD_CLOSE "CloseDevice"
+#define METHOD_VIBRATE_MONOTONE "VibrateMonotone"
+#define METHOD_VIBRATE_BUFFER "VibrateBuffer"
+#define METHOD_STOP "StopDevice"
-static int vibstatus;
-static int noti_vibstatus;
-static int vib_level;
-static int noti_level;
-static int feedbackstatus;
+#define DEFAULT_DURATION 100
+#define SIP_DURATION 60
+static int vibstatus;
static unsigned int v_handle;
-static xmlDocPtr v_doc;
+static struct feedback_config_info vib_info = {
+ .name = "Vibration",
+};
+
+static char *get_data(feedback_pattern_e pattern)
+{
+ char *data;
+
+ if (pattern <= FEEDBACK_PATTERN_NONE ||
+ pattern >= profile->max_pattern)
+ return NULL;
+
+ if (vib_info.data[pattern].changed)
+ data = vib_info.data[pattern].changed;
+ else
+ data = vib_info.data[pattern].origin;
+
+ return data;
+}
-static char haptic_file[FEEDBACK_PATTERN_END][NAME_MAX];
+inline int is_vibration_mode(void)
+{
+ return vibstatus;
+}
static int haptic_open(void)
{
arr[0] = buf_handle;
bytes.size = size;
bytes.data = buffer;
- arr[2] = (char*)&bytes;
+ arr[2] = (char *)&bytes;
snprintf(buf_iteration, sizeof(buf_iteration), "%d", iteration);
arr[3] = buf_iteration;
snprintf(buf_feedback, sizeof(buf_feedback), "%d", feedback);
"uayiii", arr);
}
+static int haptic_vibrate_monotone(unsigned int handle,
+ int duration,
+ int feedback,
+ int priority)
+{
+ char *arr[4];
+ char buf_handle[32];
+ char buf_duration[32];
+ char buf_feedback[32];
+ char buf_priority[32];
+
+ snprintf(buf_handle, sizeof(buf_handle), "%u", handle);
+ arr[0] = buf_handle;
+ snprintf(buf_duration, sizeof(buf_duration), "%d", duration);
+ arr[1] = buf_duration;
+ snprintf(buf_feedback, sizeof(buf_feedback), "%d", feedback);
+ arr[2] = buf_feedback;
+ snprintf(buf_priority, sizeof(buf_priority), "%d", priority);
+ arr[3] = buf_priority;
+
+ return dbus_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_HAPTIC,
+ DEVICED_INTERFACE_HAPTIC, METHOD_VIBRATE_MONOTONE,
+ "uiii", arr);
+}
+
static int haptic_vibrate_stop(unsigned int handle)
{
char *arr[1];
"u", arr);
}
-static unsigned char* convert_file_to_buffer(const char *file_name, int *size)
+static unsigned char *convert_file_to_buffer(const char *file_name, int *size)
{
FILE *pf;
long file_size;
/* Get File Stream Pointer */
pf = fopen(file_name, "rb");
if (!pf) {
- _E("fopen failed : %d", errno);
+ _E("fopen failed : %s", strerror(errno));
return NULL;
}
if (file_size < 0)
goto error;
- pdata = (unsigned char*)malloc(file_size);
+ pdata = (unsigned char *)malloc(file_size);
if (!pdata)
goto error;
error:
fclose(pf);
- _E("failed to convert file to buffer (%d)", errno);
+ _E("failed to convert file to buffer (%s)", strerror(errno));
return NULL;
}
-static void feedback_noti_vibstatus_cb(keynode_t *key, void* data)
-{
- noti_vibstatus = vconf_keynode_get_bool(key);
-}
-
-static void feedback_vib_cb(keynode_t *key, void* data)
-{
- vib_level = vconf_keynode_get_int(key);
-}
-
-static void feedback_noti_cb(keynode_t *key, void* data)
-{
- noti_level = vconf_keynode_get_int(key);
-}
-
-static void feedback_feedbackstatus_cb(keynode_t *key, void* data)
-{
- feedbackstatus = vconf_keynode_get_bool(key);
-}
-
static int get_priority(feedback_pattern_e pattern)
{
if (pattern >= FEEDBACK_PATTERN_TAP && pattern <= FEEDBACK_PATTERN_HW_HOLD)
return HAPTIC_PRIORITY_MIDDLE;
}
-static int get_haptic_level(feedback_pattern_e pattern)
+static int get_duration(feedback_pattern_e pattern)
{
- int level;
-
- if (pattern >= FEEDBACK_PATTERN_MESSAGE && pattern <= FEEDBACK_PATTERN_SMART_ALERT)
- level = noti_level * HAPTIC_FEEDBACK_STEP;
- else
- level = vib_level * HAPTIC_FEEDBACK_STEP;
-
- _D("Call status : %d, pattern : %s, level : %d", callstatus, str_pattern[pattern], level);
- if (callstatus == VCONFKEY_CALL_VOICE_ACTIVE
- || callstatus == VCONFKEY_CALL_VIDEO_ACTIVE) {
- // if call status is ON, vibration magnitude is 20%
- level = 20;
- _D("level changed : %d", level);
- }
-
- return level;
-}
-
-static bool get_always_alert_case(feedback_pattern_e pattern)
-{
- switch (pattern) {
- case FEEDBACK_PATTERN_KEY0 ... FEEDBACK_PATTERN_KEY_BACK:
- case FEEDBACK_PATTERN_HOLD:
- if (feedbackstatus)
- return true;
- break;
- case FEEDBACK_PATTERN_SIP:
- case FEEDBACK_PATTERN_SIP_BACKSPACE:
- case FEEDBACK_PATTERN_SIP_FUNCTION:
- case FEEDBACK_PATTERN_SIP_FJKEY:
- return true;
- case FEEDBACK_PATTERN_TIMER:
- case FEEDBACK_PATTERN_TIMER_ON_CALL:
- case FEEDBACK_PATTERN_WAKEUP:
- case FEEDBACK_PATTERN_WAKEUP_ON_CALL:
- return true;
- case FEEDBACK_PATTERN_MESSAGE_ON_CALL:
- case FEEDBACK_PATTERN_EMAIL_ON_CALL:
- case FEEDBACK_PATTERN_GENERAL_ON_CALL:
- if (alert_callstatus)
- return true;
- break;
- case FEEDBACK_PATTERN_MESSAGE:
- case FEEDBACK_PATTERN_EMAIL:
- if (noti_vibstatus)
- return true;
- break;
- case FEEDBACK_PATTERN_3RD_APPLICATION:
- case FEEDBACK_PATTERN_SMART_ALERT:
- case FEEDBACK_PATTERN_SEND_SOS_MESSAGE:
- case FEEDBACK_PATTERN_END_SOS_MESSAGE:
- case FEEDBACK_PATTERN_CMAS:
- case FEEDBACK_PATTERN_OUTGOING_CALL:
- case FEEDBACK_PATTERN_MMS:
- case FEEDBACK_PATTERN_HOURLY_ALERT:
- return true;
- case FEEDBACK_PATTERN_SPEED_UP:
- case FEEDBACK_PATTERN_SLOW_DOWN:
- case FEEDBACK_PATTERN_KEEP_THIS_PACE:
- case FEEDBACK_PATTERN_GOAL_ACHIEVED:
- case FEEDBACK_PATTERN_EXERCISE_COUNT:
- case FEEDBACK_PATTERN_START_CUE:
- /* except mute case */
- if (is_sound_mode() || vibstatus)
- return true;
- break;
- case FEEDBACK_PATTERN_CHARGERCONN_ON_CALL:
- case FEEDBACK_PATTERN_CHARGING_ERROR_ON_CALL:
- case FEEDBACK_PATTERN_LOWBATT_ON_CALL:
- /* no matter sound profile */
- return true;
- default:
- break;
- }
- return false;
-}
-
-static bool get_always_off_case(feedback_pattern_e pattern)
-{
- switch (pattern) {
- case FEEDBACK_PATTERN_KEY0 ... FEEDBACK_PATTERN_KEY_BACK:
- case FEEDBACK_PATTERN_HOLD:
- if (!feedbackstatus)
- return true;
- break;
- default:
- break;
- }
- return false;
-}
-
-static int get_xml_data(xmlDocPtr doc, feedback_pattern_e pattern, struct xmlData **data)
-{
- xmlNodePtr cur;
- struct xmlData *retData;
-
- cur = xml_find(doc, VIBRATION_STR, (const xmlChar*)str_pattern[pattern]);
- /* This pattern does not have sound file to play */
- if (cur == NULL)
- return -ENOENT;
-
- retData = xml_parse(doc, cur);
- if (retData == NULL) {
- _E("xml_parse fail");
- return -EPERM;
- }
-
- *data = retData;
- return 0;
-}
-
-static void release_xml_data(struct xmlData *data)
-{
- if (data == NULL)
- return;
-
- xml_free(data);
+ if (pattern == FEEDBACK_PATTERN_SIP)
+ return SIP_DURATION;
+#ifdef MOBILE
+ if (pattern == (feedback_pattern_e)FEEDBACK_PATTERN_MOBILE_SIP_BACKSPACE)
+ return SIP_DURATION;
+#endif
+#ifdef WEARABLE
+ if (pattern == (feedback_pattern_e)FEEDBACK_PATTERN_WEARABLE_SIP_BACKSPACE)
+ return SIP_DURATION;
+#endif
+ return DEFAULT_DURATION;
}
static void vibrator_init(void)
{
int ret;
- /* xml Init */
- v_doc = xml_open(VIBRATION_XML);
- if (v_doc == NULL) {
- _E("xml_open(%s) fail", VIBRATION_XML);
- return;
- }
-
/* Vibration Init */
ret = haptic_open();
if (ret < 0) {
_E("haptic_open ==> FAIL!! : %d", ret);
- xml_close(v_doc);
- v_doc = NULL;
+ v_handle = -ENOTSUP;
return;
}
/* Set vibration handle */
v_handle = (unsigned int)ret;
- /* check vibration status */
- if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, ¬i_vibstatus) < 0)
- _W("VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL ==> FAIL!!");
-
- /* check vib_level */
- if (vconf_get_int(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, &vib_level) < 0)
- _W("VCONFKEY_FEEDBACK_VIBRATION_LEVEL_INT ==> FAIL!!");
-
- /* check noti_level */
- if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, ¬i_level) < 0)
- _W("VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT ==> FAIL!!");
-
- /* feedback Init */
- if(vconf_get_bool(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, &feedbackstatus) < 0)
- _W("VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL ==> FAIL!!");
-
- /* add watch for status value */
- vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, feedback_noti_vibstatus_cb, NULL);
- vconf_notify_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb, NULL);
- vconf_notify_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb, NULL);
- vconf_notify_key_changed(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, feedback_feedbackstatus_cb, NULL);
+ /* get vibration data */
+ feedback_load_config(VIBRATION_CONF_FILE, &vib_info);
}
static void vibrator_exit(void)
{
int ret;
- /* remove watch */
- vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATE_WHEN_NOTIFICATION_BOOL, feedback_noti_vibstatus_cb);
- vconf_ignore_key_changed(VCONFKEY_SETAPPL_TOUCH_FEEDBACK_VIBRATION_LEVEL_INT, feedback_vib_cb);
- vconf_ignore_key_changed(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, feedback_noti_cb);
- vconf_ignore_key_changed(VCONFKEY_SETAPPL_HAPTIC_FEEDBACK_STATUS_BOOL, feedback_feedbackstatus_cb);
-
- if (v_handle) {
+ if (v_handle > 0) {
ret = haptic_close(v_handle);
if (ret < 0)
_E("haptic_close is failed : %d", ret);
v_handle = 0;
}
- if (v_doc) {
- xml_close(v_doc);
- v_doc = NULL;
- }
+ /* free vibration data */
+ feedback_free_config(&vib_info);
}
static int vibrator_play(feedback_pattern_e pattern)
{
- int ret, size;
- struct xmlData *data;
- char *path;
- unsigned char *buf;
+ struct stat buf;
+ char *data;
+ unsigned char *pbuf;
+ int size;
+ int ret;
+ int level;
+ int duration;
- if (!v_handle || !v_doc) {
+ if (!v_handle) {
_E("Not initialize");
return -EPERM;
}
+ if (v_handle == -ENOTSUP) {
+ _E("Not supported vibration");
+ return -ENOTSUP;
+ }
+
if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) < 0) {
_D("fail to get vibration status, will work as turning off");
vibstatus = 0;
}
- if (vibstatus == 0 && !get_always_alert_case(pattern)) {
+ if (vibstatus == 0 && profile->get_always_alert_case &&
+ !profile->get_always_alert_case(FEEDBACK_TYPE_VIBRATION, pattern)) {
_D("Vibration condition is OFF (vibstatus : %d)", vibstatus);
return 0;
}
- if (vibstatus && get_always_off_case(pattern)) {
+ if (vibstatus && profile->get_always_off_case &&
+ profile->get_always_off_case(FEEDBACK_TYPE_VIBRATION, pattern)) {
_D("Vibration always off condition");
return 0;
}
- /* if there is a file path user defined */
- path = haptic_file[pattern];
- if (*path) {
- buf = convert_file_to_buffer(path, &size);
- if (!buf) {
- _E("convert_file_to_buffer is failed");
- return -EPERM;
- }
-
- ret = haptic_vibrate_buffer(v_handle, buf, size, HAPTIC_ITERATION_ONCE,
- get_haptic_level(pattern), get_priority(pattern));
- if (ret < 0) {
- _E("haptic_vibrate_buffer is failed");
- free(buf);
- return -EPERM;
- }
-
- free(buf);
- return 0;
- }
+ if (profile->get_strength_type)
+ level = profile->get_strength_type(FEEDBACK_TYPE_VIBRATION, pattern);
+ else
+ level = DEFAULT_VIB_LEVEL * HAPTIC_FEEDBACK_STEP;
- ret = get_xml_data(v_doc, pattern, &data);
- if (ret == -ENOENT) {
- _D("No vibration case(%s)", str_pattern[pattern]);
- return 0;
+ /* get vibration data */
+ data = get_data(pattern);
+ if (!data) {
+ _E("Not supported vibration pattern");
+ return -ENOTSUP;
}
- if (ret < 0) {
- _E("get_xml_data fail");
- return -EPERM;
- }
+ /* if it has a file path */
+ if (!stat(data, &buf)) {
+ pbuf = convert_file_to_buffer(data, &size);
+ if (!pbuf) {
+ _E("fail to convert file to buffer");
+ return -EPERM;
+ }
- if (data->data == NULL) {
- _D("No vibration case(%s)", str_pattern[pattern]);
- release_xml_data(data);
- return 0;
+ ret = haptic_vibrate_buffer(v_handle, pbuf, size,
+ HAPTIC_ITERATION_ONCE,
+ level, get_priority(pattern));
+ free(pbuf);
+ } else {
+ duration = get_duration(pattern);
+ ret = haptic_vibrate_monotone(v_handle, duration,
+ level, get_priority(pattern));
}
- /* play haptic buffer */
- ret = haptic_vibrate_buffer(v_handle, (unsigned char*)data->data, data->size, HAPTIC_ITERATION_ONCE,
- get_haptic_level(pattern), get_priority(pattern));
if (ret < 0) {
- _E("haptic_vibrate_buffer is failed");
- release_xml_data(data);
+ _E("fail to play vibration");
+ if (ret == -ECOMM)
+ return ret;
return -EPERM;
}
- release_xml_data(data);
+ _D("Play success! Data is %s", data);
return 0;
}
{
int ret;
- if (!v_handle || !v_doc) {
+ if (!v_handle) {
_E("Not initialize");
return -EPERM;
}
+ if (v_handle == -ENOTSUP) {
+ _E("Not supported vibration");
+ return -ENOTSUP;
+ }
+
/* stop haptic device */
ret = haptic_vibrate_stop(v_handle);
if (ret < 0) {
_E("haptic_vibrate_stop is failed");
+ if (ret == -ECOMM)
+ return ret;
return -EPERM;
}
return 0;
}
-static int vibrator_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
+static int vibrator_is_supported(int pattern, bool *supported)
{
- const char *cur_path;
+ char *data;
+ bool ret = true;
- assert(buf != NULL && buflen > 0);
+ if (!supported) {
+ _E("Invalid parameter : supported(NULL)");
+ return -EINVAL;
+ }
- cur_path = haptic_file[pattern];
- if (*cur_path) {
- _E("This pattern(%s) in vibrator type is not supported to play", str_pattern[pattern]);
- snprintf(buf, buflen, "NULL");
- return -ENOENT;
+ if (!v_handle) {
+ _E("Not initialize");
+ return -EPERM;
}
- snprintf(buf, buflen, "%s", cur_path);
+ if (v_handle == -ENOTSUP) {
+ _E("Not supported vibration");
+ *supported = false;
+ return 0;
+ }
+
+ /* get vibration data */
+ data = get_data(pattern);
+ if (!data) {
+ _E("Not supported vibration pattern");
+ ret = false;
+ }
+
+ *supported = ret;
return 0;
}
+static int vibrator_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
+{
+ char *data;
+ int ret = 0;
+
+ if (!buf || buflen <= 0)
+ return -EINVAL;
+
+ /* get vibration data */
+ data = get_data(pattern);
+ if (!data) {
+ _E("This pattern(%s) in vibrator type is not supported to play",
+ profile->str_pattern[pattern]);
+ data = "NULL";
+ ret = -ENOENT;
+ }
+
+ snprintf(buf, buflen, "%s", data);
+ return ret;
+}
+
static int vibrator_set_path(feedback_pattern_e pattern, char *path)
{
struct stat buf;
- char *ppath;
/*
* check the path is valid
- * if path is null, below operation is ignored
+ * if path is null, reset vibration path
*/
+ if (!path) {
+ if (vib_info.data[pattern].changed) {
+ free(vib_info.data[pattern].changed);
+ vib_info.data[pattern].changed = NULL;
+ }
+ return 0;
+ }
+
if (path && stat(path, &buf)) {
_E("%s is not presents", path);
return -errno;
}
- ppath = haptic_file[pattern];
+ if (vib_info.data[pattern].changed) {
+ free(vib_info.data[pattern].changed);
+ vib_info.data[pattern].changed = NULL;
+ }
/* if path is NULL, this pattern set to default file */
if (path)
- snprintf(ppath, NAME_MAX, "%s", path);
- else
- memset(ppath, 0, NAME_MAX);
+ vib_info.data[pattern].changed = strdup(path);
- _D("The file of pattern(%s) is changed to [%s]", str_pattern[pattern], path);
+ _D("The file of pattern(%s) is changed to [%s]",
+ profile->str_pattern[pattern], path);
return 0;
}
static const struct device_ops vibrator_device_ops = {
.type = FEEDBACK_TYPE_VIBRATION,
+ .name = "Vibrator",
.init = vibrator_init,
.exit = vibrator_exit,
.play = vibrator_play,
.stop = vibrator_stop,
+ .is_supported = vibrator_is_supported,
.get_path = vibrator_get_path,
.set_path = vibrator_set_path,
};