Remove standard-vibcore.c 26/200026/6
authorpr.jung <pr.jung@samsung.com>
Mon, 18 Feb 2019 06:59:24 +0000 (15:59 +0900)
committerpr.jung <pr.jung@samsung.com>
Mon, 25 Feb 2019 06:10:11 +0000 (15:10 +0900)
Change-Id: I6a8eb297a6b3cb10637b763c5615c75d9bbc82ad
Signed-off-by: pr.jung <pr.jung@samsung.com>
CMakeLists.txt
src/haptic/circle.c
src/haptic/emulator.c
src/haptic/gpio_haptic.c
src/haptic/haptic-plugin-intf.h
src/haptic/haptic.c
src/haptic/standard-vibcore.c [deleted file]
src/haptic/standard-vibcore.h [deleted file]
src/haptic/standard.c

index 8950c06..45ecc01 100644 (file)
@@ -21,11 +21,11 @@ IF(DRIVER STREQUAL external)
 ELSEIF(DRIVER STREQUAL emulator)
        SET(SRCS ${SRCS} src/haptic/emulator.c)
 ELSEIF(DRIVER STREQUAL gpio)
-       SET(SRCS ${SRCS} src/haptic/gpio_haptic.c src/haptic/standard-vibcore.c)
+       SET(SRCS ${SRCS} src/haptic/gpio_haptic.c)
 ELSEIF(DRIVER STREQUAL standard)
-       SET(SRCS ${SRCS} src/haptic/standard.c src/haptic/standard-vibcore.c)
+       SET(SRCS ${SRCS} src/haptic/standard.c)
 ELSEIF(DRIVER STREQUAL circle)
-       SET(SRCS ${SRCS} src/haptic/circle.c src/haptic/standard-vibcore.c)
+       SET(SRCS ${SRCS} src/haptic/circle.c)
 ENDIF()
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src)
index 7fd46f1..a4af20f 100644 (file)
@@ -29,7 +29,6 @@
 #include "core/log.h"
 #include "core/list.h"
 #include "haptic.h"
-#include "standard-vibcore.h"
 
 #define CIRCLE_ON_PATH             "/sys/class/sec/motor/motor_on"
 #define CIRCLE_OFF_PATH            "/sys/class/sec/motor/motor_off"
@@ -250,9 +249,6 @@ static int stop_device(int device_handle)
                return -EPERM;
        }
 
-       /* Remove duration_timer for vibrate_effect */
-       standard_vibrate_close();
-
        if (fd_stop < 0) {
                fd_stop = open(CIRCLE_OFF_PATH, O_RDONLY);
                if (fd_stop < 0) {
@@ -278,9 +274,7 @@ static const struct haptic_plugin_ops default_plugin = {
        .get_device_count    = get_device_count,
        .open_device         = open_device,
        .close_device        = close_device,
-       .vibrate_monotone    = standard_vibrate_monotone,
-       .vibrate_effect      = standard_vibrate_effect,
-       .is_supported        = standard_is_supported,
+       .vibrate_monotone    = vibrate_monotone,
        .stop_device         = stop_device,
 };
 
@@ -293,8 +287,6 @@ static bool is_valid(void)
                return false;
        }
 
-       standard_config_parse();
-
        state = true;
        _I("Support wearable haptic device");
        return true;
@@ -302,7 +294,6 @@ static bool is_valid(void)
 
 static const struct haptic_plugin_ops *load(void)
 {
-       standard_set_vib_function(&vibrate_monotone);
        return &default_plugin;
 }
 
index 6807391..fe40435 100644 (file)
@@ -78,17 +78,6 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p
        return 0;
 }
 
-static int vibrate_effect(int device_handle, const char *pattern, int feedback, int priority)
-{
-       dd_list *elem;
-
-       elem = DD_LIST_FIND(handle_list, (gpointer)(long)device_handle);
-       if (!elem)
-               return -EINVAL;
-
-       return 0;
-}
-
 static int stop_device(int device_handle)
 {
        dd_list *elem;
@@ -99,11 +88,6 @@ static int stop_device(int device_handle)
 
        return 0;
 }
-
-static int is_supported(const char *pattern)
-{
-       return 0;
-}
 /* END: Haptic Module APIs */
 
 static const struct haptic_plugin_ops default_plugin = {
@@ -111,8 +95,6 @@ static const struct haptic_plugin_ops default_plugin = {
        .open_device         = open_device,
        .close_device        = close_device,
        .vibrate_monotone    = vibrate_monotone,
-       .vibrate_effect      = vibrate_effect,
-       .is_supported        = is_supported,
        .stop_device         = stop_device,
 };
 
index 2334598..a188b10 100644 (file)
@@ -22,7 +22,6 @@
 #include "core/log.h"
 #include "haptic.h"
 #include "peripheral_io.h"
-#include "standard-vibcore.h"
 
 #define GPIO_I2C_BUS_INDEX             1
 #define MAX_HAPIC                              1
@@ -259,9 +258,6 @@ static int gpio_haptic_stop_device(int handle)
                return -EPERM;
        }
 
