From 97f5aad633293463b764b179a0593cfd27afc4cc Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 18 Feb 2019 15:59:24 +0900 Subject: [PATCH] Remove standard-vibcore.c Change-Id: I6a8eb297a6b3cb10637b763c5615c75d9bbc82ad Signed-off-by: pr.jung --- CMakeLists.txt | 6 +- src/haptic/circle.c | 11 +- src/haptic/emulator.c | 18 -- src/haptic/gpio_haptic.c | 11 +- src/haptic/haptic-plugin-intf.h | 2 - src/haptic/haptic.c | 564 +++++++++++++++++++++++++++++++++++++- src/haptic/standard-vibcore.c | 593 ---------------------------------------- src/haptic/standard-vibcore.h | 32 --- src/haptic/standard.c | 11 +- 9 files changed, 565 insertions(+), 683 deletions(-) delete mode 100644 src/haptic/standard-vibcore.c delete mode 100644 src/haptic/standard-vibcore.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8950c06..45ecc01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 7fd46f1..a4af20f 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -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; } diff --git a/src/haptic/emulator.c b/src/haptic/emulator.c index 6807391..fe40435 100644 --- a/src/haptic/emulator.c +++ b/src/haptic/emulator.c @@ -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, }; diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index 2334598..a188b10 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -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; } diff --git a/src/haptic/haptic-plugin-intf.h b/src/haptic/haptic-plugin-intf.h index 9d11f62..4c039a7 100644 --- a/src/haptic/haptic-plugin-intf.h +++ b/src/haptic/haptic-plugin-intf.h @@ -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); }; diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index f1cdc8a..d253225 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -33,6 +33,10 @@ #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" @@ -62,6 +66,32 @@ #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 index 66e3eae..0000000 --- a/src/haptic/standard-vibcore.c +++ /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 -#include -#include -#include -#include - -#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 index dd0c071..0000000 --- a/src/haptic/standard-vibcore.h +++ /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__ */ diff --git a/src/haptic/standard.c b/src/haptic/standard.c index f5e43b4..871fd2c 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -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; } -- 2.7.4