-       /* Remove duration_timer for vibrate_effect */
-       standard_vibrate_close();
-
        if (device_handle == NULL) {
                if (peripheral_i2c_open(GPIO_I2C_BUS_INDEX, DRV2605L_DEFAULT_ADDR, &device_handle) < PERIPHERAL_ERROR_NONE) {
                        _E("Failed to open I2C");
@@ -286,9 +282,7 @@ static const struct haptic_plugin_ops default_plugin = {
        .get_device_count               = gpio_haptic_get_device_count,
        .open_device                    = gpio_haptic_open_device,
        .close_device                   = gpio_haptic_close_device,
-       .vibrate_monotone               = standard_vibrate_monotone,
-       .vibrate_effect                 = standard_vibrate_effect,
-       .is_supported                   = standard_is_supported,
+       .vibrate_monotone               = gpio_haptic_vibrate_monotone,
        .stop_device                    = gpio_haptic_stop_device,
 };
 
@@ -315,8 +309,6 @@ static bool is_valid(void)
                return false;
        }
 
-       standard_config_parse();
-
        state = true;
        _I("Support gpio haptic device");
        return true;
@@ -325,7 +317,6 @@ static bool is_valid(void)
 static const struct haptic_plugin_ops *load(void)
 {
        _I("gpio haptic device module loaded");
-       standard_set_vib_function(&gpio_haptic_vibrate_monotone);
        return &default_plugin;
 }
 
index 9d11f62..4c039a7 100644 (file)
@@ -27,8 +27,6 @@ struct haptic_plugin_ops {
        int (*open_device) (int, int*);
        int (*close_device) (int);
        int (*vibrate_monotone) (int, int, int, int);
-       int (*vibrate_effect) (int, const char*, int, int);
-       int (*is_supported) (const char*);
        int (*stop_device) (int);
 };
 
index f1cdc8a..d253225 100644 (file)
 #include "core/config-parser.h"
 #include "haptic.h"
 
+#define FEEDBACK_BASE_PATH         "/usr/share/feedback/"
+#define STANDARD_FILE_PATH         FEEDBACK_BASE_PATH"vibration/"
+#define VIBRATION_CONF_PATH        FEEDBACK_BASE_PATH"vibration.conf"
+
 #define HAPTIC_CONF_PATH                "/etc/feedbackd/haptic.conf"
 #define SIGNAL_CHANGE_HARDKEY           "ChangeHardkey"
 #define SIGNAL_POWEROFF_STATE           "ChangeState"
 #define CHECK_VALID_OPS(ops, r)                ((ops) ? true : !(r = -ENODEV))
 #define RETRY_CNT      3
 
+#define INTENSITY_BASE_RATE        (10000)
+#define VALUE_MAX_LEN              10
+#define VIB_LOCK_TIMEOUT_MAX       (300000) /* 5minutes */
+
+/*
+               1,A_W or A,A_W or 250D250W250D750W
+
+               85,10000,
+               90,0,
+               105,10000,
+               0,end
+*/
+struct vibration_config {
+       char *pattern; /* pattern name */
+       char *standard; /* assigned standard pattern name */
+       dd_list *data; /* duration_data list */
+       unsigned int pattern_duration;
+       int unlimit;
+};
+
+struct duration_data {
+       int duration;
+       int intensity;
+       int wait;
+};
+
 enum poweroff_type {
        POWER_OFF_NONE = 0,
        POWER_OFF_POPUP,
@@ -92,6 +122,11 @@ struct vibrate_monotone_info {
 /* for playing */
 static int g_handle;
 
+/* pattern configuration list */
+static dd_list *vib_conf_list;
+
+guint duration_timer;
+
 /* haptic operation variable */
 static dd_list *h_head;
 static dd_list *haptic_handle_list;
@@ -124,12 +159,353 @@ void remove_haptic(const struct haptic_ops *ops)
        DD_LIST_REMOVE(h_head, (void *)ops);
 }
 
+static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
+{
+       struct duration_data *data;
+
+       data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
+       if (!data) {
+               _E("not enough memory");
+               return -ENOMEM;
+       }
+       memcpy(data, update, sizeof(struct duration_data));
+       /* insert vibration pattern data */
+       // to debug :
+       // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdriving, data->wait);
+       DD_LIST_APPEND(*conf_data, data);
+       return 0;
+}
+
+static void get_pattern_property(char **iter, char property, int *value)
+{
+       char *check;
+       unsigned long int val;
+
+       check = strchr(*iter, property);
+       if (!check)
+               return;
+
+       *check = '\0';
+       val = strtoul(*iter, NULL, 10);
+       if (errno == EINVAL || errno == ERANGE) {
+               val = 0;
+               _E("Failed to get value of %s: %d", *iter, errno);
+       }
+       if (val > VIB_LOCK_TIMEOUT_MAX)
+               val = VIB_LOCK_TIMEOUT_MAX;
+
+       *value = (int)val;
+
+       *iter = check + 1;
+}
+
+/* [A]xxxDxxxIxxxFxxxOxxxW format */
+static int insert_raw_data_format(dd_list **conf_data, char *value)
+{
+       struct duration_data update = {0, };
+       char *iter;
+       char *end;
+       int pattern_duration = 0;
+
+       if (!value)
+               return insert_conf_data(conf_data, &update);
+       if (!conf_data) {
+               _E("Invalid parameter: Configuration list is null");
+               return -EINVAL;
+       }
+
+       iter = value;
+       end = iter + strlen(iter);
+       while (iter < end) {
+               memset(&update, 0, sizeof(struct duration_data));
+
+               get_pattern_property(&iter, 'D', &update.duration);
+               get_pattern_property(&iter, 'I', &update.intensity);
+               if (update.intensity > INTENSITY_BASE_RATE)
+                       update.intensity = INTENSITY_BASE_RATE;
+               get_pattern_property(&iter, 'W', &update.wait);
+
+               if (update.duration == 0 && update.wait == 0) {
+                       _D("Pattern duration is zero.");
+                       break;
+               }
+
+               pattern_duration += (update.duration + update.wait);
+               if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
+                       _D("Max pattern duration");
+                       pattern_duration = VIB_LOCK_TIMEOUT_MAX;
+               }
+
+               if (insert_conf_data(conf_data, &update) < 0)
+                       return -EINVAL;
+       }
+
+       return pattern_duration;
+}
+
+static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
+{
+       static int duration = 0;
+       int value;
+
+       if (count > 2 || count <= 0) {
+               _E("Invalid parameter: count is invalid");
+               return -EINVAL;
+       }
+
+       if (!packed || !val || !pattern_duration || !update) {
+               _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
+               return -EINVAL;
+       }
+
+       get_pattern_property(&val, 'C', &value);
+
+       if (count == 1) {
+               duration = value;
+               *pattern_duration += duration;
+               if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
+                       _D("Max pattern duration");
+                       *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
+
+               }
+               return count;
+       }
+
+       if (value > INTENSITY_BASE_RATE)
+               value = INTENSITY_BASE_RATE;
+       if (*packed == false) {
+               update->duration = duration;
+               update->intensity = value;
+               *packed = true;
+               return 0;
+       }
+       if (value == 0)
+               update->wait = duration;
+       else
+               update->wait = 0;
+       *packed = false;
+       duration = 0;
+
+       return -1;
+}
+
+/*
+       duration, intensity, frequency, overdriving
+       waiting duration, intensity=0, frequency, overdriving
+       85,10000,
+       90,0,
+       105,10000,
+       0,end
+*/
+static int load_standard_format(const char *pattern)
+{
+       struct duration_data update = {0, };
+       bool packed = false;
+       struct vibration_config *conf;
+       int ret = 0, count = 0, end = 2;
+       int index = 0;
+       int fd;
+       char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
+
+       snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return -ENOENT;
+
+       conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
+       if (!conf) {
+               _E("fail to alloc");
+               ret = -errno;
+               goto error_out;
+       }
+
+       conf->pattern = strdup(pattern);
+       if (!conf->pattern) {
+               _E("fail to copy %s pattern data", pattern);
+               ret = -errno;
+               goto error_out;
+       }
+
+       /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
+       while (read(fd, &elem, 1) != 0) {
+               if (end == 0) {
+                       if (insert_conf_data(&conf->data, &update) < 0)
+                               goto error_out;
+                       break;
+               }
+               if (elem == 'e' || elem == 'n' || elem == 'd') {
+                       end--;
+                       continue;
+               }
+               if (elem == '\n') {
+                       count = 0;
+                       continue;
+               }
+               if (elem == ',') {
+                       count++;
+                       val[index] = 'C';
+                       index = 0;
+
+                       ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
+                       if (ret < 0) {
+                               if (ret == -EINVAL)
+                                       break;
+                               if (insert_conf_data(&conf->data, &update) < 0)
+                                       goto error_out;
+                               memset(&update, 0, sizeof(struct duration_data));
+                       } else
+                               count = ret;
+               } else {
+                       if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
+                               val[index++] = elem;
+                       else
+                               _E("Pattern %s is out of bound: %s", pattern, val);
+               }
+       }
+       close(fd);
+       DD_LIST_APPEND(vib_conf_list, conf);
+       return ret;
+
+error_out:
+       if (fd >= 0)
+               close(fd);
+       if (conf) {
+               if (conf->pattern)
+                       free(conf->pattern);
+               free(conf);
+       }
+       return -ENOENT;
+}
+
+static int vibration_load_config(struct parse_result *result, void *user_data)
+{
+       struct vibration_config *conf;
+       char *value;
+       char *check;
+       int len;
+       int duration;
+
+       if (!result)
+               return 0;
+
+       if (!MATCH(result->section, "Vibration"))
+               return 0;
+
+
+       if (!result->name || !result->value)
+               return 0;
+
+       conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
+       if (!conf) {
+               _E("fail to alloc");
+               return -ENOMEM;
+       }
+
+       conf->pattern_duration = 0;
+       conf->pattern = strdup(result->name);
+       if (!conf->pattern) {
+               _E("fail to copy %s pattern data", result->name);
+               goto error_out;
+       }
+
+       value = result->value;
+       len = strlen(value);
+
+       if (len == 0) {
+               if (insert_raw_data_format(&conf->data, NULL) < 0)
+                       goto error_out;
+               DD_LIST_APPEND(vib_conf_list, conf);
+               return 0;
+       }
+
+       /* Load Standard Pattern Name */
+       /* value: 1,A_W or A,A_W */
+       if ((check = strchr(value, ','))) {
+               *check = '\0';
+               if (strncmp(value, "A", 1) == 0)
+                       conf->unlimit = 1;
+               value = check + 1;
+               conf->standard = strdup(value);
+               if (!conf->standard) {
+                       _E("fail to copy standard name");
+                       goto error_out;
+               }
+               DD_LIST_APPEND(vib_conf_list, conf);
+               return 0;
+       }
+
+       /* value : A100D or 100D0W or 250D250W250D750W */
+       /* Load Vibration Pattern Data */
+       check = strchr(value, 'A');
+       if (check) {
+               *check = '\0';
+               conf->unlimit = 1;
+               if (!value)
+                       len = len - 1;
+               else
+                       len = len - strlen(value) - 1;
+               value = check + 1;
+       }
+       duration = insert_raw_data_format(&conf->data, value);
+       if (duration < 0) {
+               conf->pattern_duration = 0;
+               goto error_out;
+       } else
+               conf->pattern_duration = duration;
+       DD_LIST_APPEND(vib_conf_list, conf);
+
+       return 0;
+
+error_out:
+       if (conf) {
+               if (conf->pattern)
+                       free(conf->pattern);
+               if (conf->standard)
+                       free(conf->standard);
+       }
+       return -ENOMEM;
+}
+
+static void load_standard_vibration_patterns(void)
+{
+       DIR *dir;
+       struct dirent *dent;
+       int ret;
+
+       dir = opendir(STANDARD_FILE_PATH);
+       if (!dir) {
+               _E("Failed to load %s Use default value!", STANDARD_FILE_PATH);
+               return;
+       }
+       while ((dent = readdir(dir))) {
+               if (dent->d_type == DT_DIR)
+                       continue;
+               ret = load_standard_format(dent->d_name);
+               if (ret < 0)
+                       _E("Failed to parse %s: %d", dent->d_name, ret);
+       }
+       closedir(dir);
+       _D("Success to load %s", STANDARD_FILE_PATH);
+}
+
+void pattern_config_parse(void)
+{
+       int ret;
+
+       ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
+       if (ret < 0)
+               _E("Failed to load %s, %d Use default value!", VIBRATION_CONF_PATH, ret);
+
+       load_standard_vibration_patterns();
+}
+
 static int haptic_module_load(void)
 {
        struct haptic_ops *ops;
        dd_list *elem;
        int r;
 
+       pattern_config_parse();
        /* find valid plugin */
        DD_LIST_FOREACH(h_head, elem, ops) {
                if (ops->is_valid && ops->is_valid()) {
@@ -317,6 +693,20 @@ exit:
        return g_variant_new("(i)", ret);
 }
 
+int clear_current_data(void)
+{
+       cur_h_data.handle = INVALID_HANDLE;
+       cur_h_data.priority = PRIORITY_MIN;
+
+       if (duration_timer) {
+               _I("Remove duration_timer");
+               g_source_remove(duration_timer);
+               duration_timer = 0;
+       }
+
+       return 0;
+}
+
 GVariant *hdbus_close_device(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
@@ -341,6 +731,11 @@ GVariant *hdbus_close_device(GDBusConnection *conn,
        if (ret < 0)
                goto exit;
 
+       if (cur_h_data.handle == handle) {
+               /* Remove duration_timer for vibrate_effect */
+               clear_current_data();
+       }
+
        info = get_matched_haptic_info(sender);
        if (!info) {
                _E("fail to find the matched haptic info.");
@@ -359,14 +754,31 @@ exit:
 static void vibrate_monotone_idler_cb(void *data)
 {
        struct vibrate_monotone_info *vibrate_info;
+       int ret;
 
        if (!data)
                return;
 
        vibrate_info = (struct vibrate_monotone_info *)data;
 
-       h_ops->vibrate_monotone(vibrate_info->handle, vibrate_info->duration,
-                       vibrate_info->level, vibrate_info->priority);
+       if (vibrate_info->priority < cur_h_data.priority) {
+               _I("Handle %d skip low priority(pre:%d now:%d)", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
+               free(vibrate_info);
+               return;
+       }
+
+       cur_h_data.vibration_data = NULL;
+       cur_h_data.handle = vibrate_info->handle;
+       cur_h_data.level = vibrate_info->level;
+       cur_h_data.priority = vibrate_info->priority;
+       cur_h_data.stop = false;
+       cur_h_data.unlimit = false;
+
+       ret = device_power_request_lock(POWER_LOCK_CPU, vibrate_info->duration);
+       if (ret != DEVICE_ERROR_NONE)
+               _E("Failed to request power lock");
+       h_ops->vibrate_monotone(cur_h_data.handle, vibrate_info->duration, cur_h_data.level, cur_h_data.priority);
+
        free(vibrate_info);
 }
 
@@ -421,17 +833,134 @@ exit:
        return g_variant_new("(i)", ret);
 }
 
+static gboolean haptic_duration_play(void *data)
+{
+       dd_list *head, *n, *next;
+       struct duration_data *node;
+       int level;
+       int ret = 0;
+
+       if (duration_timer) {
+               g_source_remove(duration_timer);
+               duration_timer = 0;
+       }
+
+       if (!data) {
+               if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
+                       head = cur_h_data.vibration_data;
+               else {
+                       cur_h_data.handle = INVALID_HANDLE;
+                       cur_h_data.priority = PRIORITY_MIN;
+                       goto out;
+               }
+       } else
+               head = (dd_list *)data;
+
+       if (cur_h_data.stop) {
+               _I("Stop currunt vibration");
+               cur_h_data.stop = false;
+               cur_h_data.handle = INVALID_HANDLE;
+               cur_h_data.priority = PRIORITY_MIN;
+               goto out;
+       }
+
+       DD_LIST_FOREACH_SAFE(head, n, next, node) {
+               _D("Handle %d play: %dms and Wait: %dms %s type",
+                       cur_h_data.handle, node->duration, node->wait,
+                       cur_h_data.unlimit ? "Unlimit" : "Once");
+               if ((node->duration + node->wait) <= 0) {
+                       if (!cur_h_data.unlimit) {
+                               cur_h_data.handle = INVALID_HANDLE;
+                               cur_h_data.priority = PRIORITY_MIN;
+                               break;
+                       } else {
+                               next = cur_h_data.vibration_data;
+                               continue;
+                       }
+               }
+
+               if (node->intensity)
+                       level = (cur_h_data.level * node->intensity) / INTENSITY_BASE_RATE;
+               else
+                       level = cur_h_data.level;
+
+               duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
+
+               ret = h_ops->vibrate_monotone(cur_h_data.handle, node->duration, level, cur_h_data.priority);
+
+               break;
+       }
+       if (ret != 0) {
+               _D("auto stop vibration");
+               cur_h_data.stop = true;
+       }
+out:
+       return G_SOURCE_REMOVE;
+}
+
 static void vibrate_effect_idler_cb(void *data)
 {
        struct vibrate_effect_info *vibrate_info;
+       dd_list *elem;
+       struct vibration_config *conf;
+       char pattern[PATH_MAX];
+       int ret;
+       int unlimit = 0;
 
        if (!data)
                return;
 
        vibrate_info = (struct vibrate_effect_info *)data;
 
-       h_ops->vibrate_effect(vibrate_info->handle, vibrate_info->pattern,
-                       vibrate_info->level, vibrate_info->priority);
+       if (!(vibrate_info->pattern)) {
+               free(vibrate_info);
+               return;
+       }
+
+       /* Same or higher priority pattern should be played */
+       if (vibrate_info->priority < cur_h_data.priority) {
+               _I("Handle %d skip low priority(pre:%d now:%d)", vibrate_info->handle, cur_h_data.priority, vibrate_info->priority);
+               goto out;
+       }
+
+       snprintf(pattern, sizeof(pattern), "%s", vibrate_info->pattern);
+       DD_LIST_FOREACH(vib_conf_list, elem, conf) {
+               if (!conf->pattern)
+                       continue;
+               if (strcmp(conf->pattern, pattern))
+                       continue;
+               if (conf->standard) {
+                       unlimit = conf->unlimit;
+                       snprintf(pattern, sizeof(pattern), "%s", conf->standard);
+                       continue;
+               }
+
+               if (unlimit)
+                       cur_h_data.unlimit = unlimit;
+               else
+                       cur_h_data.unlimit = conf->unlimit;
+               cur_h_data.vibration_data = conf->data;
+               cur_h_data.handle = vibrate_info->handle;
+               cur_h_data.level = vibrate_info->level;
+               cur_h_data.priority = vibrate_info->priority;
+               cur_h_data.stop = false;
+               _I("Handle %d play %s pri %d %s", cur_h_data.handle, conf->pattern, cur_h_data.priority,
+                               cur_h_data.unlimit ? "Unlimit" : "Once");
+
+               if (conf->pattern_duration <= 0)
+                       break;
+
+               if (!cur_h_data.unlimit && conf->pattern_duration > 0) {
+                       ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration);
+                       if (ret != DEVICE_ERROR_NONE)
+                               _E("Failed to request power lock");
+               }
+               haptic_duration_play((void *)cur_h_data.vibration_data);
+               goto out;
+       }
+       _E("Handle %d %s is not supported", vibrate_info->handle, pattern);
+
+out:
        free(vibrate_info->pattern);
        free(vibrate_info);
 }
@@ -513,6 +1042,9 @@ GVariant *hdbus_stop_device(GDBusConnection *conn,
 
        ret = h_ops->stop_device(handle);
 
+       /* Remove duration_timer for vibrate_effect */
+       clear_current_data();
+
 exit:
        return g_variant_new("(i)", ret);
 }
@@ -534,6 +1066,28 @@ GVariant *hdbus_show_handle_list(GDBusConnection *conn,
        return g_variant_new_tuple(NULL, 0);
 }
 
+int pattern_is_supported(const char *pattern)
+{
+       dd_list *elem;
+       struct vibration_config *conf;
+       int ret;
+
+       if (!pattern)
+               return -EINVAL;
+
+       ret = 0;
+       DD_LIST_FOREACH(vib_conf_list, elem, conf) {
+               if (!conf->pattern)
+                       continue;
+               if (!strcmp(conf->pattern, pattern)) {
+                       ret = true;
+                       break;
+               }
+       }
+
+       return ret;
+}
+
 GVariant *hdbus_pattern_is_supported(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
@@ -550,7 +1104,7 @@ GVariant *hdbus_pattern_is_supported(GDBusConnection *conn,
 
        g_variant_get(param, "(s)", &data);
 
-       ret = h_ops->is_supported(data);
+       ret = pattern_is_supported(data);
 
        _I("%s is supported : %d", data, ret);
 
diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c
deleted file mode 100644 (file)
index 66e3eae..0000000
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * feedbackd
- *
- * Copyright (c) 2016 - 2017 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-#include "core/log.h"
-#include "core/list.h"
-#include "core/config-parser.h"
-#include "haptic.h"
-#include "standard-vibcore.h"
-
-#define FEEDBACK_BASE_PATH         "/usr/share/feedback/"
-#define STANDARD_FILE_PATH         FEEDBACK_BASE_PATH"vibration/"
-#define VIBRATION_CONF_PATH        FEEDBACK_BASE_PATH"vibration.conf"
-
-#define INTENSITY_BASE_RATE        (10000)
-#define VALUE_MAX_LEN 10
-#define VIB_LOCK_TIMEOUT_MAX       (300000) /* 5minutes */
-
-/*
-               1,A_W or A,A_W or 250D250W250D750W
-
-               85,10000,
-               90,0,
-               105,10000,
-               0,end
-*/
-struct vibration_config {
-       char *pattern; /* pattern name */
-       char *standard; /* assigned standard pattern name */
-       dd_list *data; /* duration_data list */
-       unsigned int pattern_duration;
-       int unlimit;
-};
-
-struct duration_data {
-       int duration;
-       int intensity;
-       int wait;
-};
-
-static dd_list *vib_conf_list;
-static guint duration_timer;
-
-static t_vibrate_monotone real_vibrate_monotone;
-
-static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
-{
-       struct duration_data *data;
-
-       data = (struct duration_data *)calloc(1, sizeof(struct duration_data));
-       if (!data) {
-               _E("not enough memory");
-               return -ENOMEM;
-       }
-       memcpy(data, update, sizeof(struct duration_data));
-       /* insert vibration pattern data */
-       // to debug :
-       // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdriving, data->wait);
-       DD_LIST_APPEND(*conf_data, data);
-       return 0;
-}
-
-static void get_pattern_property(char **iter, char property, int *value)
-{
-       char *check;
-       unsigned long int val;
-
-       check = strchr(*iter, property);
-       if (!check)
-               return;
-
-       *check = '\0';
-       val = strtoul(*iter, NULL, 10);
-       if (errno == EINVAL || errno == ERANGE) {
-               val = 0;
-               _E("Failed to get value of %s: %d", *iter, errno);
-       }
-       if (val > VIB_LOCK_TIMEOUT_MAX)
-               val = VIB_LOCK_TIMEOUT_MAX;
-
-       *value = (int)val;
-
-       *iter = check + 1;
-}
-
-/* [A]xxxDxxxIxxxFxxxOxxxW format */
-static int insert_raw_data_format(dd_list **conf_data, char *value)
-{
-       struct duration_data update = {0, };
-       char *iter;
-       char *end;
-       int pattern_duration = 0;
-
-       if (!value)
-               return insert_conf_data(conf_data, &update);
-       if (!conf_data) {
-               _E("Invalid parameter: Configuration list is null");
-               return -EINVAL;
-       }
-
-       iter = value;
-       end = iter + strlen(iter);
-       while (iter < end) {
-               memset(&update, 0, sizeof(struct duration_data));
-
-               get_pattern_property(&iter, 'D', &update.duration);
-               get_pattern_property(&iter, 'I', &update.intensity);
-               if (update.intensity > INTENSITY_BASE_RATE)
-                       update.intensity = INTENSITY_BASE_RATE;
-               get_pattern_property(&iter, 'W', &update.wait);
-
-               if (update.duration == 0 && update.wait == 0) {
-                       _D("Pattern duration is zero.");
-                       break;
-               }
-
-               pattern_duration += (update.duration + update.wait);
-               if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
-                       _D("Max pattern duration");
-                       pattern_duration = VIB_LOCK_TIMEOUT_MAX;
-               }
-
-               if (insert_conf_data(conf_data, &update) < 0)
-                       return -EINVAL;
-       }
-
-       return pattern_duration;
-}
-
-static int get_config_data(int count, bool *packed, char *val, unsigned int *pattern_duration, struct duration_data *update)
-{
-       static int duration = 0;
-       int value;
-
-       if (count > 2 || count <= 0) {
-               _E("Invalid parameter: count is invalid");
-               return -EINVAL;
-       }
-
-       if (!packed || !val || !pattern_duration || !update) {
-               _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update);
-               return -EINVAL;
-       }
-
-       get_pattern_property(&val, 'C', &value);
-
-       if (count == 1) {
-               duration = value;
-               *pattern_duration += duration;
-               if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
-                       _D("Max pattern duration");
-                       *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
-
-               }
-               return count;
-       }
-
-       if (value > INTENSITY_BASE_RATE)
-               value = INTENSITY_BASE_RATE;
-       if (*packed == false) {
-               update->duration = duration;
-               update->intensity = value;
-               *packed = true;
-               return 0;
-       }
-       if (value == 0)
-               update->wait = duration;
-       else
-               update->wait = 0;
-       *packed = false;
-       duration = 0;
-
-       return -1;
-}
-
-/*
-       duration, intensity, frequency, overdriving
-       waiting duration, intensity=0, frequency, overdriving
-       85,10000,
-       90,0,
-       105,10000,
-       0,end
-*/
-static int load_standard_format(const char *pattern)
-{
-       struct duration_data update = {0, };
-       bool packed = false;
-       struct vibration_config *conf;
-       int ret = 0, count = 0, end = 2;
-       int index = 0;
-       int fd;
-       char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, };
-
-       snprintf(path, sizeof(path), STANDARD_FILE_PATH"%s", pattern);
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-               return -ENOENT;
-
-       conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
-       if (!conf) {
-               _E("fail to alloc");
-               ret = -errno;
-               goto error_out;
-       }
-
-       conf->pattern = strdup(pattern);
-       if (!conf->pattern) {
-               _E("fail to copy %s pattern data", pattern);
-               ret = -errno;
-               goto error_out;
-       }
-
-       /* make feedback pattern(xDxIxFxOxW) format from d,i,f,o, */
-       while (read(fd, &elem, 1) != 0) {
-               if (end == 0) {
-                       if (insert_conf_data(&conf->data, &update) < 0)
-                               goto error_out;
-                       break;
-               }
-               if (elem == 'e' || elem == 'n' || elem == 'd') {
-                       end--;
-                       continue;
-               }
-               if (elem == '\n') {
-                       count = 0;
-                       continue;
-               }
-               if (elem == ',') {
-                       count++;
-                       val[index] = 'C';
-                       index = 0;
-
-                       ret = get_config_data(count, &packed, val, &(conf->pattern_duration), &update);
-                       if (ret < 0) {
-                               if (ret == -EINVAL)
-                                       break;
-                               if (insert_conf_data(&conf->data, &update) < 0)
-                                       goto error_out;
-                               memset(&update, 0, sizeof(struct duration_data));
-                       } else
-                               count = ret;
-               } else {
-                       if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */
-                               val[index++] = elem;
-                       else
-                               _E("Pattern %s is out of bound: %s", pattern, val);
-               }
-       }
-       close(fd);
-       DD_LIST_APPEND(vib_conf_list, conf);
-       return ret;
-
-error_out:
-       if (fd >= 0)
-               close(fd);
-       if (conf) {
-               if (conf->pattern)
-                       free(conf->pattern);
-               free(conf);
-       }
-       return -ENOENT;
-}
-
-static int vibration_load_config(struct parse_result *result, void *user_data)
-{
-       struct vibration_config *conf;
-       char *value;
-       char *check;
-       int len;
-       int duration;
-
-       if (!result)
-               return 0;
-
-       if (!MATCH(result->section, "Vibration"))
-               return 0;
-
-
-       if (!result->name || !result->value)
-               return 0;
-
-       conf = (struct vibration_config *)calloc(1, sizeof(struct vibration_config));
-       if (!conf) {
-               _E("fail to alloc");
-               return -ENOMEM;
-       }
-
-       conf->pattern_duration = 0;
-       conf->pattern = strdup(result->name);
-       if (!conf->pattern) {
-               _E("fail to copy %s pattern data", result->name);
-               goto error_out;
-       }
-
-       value = result->value;
-       len = strlen(value);
-
-       if (len == 0) {
-               if (insert_raw_data_format(&conf->data, NULL) < 0)
-                       goto error_out;
-               DD_LIST_APPEND(vib_conf_list, conf);
-               return 0;
-       }
-
-       /* Load Standard Pattern Name */
-       /* value: 1,A_W or A,A_W */
-       if ((check = strchr(value, ','))) {
-               *check = '\0';
-               if (strncmp(value, "A", 1) == 0)
-                       conf->unlimit = 1;
-               value = check + 1;
-               conf->standard = strdup(value);
-               if (!conf->standard) {
-                       _E("fail to copy standard name");
-                       goto error_out;
-               }
-               DD_LIST_APPEND(vib_conf_list, conf);
-               return 0;
-       }
-
-       /* value : A100D or 100D0W or 250D250W250D750W */
-       /* Load Vibration Pattern Data */
-       check = strchr(value, 'A');
-       if (check) {
-               *check = '\0';
-               conf->unlimit = 1;
-               if (!value)
-                       len = len - 1;
-               else
-                       len = len - strlen(value) - 1;
-               value = check + 1;
-       }
-       duration = insert_raw_data_format(&conf->data, value);
-       if (duration < 0) {
-               conf->pattern_duration = 0;
-               goto error_out;
-       } else
-               conf->pattern_duration = duration;
-       DD_LIST_APPEND(vib_conf_list, conf);
-
-       return 0;
-
-error_out:
-       if (conf) {
-               if (conf->pattern)
-                       free(conf->pattern);
-               if (conf->standard)
-                       free(conf->standard);
-       }
-       return -ENOMEM;
-}
-
-static void load_standard_vibration_patterns(void)
-{
-       DIR *dir;
-       struct dirent *dent;
-       int ret;
-
-       dir = opendir(STANDARD_FILE_PATH);
-       if (!dir) {
-               _E("Failed to load %s Use default value!", STANDARD_FILE_PATH);
-               return;
-       }
-       while ((dent = readdir(dir))) {
-               if (dent->d_type == DT_DIR)
-                       continue;
-               ret = load_standard_format(dent->d_name);
-               if (ret < 0)
-                       _E("Failed to parse %s: %d", dent->d_name, ret);
-       }
-       closedir(dir);
-       _D("Success to load %s", STANDARD_FILE_PATH);
-}
-
-void standard_config_parse(void)
-{
-       int ret;
-
-       ret = config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL);
-       if (ret < 0)
-               _E("Failed to load %s, %d Use default value!", VIBRATION_CONF_PATH, ret);
-
-       load_standard_vibration_patterns();
-}
-
-int standard_is_supported(const char *pattern)
-{
-       dd_list *elem;
-       struct vibration_config *conf;
-       int ret;
-
-       if (!pattern)
-               return -EINVAL;
-
-       ret = 0;
-       DD_LIST_FOREACH(vib_conf_list, elem, conf) {
-               if (!conf->pattern)
-                       continue;
-               if (!strcmp(conf->pattern, pattern)) {
-                       ret = true;
-                       break;
-               }
-       }
-
-       return ret;
-}
-
-static gboolean haptic_duration_play(void *data)
-{
-       dd_list *head, *n, *next;
-       struct duration_data *node;
-       int level;
-       int ret = 0;
-
-       if (duration_timer) {
-               g_source_remove(duration_timer);
-               duration_timer = 0;
-       }
-
-       if (!data) {
-               if (cur_h_data.unlimit) /* In case of unlimit pattern, do not stop */
-                       head = cur_h_data.vibration_data;
-               else {
-                       cur_h_data.handle = INVALID_HANDLE;
-                       cur_h_data.priority = PRIORITY_MIN;
-                       goto out;
-               }
-       } else
-               head = (dd_list *)data;
-
-       if (cur_h_data.stop) {
-               _I("Stop currunt vibration");
-               cur_h_data.stop = false;
-               cur_h_data.handle = INVALID_HANDLE;
-               cur_h_data.priority = PRIORITY_MIN;
-               goto out;
-       }
-
-       DD_LIST_FOREACH_SAFE(head, n, next, node) {
-               _D("Handle %d play: %dms and Wait: %dms %s type",
-                       cur_h_data.handle, node->duration, node->wait,
-                       cur_h_data.unlimit ? "Unlimit" : "Once");
-               if ((node->duration + node->wait) <= 0) {
-                       if (!cur_h_data.unlimit) {
-                               cur_h_data.handle = INVALID_HANDLE;
-                               cur_h_data.priority = PRIORITY_MIN;
-                               break;
-                       } else {
-                               next = cur_h_data.vibration_data;
-                               continue;
-                       }
-               }
-
-               if (node->intensity)
-                       level = (cur_h_data.level * node->intensity) / INTENSITY_BASE_RATE;
-               else
-                       level = cur_h_data.level;
-
-               duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next);
-
-               ret = real_vibrate_monotone(cur_h_data.handle, node->duration, level, cur_h_data.priority);
-
-               break;
-       }
-       if (ret != 0) {
-               _D("auto stop vibration");
-               cur_h_data.stop = true;
-       }
-out:
-       return G_SOURCE_REMOVE;
-}
-
-int standard_set_vib_function(t_vibrate_monotone func)
-{
-       real_vibrate_monotone = func;
-       return 0;
-}
-
-int standard_vibrate_monotone(int device_handle, int duration, int feedback, int priority)
-{
-       int ret;
-
-       if (priority < cur_h_data.priority) {
-               _I("Handle %d skip low priority(pre:%d now:%d)", device_handle, cur_h_data.priority, priority);
-               return 0;
-       }
-
-       cur_h_data.vibration_data = NULL;
-       cur_h_data.handle = device_handle;
-       cur_h_data.level = feedback;
-       cur_h_data.priority = priority;
-       cur_h_data.stop = false;
-       cur_h_data.unlimit = false;
-
-       ret = device_power_request_lock(POWER_LOCK_CPU, duration);
-       if (ret != DEVICE_ERROR_NONE)
-               _E("Failed to request power lock");
-       real_vibrate_monotone(cur_h_data.handle, duration, cur_h_data.level, cur_h_data.priority);
-
-       return 0;
-}
-
-int standard_vibrate_effect(int device_handle, const char *requested_pattern, int feedback, int priority)
-{
-       dd_list *elem;
-       struct vibration_config *conf;
-       char pattern[PATH_MAX];
-       int ret;
-       int unlimit = 0;
-
-       if (device_handle < 0 || !requested_pattern)
-               return -EINVAL;
-
-       /* Same or higher priority pattern should be played */
-       if (priority < cur_h_data.priority) {
-               _I("Handle %d skip low priority(pre:%d now:%d)", device_handle, cur_h_data.priority, priority);
-               return 0;
-       }
-
-       snprintf(pattern, sizeof(pattern), "%s", requested_pattern);
-       DD_LIST_FOREACH(vib_conf_list, elem, conf) {
-               if (!conf->pattern)
-                       continue;
-               if (strcmp(conf->pattern, pattern))
-                       continue;
-               if (conf->standard) {
-                       unlimit = conf->unlimit;
-                       snprintf(pattern, sizeof(pattern), "%s", conf->standard);
-                       continue;
-               }
-
-               if (unlimit)
-                       cur_h_data.unlimit = unlimit;
-               else
-                       cur_h_data.unlimit = conf->unlimit;
-               cur_h_data.vibration_data = conf->data;
-               cur_h_data.handle = device_handle;
-               cur_h_data.level = feedback;
-               cur_h_data.priority = priority;
-               cur_h_data.stop = false;
-               _I("Handle %d play %s pri %d %s", cur_h_data.handle, conf->pattern, cur_h_data.priority,
-                               cur_h_data.unlimit ? "Unlimit" : "Once");
-
-               if (conf->pattern_duration <= 0)
-                       break;
-
-               if (!cur_h_data.unlimit && conf->pattern_duration > 0) {
-                       ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration);
-                       if (ret != DEVICE_ERROR_NONE)
-                               _E("Failed to request power lock");
-               }
-               haptic_duration_play((void *)cur_h_data.vibration_data);
-               return 0;
-       }
-       _E("Handld %d %s is not supported", device_handle, pattern);
-
-       return 0;
-}
-
-int standard_vibrate_close(void)
-{
-       cur_h_data.handle = INVALID_HANDLE;
-       cur_h_data.priority = PRIORITY_MIN;
-
-       if (duration_timer) {
-               _I("Remove duration_timer");
-               g_source_remove(duration_timer);
-               duration_timer = 0;
-       }
-
-       return 0;
-}
-
diff --git a/src/haptic/standard-vibcore.h b/src/haptic/standard-vibcore.h
deleted file mode 100644 (file)
index dd0c071..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * feedbackd
- *
- * Copyright (c) 2016 - 2017 Samsung Electronics Co., Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#ifndef __FEEDBACKD_STANDARD_VIBCORE_H__
-#define __FEEDBACKD_STANDARD_VIBCORE_H__
-
-typedef int (*t_vibrate_monotone)(int device_handle, int duration, int feedback, int priority);
-
-void standard_config_parse(void);
-int standard_is_supported(const char *pattern);
-int standard_vibrate_monotone(int device_handle, int duration, int feedback, int priority);
-int standard_vibrate_effect(int device_handle, const char *pattern, int feedback, int priority);
-int standard_set_vib_function(t_vibrate_monotone func);
-int standard_vibrate_close(void);
-
-#endif  /* __FEEDBACKD_STANDARD_VIBCORE_H__ */
index f5e43b4..871fd2c 100644 (file)
@@ -32,7 +32,6 @@
 #include "core/log.h"
 #include "core/list.h"
 #include "haptic.h"
-#include "standard-vibcore.h"
 
 #define MAX_MAGNITUDE                  0xFFFF
 #define PERIODIC_MAX_MAGNITUDE 0x7FFF  /* 0.5 * MAX_MAGNITUDE */
@@ -494,9 +493,6 @@ static int stop_device(int device_handle)
                return -EPERM;
        }
 
-       /* Remove duration_timer for vibrate_effect */
-       standard_vibrate_close();
-
        /* stop effect */
        r = ff_stop(ff_fd, &info->effect);
        if (r < 0)
@@ -518,9 +514,7 @@ static const struct haptic_plugin_ops default_plugin = {
        .get_device_count    = get_device_count,
        .open_device         = open_device,
        .close_device        = close_device,
-       .vibrate_monotone    = standard_vibrate_monotone,
-       .vibrate_effect      = standard_vibrate_effect,
-       .is_supported        = standard_is_supported,
+       .vibrate_monotone    = vibrate_monotone,
        .stop_device         = stop_device,
 };
 
@@ -534,15 +528,12 @@ static bool is_valid(void)
                return false;
        }
 
-       standard_config_parse();
-
        _I("Support standard haptic device");
        return true;
 }
 
 static const struct haptic_plugin_ops *load(void)
 {
-       standard_set_vib_function(&vibrate_monotone);
        return &default_plugin;
 }