From 65c2f634edc2646d483286e3532af3967710b8ea Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Thu, 17 May 2018 13:47:19 +0900 Subject: [PATCH 01/16] dbus-policy: change to default deny policy Change-Id: I8849c0e73c766e9b11ba004c12b7e0b5fff48fca Signed-off-by: sanghyeok.oh --- scripts/feedbackd.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/feedbackd.conf b/scripts/feedbackd.conf index 05f4ece..2ded9e1 100755 --- a/scripts/feedbackd.conf +++ b/scripts/feedbackd.conf @@ -12,6 +12,7 @@ + Date: Wed, 20 Jun 2018 18:08:57 +0900 Subject: [PATCH 02/16] haptic: Remove unused code - Remove standard_mix.c Change-Id: I8d6a567da78bf472a7a0ca72265a6325b497d733 Signed-off-by: pr.jung --- CMakeLists.txt | 2 - packaging/feedbackd.spec | 2 - src/haptic/standard-mix.c | 1085 --------------------------------------------- 3 files changed, 1089 deletions(-) delete mode 100644 src/haptic/standard-mix.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 273646c..3eeb80b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,8 +26,6 @@ ELSEIF(DRIVER STREQUAL standard) SET(SRCS ${SRCS} src/haptic/standard.c src/haptic/standard-vibcore.c) ELSEIF(DRIVER STREQUAL circle) SET(SRCS ${SRCS} src/haptic/circle.c src/haptic/standard-vibcore.c) -ELSEIF(DRIVER STREQUAL mix) - SET(SRCS ${SRCS} src/haptic/standard-mix.c) ENDIF() INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index 8e38701..d33ccfb 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -3,8 +3,6 @@ %bcond_with wayland %bcond_with emulator -%define standard_mix off - Name: feedbackd Summary: Feedbackd Version: 1.0.0 diff --git a/src/haptic/standard-mix.c b/src/haptic/standard-mix.c deleted file mode 100644 index 578a700..0000000 --- a/src/haptic/standard-mix.c +++ /dev/null @@ -1,1085 +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 -#include -#include -#include -#include -#include - -#include "core/log.h" -#include "core/list.h" -#include "core/config-parser.h" -#include "haptic.h" - -#define MAX_MAGNITUDE 0xFFFF -#define PERIODIC_MAX_MAGNITUDE 0x7FFF /* 0.5 * MAX_MAGNITUDE */ -#define RUMBLE_MAX_MAGNITUDE 0xFFFF - -#define DEV_INPUT "/dev/input" -#define EVENT "event" - -#define BITS_PER_LONG (sizeof(long) * 8) -#define OFF(x) ((x)%BITS_PER_LONG) -#define BIT(x) (1UL<> OFF(bit)) & 1) - -#define MAX_DATA 16 -#define FF_INFO_MAGIC 0xDEADFEED - -#define VIBRATION_CONF_PATH "/usr/share/feedback/vibration_mix.conf" -#define VIBRATION_DURATION_CONF_PATH "/usr/share/feedback/vibration_duration.conf" -#define VIBRATION_WAITING_CONF_PATH "/usr/share/feedback/vibration_waiting.conf" - -struct ff_info_header { - unsigned int magic; - int iteration; - int ff_info_data_count; -}; - -struct ff_info_data { - int type;/* play, stop etc */ - int magnitude; /* strength */ - int length; /* in ms for stop, play*/ -}; - -struct ff_info_buffer { - struct ff_info_header header; - struct ff_info_data data[MAX_DATA]; -}; - -struct ff_info { - int handle; - guint timer; - struct ff_effect effect; - struct ff_info_buffer *ffinfobuffer; - int currentindex; -}; - -struct vibration_table { - char *pattern; - char *duration; - char *waiting; -}; - -struct vibration_config { - char *pattern; - int *data; - int data_len; -}; - -struct haptic_data { - unsigned int handle; - int *duration_config; - int *waiting_config; - int level; - int priority; - int duration_len; - int waiting_len; - int index; - bool stop; -}; - -static int ff_fd; -static dd_list *ff_list; -static dd_list *handle_list; -static dd_list *vib_conf_list; -static dd_list *vib_duration_conf_list; -static dd_list *vib_waiting_conf_list; -static guint duration_timer; -static char ff_path[PATH_MAX]; -static int unique_number; - -struct ff_info *read_from_list(int handle) -{ - struct ff_info *temp; - dd_list *elem; - - DD_LIST_FOREACH(ff_list, elem, temp) { - if (temp->handle == handle) - return temp; - } - return NULL; -} - -static bool check_valid_handle(struct ff_info *info) -{ - struct ff_info *temp; - dd_list *elem; - - DD_LIST_FOREACH(ff_list, elem, temp) { - if (temp == info) - break; - } - - if (!temp) - return false; - return true; -} - -static bool check_fd(int *fd) -{ - int ffd; - - if (*fd > 0) - return true; - - ffd = open(ff_path, O_RDWR); - if (ffd < 0) - return false; - - *fd = ffd; - return true; -} - -static int ff_stop(int fd, struct ff_effect *effect); -static Eina_Bool timer_cb(void *data) -{ - struct ff_info *info = (struct ff_info *)data; - - if (!info) - return G_SOURCE_REMOVE; - - if (!check_valid_handle(info)) - return G_SOURCE_REMOVE; - - _I("stop vibration by timer : id(%d)", info->effect.id); - - /* stop previous vibration */ - ff_stop(ff_fd, &info->effect); - - /* reset timer */ - info->timer = NULL; - - return G_SOURCE_REMOVE; -} - -static int ff_find_device(void) -{ - DIR *dir; - struct dirent *dent; - char ev_path[PATH_MAX]; - unsigned long features[1+FF_MAX/sizeof(unsigned long)]; - int fd, ret; - - dir = opendir(DEV_INPUT); - if (!dir) - return -errno; - - while (1) { - dent = readdir(dir); - if (dent == NULL) - break; - - if (dent->d_type == DT_DIR || - !strstr(dent->d_name, "event")) - continue; - - snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name); - - fd = open(ev_path, O_RDWR); - if (fd < 0) - continue; - - /* get force feedback device */ - memset(features, 0, sizeof(features)); - ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features); - if (ret == -1) { - close(fd); - continue; - } - - if (test_bit(FF_CONSTANT, features)) - _D("%s type : constant", ev_path); - if (test_bit(FF_PERIODIC, features)) - _D("%s type : periodic", ev_path); - if (test_bit(FF_SPRING, features)) - _D("%s type : spring", ev_path); - if (test_bit(FF_FRICTION, features)) - _D("%s type : friction", ev_path); - if (test_bit(FF_RUMBLE, features)) - _D("%s type : rumble", ev_path); - - if (test_bit(FF_RUMBLE, features)) { - memcpy(ff_path, ev_path, strlen(ev_path)); - close(fd); - closedir(dir); - return 0; - } - - close(fd); - } - - closedir(dir); - return -1; -} - -static int ff_init_effect(struct ff_effect *effect) -{ - if (!effect) - return -EINVAL; - - /*Only rumble supported as of now*/ - effect->type = FF_RUMBLE; - effect->replay.length = 0; - effect->replay.delay = 10; - effect->id = -1; - effect->u.rumble.strong_magnitude = 0x8000; - effect->u.rumble.weak_magnitude = 0xc000; - - return 0; -} - -static int ff_set_effect(struct ff_effect *effect, int length, int level) -{ - double magnitude; - - if (!effect) - return -EINVAL; - - magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX; - magnitude *= RUMBLE_MAX_MAGNITUDE; - - _I("info : magnitude(%d) length(%d)", (int)magnitude, length); - - /* set member variables in effect struct */ - effect->u.rumble.strong_magnitude = (int)magnitude; - effect->replay.length = length; /* length millisecond */ - - return 0; -} - -static int ff_play(int fd, struct ff_effect *effect) -{ - struct input_event play; - int ret; - - if (fd < 0 || !effect) { - if (fd < 0) - _E("fail to check fd"); - else - _E("fail to check effect"); - return -EINVAL; - } - - /* upload an effect */ - if (ioctl(fd, EVIOCSFF, effect) == -1) { - _E("fail to ioctl"); - return -errno; - } - - /* play vibration*/ - play.type = EV_FF; - play.code = effect->id; - play.value = 1; /* 1 : PLAY, 0 : STOP */ - - ret = write(fd, (const void *)&play, sizeof(play)); - if (ret == -1) { - _E("fail to write"); - return -errno; - } - - return 0; -} - -static int ff_stop(int fd, struct ff_effect *effect) -{ - struct input_event stop; - int ret; - - if (fd < 0) - return -EINVAL; - - /* Stop vibration */ - stop.type = EV_FF; - stop.code = effect->id; - stop.value = 0; /* 1 : PLAY, 0 : STOP */ - ret = write(fd, (const void *)&stop, sizeof(stop)); - if (ret == -1) - return -errno; - - /* removing an effect from the device */ - if (ioctl(fd, EVIOCRMFF, effect->id) == -1) - return -errno; - - /* reset effect id */ - effect->id = -1; - - return 0; -} - -/* START: Haptic Module APIs */ -static int get_device_count(int *count) -{ - /* suppose there is just one haptic device */ - if (count) - *count = 1; - - return 0; -} - -static int open_device(int device_index, int *device_handle) -{ - struct ff_info *info; - int n; - bool found = false; - dd_list *elem; - - if (!device_handle) - return -EINVAL; - - /* if it is the first element */ - n = DD_LIST_LENGTH(ff_list); - if (n == 0 && !ff_fd) { - _I("First element: open ff driver"); - /* open ff driver */ - ff_fd = open(ff_path, O_RDWR); - if (ff_fd < 0) { - _E("Failed to open %s : %d", ff_path, errno); - return -errno; - } - } - - /* allocate memory */ - info = calloc(sizeof(struct ff_info), 1); - if (!info) { - _E("Failed to allocate memory : %d", errno); - return -errno; - } - - /* initialize ff_effect structure */ - ff_init_effect(&info->effect); - - if (unique_number == INT_MAX) - unique_number = 0; - - while (found != true) { - ++unique_number; - elem = DD_LIST_FIND(handle_list, (gpointer)(long)unique_number); - if (!elem) - found = true; - } - - info->handle = unique_number; - - /* add info to local list */ - DD_LIST_APPEND(ff_list, info); - DD_LIST_APPEND(handle_list, (gpointer)(long)info->handle); - - *device_handle = info->handle; - return 0; -} - -static int close_device(int device_handle) -{ - struct ff_info *info; - int r, n; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* stop vibration */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _I("already stopped or failed to stop effect : %d", r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - _D("device handle %d is closed and timer deleted", device_handle); - g_source_remove(info->timer); - info->timer = NULL; - } - - DD_LIST_REMOVE(handle_list, (gpointer)(long)info->handle); - - safe_free(info->ffinfobuffer); - /* remove info from local list */ - DD_LIST_REMOVE(ff_list, info); - safe_free(info); - - /* if it is the last element */ - n = DD_LIST_LENGTH(ff_list); - if (n == 0 && ff_fd) { - _I("Last element: close ff driver"); - /* close ff driver */ - close(ff_fd); - ff_fd = 0; - } - - return 0; -} - -static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) -{ - struct ff_info *info; - int ret; - - info = read_from_list(device_handle); - if (!info) { - _E("fail to check list"); - return -EINVAL; - } - - if (!check_valid_handle(info)) { - _E("fail to check handle"); - return -EINVAL; - } - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* Zero(0) is the infinitely vibration value */ - if (duration == HAPTIC_MODULE_DURATION_UNLIMITED) - duration = 0; - - /* unregister existing timer */ - if (info->timer) { - ff_stop(ff_fd, &info->effect); - g_source_remove(info->timer); - info->timer = NULL; - } - - /* set effect as per arguments */ - ff_init_effect(&info->effect); - ret = ff_set_effect(&info->effect, duration, feedback); - if (ret < 0) { - _E("failed to set effect(duration:%d, feedback:%d) : %d", - duration, feedback, ret); - return ret; - } - - /* play effect as per arguments */ - ret = ff_play(ff_fd, &info->effect); - if (ret < 0) { - _E("failed to play haptic effect(fd:%d id:%d) : %d", - ff_fd, info->effect.id, ret); - return ret; - } - - /* register timer */ - if (duration) { - info->timer = g_timeout_add(duration, timer_cb, info); - if (!info->timer) - _E("Failed to add timer callback"); - } - - _D("device handle %d effect id : %d %dms", device_handle, info->effect.id, duration); - if (effect_handle) - *effect_handle = info->effect.id; - - return 0; -} - -static gboolean _buffer_play(void *cbdata) -{ - struct ff_info *info = (struct ff_info *)cbdata; - struct ff_info_header *header = &info->ffinfobuffer->header; - struct ff_info_data *data = info->ffinfobuffer->data; - int index = info->currentindex; - int play_type = (index < header->ff_info_data_count) ? data[index].type : 0; - int length = (index < header->ff_info_data_count) ? data[index].length : 1; - int ret; - - ff_set_effect(&info->effect, length, 1); - if (play_type != 0) { - _D("Going to play for %d ms", length); - ret = ff_play(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to play the effect %d", ret); - } else { - _D("Going to stop for %d ms", length); - ret = ff_stop(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to stop the effect %d", ret); - } - - if (info->currentindex < header->ff_info_data_count) { - info->currentindex++; - info->timer = g_timeout_add(length, _buffer_play, info); - } else { - --header->iteration; - if (header->iteration > 0) { - info->currentindex = 0; - info->timer = g_timeout_add(0, _buffer_play, info); - } else - info->timer = NULL; - } - - return G_SOURCE_REMOVE; -} - -static void print_buffer(const unsigned char *vibe_buffer) -{ - struct ff_info_buffer fb; - int i = 0; - memcpy(&fb.header, vibe_buffer, sizeof(struct ff_info_header)); - memcpy(&fb.data, (unsigned char *)vibe_buffer+sizeof(struct ff_info_header), - sizeof(struct ff_info_data) * fb.header.ff_info_data_count); - _D("\nMagic %x\niteration %d\ncount %d\n", fb.header.magic, - fb.header.iteration, fb.header.ff_info_data_count); - - for (i = 0; i < fb.header.ff_info_data_count; i++) - _D("type %d\nmagn 0x%x\nlen %d\n", fb.data[i].type, - fb.data[i].magnitude, fb.data[i].length); -} - -static int vibrate_custom_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - struct ff_info *info; - struct ff_info_header *header; - struct ff_info_data *data; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - if (!info->ffinfobuffer) - info->ffinfobuffer = (struct ff_info_buffer *)calloc(sizeof(struct ff_info_buffer), 1); - if (!info->ffinfobuffer) - return -ENOMEM; - - header = &info->ffinfobuffer->header; - data = info->ffinfobuffer->data; - - memcpy(header, vibe_buffer, sizeof(struct ff_info_header)); - if (header->ff_info_data_count < 0 || header->ff_info_data_count > MAX_DATA) - return -EINVAL; - - memcpy(data, vibe_buffer+sizeof(struct ff_info_header), sizeof(struct ff_info_data) * header->ff_info_data_count); - - info->currentindex = 0; - if (info->timer) - g_source_remove(info->timer); - - if (header->iteration > 0) - _buffer_play(info); - - return 0; -} - -static gboolean haptic_duration_play(void *data) -{ - struct haptic_data *h_data; - double time; - int ret = 0; - int index; - unsigned int v_handle; - int level; - int priority; - int duration; - - - if (!data) - return G_SOURCE_REMOVE; - - if (duration_timer) { - g_source_remove(duration_timer); - duration_timer = 0; - } - - h_data = (struct haptic_data *)data; - if (h_data->stop) { - h_data->stop = false; - free(h_data); - return G_SOURCE_REMOVE; - } - - index = h_data->index; - v_handle = h_data->handle; - level = h_data->level; - priority = h_data->priority; - - if (!h_data->duration_config[index]) { - free(h_data); - return G_SOURCE_REMOVE; - } - - duration = h_data->duration_config[index]; - - h_data->index++; - if (h_data->index > h_data->duration_len - 1) - free(h_data); - else { - if (h_data->index > h_data->waiting_len - 1) - time = duration; - else - time = duration + h_data->waiting_config[index]; - - /*duration_timer = ecore_timer_add(time/1000.0f, haptic_duration_play, (void *)h_data);*/ - duration_timer = g_timeout_add(time, haptic_duration_play, (void *)h_data); - _D("timer: %d", time); - } - - _D("duration: %d", duration); - - ret = vibrate_monotone(v_handle, duration, level, priority, NULL); - if (ret != 0) { - _D("auto stop vibration"); - if (h_data) - h_data->stop = true; - } - return G_SOURCE_REMOVE; -} - -static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - int magic = 0; - - if (!device_handle) - return -EINVAL; - - if (vibe_buffer) - magic = *(int *)vibe_buffer; - - if (magic == FF_INFO_MAGIC) { - print_buffer(vibe_buffer); - return vibrate_custom_buffer(device_handle, vibe_buffer, iteration, feedback, priority, effect_handle); - } else - return vibrate_monotone(device_handle, 300, feedback, priority, effect_handle); -} - -static int vibrate_effect(int device_handle, const char *pattern, int feedback, int priority) -{ - dd_list *elem1, *elem2; - struct vibration_table *conf_table; - struct vibration_config *conf_duration, *conf_waiting; - struct haptic_data *data; - char *duration = NULL, *waiting = NULL; - int len1, len2; - - if (!device_handle) - return -EINVAL; - - if (!pattern) - return -EINVAL; - - len1 = strlen(pattern) + 1; - DD_LIST_FOREACH(vib_conf_list, elem1, conf_table) { - if (!conf_table->pattern) - continue; - if (strncmp(conf_table->pattern, pattern, len1)) - continue; - duration = conf_table->duration; - waiting = conf_table->waiting; - break; - } - - if (!duration) - return -ENOTSUP; - - len1 = strlen(duration) + 1; - if (!waiting) - len2 = 0; - else - len2 = strlen(waiting) + 1; - DD_LIST_FOREACH(vib_duration_conf_list, elem1, conf_duration) { - if (!conf_duration->pattern) - continue; - if (strncmp(conf_duration->pattern, duration, len1)) - continue; - - data = (struct haptic_data *)malloc(sizeof(struct haptic_data)); - if (!data) { - _E("fail to alloc"); - return -ENOMEM; - } - data->duration_len = 0; - data->waiting_len = 0; - - DD_LIST_FOREACH(vib_waiting_conf_list, elem2, conf_waiting) { - if (!waiting) - break; - if (!conf_waiting->pattern) - continue; - if (strncmp(conf_waiting->pattern, waiting, len2)) - continue; - data->waiting_config = conf_waiting->data; - data->waiting_len = conf_waiting->data_len; - break; - } - data->handle = device_handle; - data->level = feedback; - data->priority = priority; - data->duration_config = conf_duration->data; - data->duration_len = conf_duration->data_len; - data->index = 0; - - haptic_duration_play((void *)data); - break; - } - - return 0; -} - -static int is_supported(const char *pattern) -{ - dd_list *elem; - struct vibration_table *conf; - int ret = 0; - int len; - - if (!pattern) - return -EINVAL; - - len = strlen(pattern) + 1; - DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) - continue; - if (!strncmp(conf->pattern, pattern, len)) { - ret = true; - break; - } - } - - return ret; -} - -static int stop_device(int device_handle) -{ - struct ff_info *info; - int r; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - /* stop effect */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _E("failed to stop effect(id:%d) : %d", info->effect.id, r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - g_source_remove(info->timer); - info->timer = NULL; - } - - return 0; -} - -static int get_device_state(int device_index, int *effect_state) -{ - struct ff_info *info; - dd_list *elem; - int status = false; - - if (!effect_state) - return -EINVAL; - - /* suppose there is just one haptic device */ - DD_LIST_FOREACH(ff_list, elem, info) { - if (info->effect.id >= 0) { - status = true; - break; - } - } - - *effect_state = status; - return 0; -} - -static int create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not supported feature"); - return -EACCES; -} - -static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - _E("Not supported feature"); - return -EACCES; -} - -static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not supported feature"); - return -EACCES; -} -/* END: Haptic Module APIs */ - -static const struct haptic_plugin_ops default_plugin = { - .get_device_count = get_device_count, - .open_device = open_device, - .close_device = close_device, - .vibrate_monotone = vibrate_monotone, - .vibrate_buffer = vibrate_buffer, - .vibrate_effect = vibrate_effect, - .is_supported = is_supported, - .stop_device = stop_device, - .get_device_state = get_device_state, - .create_effect = create_effect, - .get_buffer_duration = get_buffer_duration, - .convert_binary = convert_binary, -}; - -static int vibration_duration_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_config *conf; - char *value; - char *check; - int count = 0; - int len; - int i; - - 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 = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_duration_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - while (check != NULL) { - count++; - check = strchr(check + 1, ','); - } - - int *duration = (int *)malloc((count + 1) * sizeof(int)); - for (i = 0; i <= count; i++) { - duration[i] = 0; - check = strchr(value, ','); - if (check) { - *check = '\0'; - duration[i] = strtol(value, NULL, 10); - value = check + 1; - } else { - duration[i] = strtol(value, NULL, 10); - break; - } - if (duration[i] == 0) - break; - } - conf->data = duration; - conf->data_len = count + 1; - - DD_LIST_APPEND(vib_duration_conf_list, conf); - - return 0; -} - -static int vibration_waiting_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_config *conf; - char *value; - char *check; - int count = 0; - int len; - int i; - - 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 = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_waiting_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - while (check != NULL) { - count++; - check = strchr(check + 1, ','); - } - - int *waiting = (int *)malloc((count + 1) * sizeof(int)); - for (i = 0; i <= count; i++) { - waiting[i] = 0; - check = strchr(value, ','); - if (check) { - *check = '\0'; - waiting[i] = strtol(value, NULL, 10); - value = check + 1; - } else { - waiting[i] = strtol(value, NULL, 10); - break; - } - if (waiting[i] == 0) - break; - } - conf->data = waiting; - conf->data_len = count + 1; - - DD_LIST_APPEND(vib_waiting_conf_list, conf); - - return 0; -} - -static int vibration_table_load_config(struct parse_result *result, void *user_data) -{ - struct vibration_table *conf; - char *value; - char *check; - int len; - - if (!result) - return 0; - - if (!MATCH(result->section, "Vibration")) - return 0; - - - if (!result->name || !result->value) - return 0; - - conf = (struct vibration_table *)calloc(1, sizeof(struct vibration_table)); - if (!conf) { - _E("fail to alloc"); - return -ENOMEM; - } - - conf->pattern = strdup(result->name); - if (!conf->pattern) - _E("fail to copy %s pattern data", result->name); - - value = result->value; - - if (!value) - len = 0; - else - len = strlen(value); - - if (len == 0) { - DD_LIST_APPEND(vib_conf_list, conf); - return 0; - } - - check = strchr(value, ','); - - if (check) { - *check = '\0'; - conf->duration = strdup(value); - value = check + 1; - conf->waiting = strdup(value); - } else - conf->duration = strdup(value); - - DD_LIST_APPEND(vib_conf_list, conf); - - return 0; -} - -static bool is_valid(void) -{ - int ret; - - ret = ff_find_device(); - if (ret < 0) { - _E("Do not support standard haptic device"); - return false; - } - ret = config_parse(VIBRATION_CONF_PATH, vibration_table_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_DURATION_CONF_PATH, ret); - ret = config_parse(VIBRATION_DURATION_CONF_PATH, vibration_duration_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_DURATION_CONF_PATH, ret); - ret = config_parse(VIBRATION_WAITING_CONF_PATH, vibration_waiting_load_config, NULL); - if (ret < 0) - _E("failed to load configuration file(%s) : %d", VIBRATION_WAITING_CONF_PATH, ret); - - _I("Support standard haptic device"); - return true; -} - -static const struct haptic_plugin_ops *load(void) -{ - return &default_plugin; -} - -static const struct haptic_ops std_ops = { - .type = HAPTIC_STANDARD, - .is_valid = is_valid, - .load = load, -}; - -HAPTIC_OPS_REGISTER(&std_ops) -- 2.7.4 From d5b1f88b401a759f55000e60529774847742a37f Mon Sep 17 00:00:00 2001 From: Hyotaek Shim Date: Fri, 29 Jun 2018 16:56:45 +0900 Subject: [PATCH 03/16] Minor fix: Type=Notify -> Type=notify Change-Id: I1a9c43235e9d063711ac8561cf01d932d27141cc Signed-off-by: Hyotaek Shim --- systemd/feedbackd.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/feedbackd.service b/systemd/feedbackd.service index e8071f7..5b412e6 100644 --- a/systemd/feedbackd.service +++ b/systemd/feedbackd.service @@ -3,7 +3,7 @@ Description=System Vibrator Daemon After=deviced.service [Service] -Type=Notify +Type=notify SmackProcessLabel=System ExecStart=/usr/bin/feedbackd Restart=always -- 2.7.4 From e2f013146add167d73520066fab1e7f977753ce2 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 9 Jul 2018 17:17:42 +0900 Subject: [PATCH 04/16] Check return value for vconf_notify_key_changed and vconf_ignore_key_changed Change-Id: I1213ecda36a2aa028ef5e7eade6d542309d1a8a2 Signed-off-by: pr.jung --- src/haptic/haptic.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 505a6de..818210c 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -824,8 +824,11 @@ void haptic_init(void) "", NULL); /* add watch for sound capturing value */ - if (haptic_conf.sound_capture) - vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL); + if (haptic_conf.sound_capture) { + r = vconf_notify_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb, NULL); + if (r != 0) + _W("Add watch for VCONFKEY_RECORDER_STATE failed"); + } /* Initialize vibration_handle (Use vibration now) */ cur_h_data.handle = INVALID_HANDLE; @@ -839,8 +842,11 @@ void haptic_exit(void) int r; /* remove watch */ - if (haptic_conf.sound_capture) - vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb); + if (haptic_conf.sound_capture) { + r = vconf_ignore_key_changed(VCONFKEY_RECORDER_STATE, sound_capturing_cb); + if (r != 0) + _W("Remove watch for VCONFKEY_RECORDER_STATE failed"); + } /* unregister notifier for below each event */ unsubscribe_dbus_signal(NULL, id_sig_change_hardkey); -- 2.7.4 From b620f8911b6748c805f0f485d5da6ad7ed1693de Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Wed, 28 Nov 2018 15:25:12 +0900 Subject: [PATCH 05/16] haptic: Request power lock before vibration - When device goes suspend mode after vibration started, vibration stops immediately. To prevent this, feedbackd request power lock during vibration time. Change-Id: I04bca81481c979ffaeb8d1676c33ec562841ab69 Signed-off-by: pr.jung --- CMakeLists.txt | 1 + packaging/feedbackd.spec | 1 + src/haptic/standard-vibcore.c | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eeb80b..ad93c9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,6 +40,7 @@ SET(PKG_MODULES capi-system-info libgdbus libsystemd + capi-system-device ) IF(DRIVER STREQUAL gpio) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index d33ccfb..0c9fc13 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -23,6 +23,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-peripheral-io) BuildRequires: pkgconfig(libgdbus) BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(capi-system-device) Requires(post): /usr/bin/vconftool diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index f8982c9..528875f 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -19,6 +19,7 @@ #include #include +#include #include "core/log.h" #include "core/list.h" @@ -30,6 +31,7 @@ struct vibration_config { char *pattern; + int pattern_duration; dd_list *data; }; @@ -67,6 +69,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) return -ENOMEM; } + conf->pattern_duration = 0; conf->pattern = strdup(result->name); if (!conf->pattern) { _E("fail to copy %s pattern data", result->name); @@ -111,6 +114,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) data->duration = strtol(value, NULL, 10); len = len - strlen(value) - 1; value = check + 1; + conf->pattern_duration += data->duration; } check = strchr(value, 'W'); @@ -119,6 +123,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) data->wait = strtol(value, NULL, 10); len = len - strlen(value) - 1; value = check + 1; + conf->pattern_duration += data->wait; } DD_LIST_APPEND(conf->data, data); @@ -227,6 +232,7 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback dd_list *elem; struct vibration_config *conf; size_t len; + int ret; if (device_handle < 0) return -EINVAL; @@ -250,6 +256,13 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback cur_h_data.priority = priority; cur_h_data.stop = false; _D("Play %s", conf->pattern); + + if (conf->pattern_duration <= 0) + break; + + ret = device_power_request_lock(POWER_LOCK_CPU, conf->pattern_duration); + if (ret != DEVICE_ERROR_NONE) + _E("Failed to request power lock"); haptic_duration_play((void *)&cur_h_data); break; } -- 2.7.4 From fcaf29164be7f6282671f3e4517cb2cb126ff3e7 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Thu, 27 Dec 2018 12:03:32 +0900 Subject: [PATCH 06/16] Remove executable flag from non-executable files Change-Id: I68327a8243aa96e13785dbfb7afd5c6a31344900 Signed-off-by: lokilee73 --- src/auto-test/haptic.c | 0 src/core/main.c | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/auto-test/haptic.c mode change 100755 => 100644 src/core/main.c diff --git a/src/auto-test/haptic.c b/src/auto-test/haptic.c old mode 100755 new mode 100644 diff --git a/src/core/main.c b/src/core/main.c old mode 100755 new mode 100644 -- 2.7.4 From 6f163ef5ccf32203c723ffd073088e49e597e4fa Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Fri, 4 Jan 2019 17:45:25 +0900 Subject: [PATCH 07/16] Parse and vibrate using standard pattern - Example) - FEEDBACK_PATTERN_NOTIFICATION_1=1,J_W - FEEDBACK_PATTERN_ALARM_1_STRONG_BUZZ=A,K_WB - 1: one time, A: unlimit(Vibrate until stop) - J_W, K_WB, and so on: standard pattern - Standard pattern is defined under /usr/share/feedback/vibration/xxx - Duration, Intensity, frequency, overdriving - Wait time, intensity(should be 0), frequency(Not used value), overdriving(Not used value) - Standard pattern example) 85,10000,205,0, 90,0,205,0, 105,10000,205,0, 0,end Change-Id: I5b6d6071983c8e8f4eaf9cd6cd9981ed906662de Signed-off-by: pr.jung --- src/haptic/circle.c | 6 +- src/haptic/gpio_haptic.c | 5 +- src/haptic/haptic.h | 1 + src/haptic/standard-vibcore.c | 372 +++++++++++++++++++++++++++++++++++------- src/haptic/standard-vibcore.h | 2 +- src/haptic/standard.c | 4 +- 6 files changed, 321 insertions(+), 69 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 1b63660..9c756e7 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -320,8 +320,6 @@ static const struct haptic_plugin_ops default_plugin = { static bool is_valid(void) { - int ret; - if ((access(CIRCLE_ON_PATH, R_OK) != 0) || (access(CIRCLE_OFF_PATH, R_OK) != 0)) { _E("Do not support wearable haptic device"); @@ -329,9 +327,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); state = true; _I("Support wearable haptic device"); diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index 45ffdac..3d91b5a 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -348,7 +348,6 @@ static bool is_valid(void) { uint8_t result; peripheral_i2c_h handle; - int ret; if (peripheral_i2c_open(GPIO_I2C_BUS_INDEX, DRV2605L_DEFAULT_ADDR, &handle) < PERIPHERAL_ERROR_NONE) { _E("Failed to open I2C"); @@ -368,9 +367,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); state = true; _I("Support gpio haptic device"); diff --git a/src/haptic/haptic.h b/src/haptic/haptic.h index 3f57723..7951d4b 100644 --- a/src/haptic/haptic.h +++ b/src/haptic/haptic.h @@ -60,6 +60,7 @@ struct haptic_data { int level; int priority; bool stop; + int unlimit; }; #define INVALID_HANDLE 0 diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 528875f..358942b 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -16,7 +16,9 @@ * limitations under the License. */ - +#include +#include +#include #include #include #include @@ -27,16 +29,35 @@ #include "haptic.h" #include "standard-vibcore.h" -#define VIBRATION_CONF_PATH "/usr/share/feedback/vibration.conf" +#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 VALUE_MAX_LEN 10 +#define VIB_LOCK_TIMEOUT_MAX (300000) /* 5minutes */ + +/* + 1,A_W or A,A_W or 250D250W250D750W + 85,10000,205,0, + 90,0,205,0, + 105,10000,205,0, + 0,end +*/ struct vibration_config { - char *pattern; + char *pattern; /* pattern name */ + char *standard; /* assigned standard pattern name */ + dd_list *data; /* duration_data list */ int pattern_duration; - dd_list *data; + int len; /* string length of pattern */ + int unlimit; }; struct duration_data { int duration; + int intensity; + int frequency; + int overdriving; int wait; }; @@ -45,10 +66,217 @@ 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; + + if (update->duration < 0 || update->intensity < 0 || update->frequency < 0 || update->overdriving < 0) + return 0; + + 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); + memset(update, 0, sizeof(struct duration_data)); + return 0; +} + +/* [A]xxxDxxxIxxxFxxxOxxxW format */ +static int insert_law_data_format(dd_list **conf_data, char *value) +{ + struct duration_data update; + int len = 0; + char *check; + int pattern_duration = 0; + + if (!value) { + memset(&update, 0, sizeof(struct duration_data)); + return insert_conf_data(conf_data, &update); + } + + len = strlen(value); + do { + memset(&update, 0, sizeof(struct duration_data)); + check = strchr(value, 'D'); + if (check) { + *check = '\0'; + update.duration = strtol(value, NULL, 10); + pattern_duration += update.duration; + if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("reached max pattern duration"); + pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + len = len - strlen(value) - 1; + value = check + 1; + check = strchr(value, 'I'); + if (check) { + *check = '\0'; + update.intensity = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + check = strchr(value, 'F'); + if (check) { + *check = '\0'; + update.frequency = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + check = strchr(value, 'O'); + if (check) { + *check = '\0'; + update.overdriving = strtol(value, NULL, 10); + len = len - strlen(value) - 1; + value = check + 1; + } + } + + check = strchr(value, 'W'); + if (check) { + *check = '\0'; + update.wait = strtol(value, NULL, 10); + pattern_duration += update.wait; + if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("reached max pattern duration"); + pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + len = len - strlen(value) - 1; + value = check + 1; + } + if (update.duration == 0 && update.wait == 0) + break; + if (insert_conf_data(conf_data, &update) < 0) + return -EINVAL; + } while (len > 0); + + return pattern_duration; +} + +/* + duration, intensity, frequency, overdriving + waiting duration, intensity=0, frequency, overdriving + 85,10000,205,0, + 90,0,205,0, + 105,10000,205,0, + 0,end +*/ +static int load_standard_format(char *pattern) +{ + struct vibration_config *conf; + struct duration_data update = {0, }; + bool packed = false; + int duration = 0, intensity = 0, ret = 0, count = 0, end = 2; + 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; + } + conf->len = strlen(conf->pattern) + 1; + + /* 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[ret] = '\0'; + ret = 0; + switch (count) { + case 1: /* D */ + duration = strtol(val, NULL, 10); + conf->pattern_duration += duration; + if (conf->pattern_duration > VIB_LOCK_TIMEOUT_MAX) { + _D("Reached max pattern duration"); + conf->pattern_duration = VIB_LOCK_TIMEOUT_MAX; + } + break; + case 2: /* I or W */ + intensity = strtol(val, NULL, 10); + if (!packed) { + update.duration = duration; + update.intensity = intensity; + break; + } + /* Intensity should be 0 for wait(off) time */ + if (intensity == 0) + update.wait = duration; + else + update.wait = 0; + packed = false; + + if (insert_conf_data(&conf->data, &update) < 0) + goto error_out; + break; + case 3: /* F */ + if (intensity != 0) + update.frequency = strtol(val, NULL, 10); + break; + case 4: /* O */ + count = 0; + if (intensity != 0) { + packed = true; + update.overdriving = strtol(val, NULL, 10); + } + break; + default: + break; + } + } else { + if (ret < (VALUE_MAX_LEN - 2)) + val[ret++] = elem; + } + } + close(fd); + DD_LIST_APPEND(vib_conf_list, conf); + return 0; + +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; - struct duration_data *data; char *value; char *check; int len; @@ -56,7 +284,9 @@ static int vibration_load_config(struct parse_result *result, void *user_data) if (!result) return 0; - if (!MATCH(result->section, "Vibration")) + if (!MATCH(result->section, "vibration") && + !MATCH(result->section, "Vibration") && + !MATCH(result->section, "VIBRATION")) return 0; @@ -73,72 +303,95 @@ static int vibration_load_config(struct parse_result *result, void *user_data) conf->pattern = strdup(result->name); if (!conf->pattern) { _E("fail to copy %s pattern data", result->name); - free(conf); - return -ENOMEM; + goto error_out; } + conf->len = strlen(conf->pattern) + 1; value = result->value; len = strlen(value); if (len == 0) { - data = (struct duration_data *)malloc(sizeof(struct duration_data)); - if (!data) { - _E("not enough memory"); - free(conf->pattern); - free(conf); - return -ENOMEM; - } - data->duration = 0; - data->wait = 0; - - DD_LIST_APPEND(conf->data, data); + if (insert_law_data_format(&conf->data, NULL) < 0) + goto error_out; DD_LIST_APPEND(vib_conf_list, conf); return 0; } - /* value : 100D or 100D0W or 250D250W250D750W*/ - do { - data = (struct duration_data *)malloc(sizeof(struct duration_data)); - if (!data) { - _E("not enough memory"); - free(conf->pattern); - free(conf); - return -ENOMEM; + /* 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; } - data->duration = 0; - data->wait = 0; + DD_LIST_APPEND(vib_conf_list, conf); + return 0; + } - check = strchr(value, 'D'); - if (check) { - *check = '\0'; - data->duration = strtol(value, NULL, 10); + /* 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; - conf->pattern_duration += data->duration; - } + value = check + 1; + } + conf->pattern_duration = insert_law_data_format(&conf->data, value); + if (conf->pattern_duration < 0) { + conf->pattern_duration = 0; + goto error_out; + } + DD_LIST_APPEND(vib_conf_list, conf); - check = strchr(value, 'W'); - if (check) { - *check = '\0'; - data->wait = strtol(value, NULL, 10); - len = len - strlen(value) - 1; - value = check + 1; - conf->pattern_duration += data->wait; - } + return 0; - DD_LIST_APPEND(conf->data, data); - if (data->duration == 0 && data->wait == 0) - break; - } while (len > 0); +error_out: + if (conf) { + if (conf->pattern) + free(conf->pattern); + if (conf->standard) + free(conf->standard); + } + return -ENOMEM; +} - DD_LIST_APPEND(vib_conf_list, conf); +static void load_standard_vibration_patterns(void) +{ + DIR *dir; + struct dirent *dent; - return 0; + 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; + load_standard_format(dent->d_name); + } + closedir(dir); + _D("Success to load %s", STANDARD_FILE_PATH); } -int standard_config_parse() +void standard_config_parse(void) { - return config_parse(VIBRATION_CONF_PATH, vibration_load_config, NULL); + 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) @@ -154,7 +407,7 @@ int standard_is_supported(const char *pattern) len = strlen(pattern) + 1; ret = 0; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) + if (!conf->pattern || conf->len != len) continue; if (!strncmp(conf->pattern, pattern, len)) { ret = true; @@ -227,11 +480,12 @@ int standard_set_vib_function(t_vibrate_monotone func) return 0; } -int standard_vibrate_effect(int device_handle, const char *pattern, int feedback, int priority) +int standard_vibrate_effect(int device_handle, const char *requested_pattern, int feedback, int priority) { dd_list *elem; struct vibration_config *conf; size_t len; + char pattern[PATH_MAX]; int ret; if (device_handle < 0) @@ -243,12 +497,18 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback return -EPERM; } + snprintf(pattern, sizeof(pattern), "%s", requested_pattern); len = strlen(pattern) + 1; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern) + if (!conf->pattern || conf->len != len) continue; if (strncmp(conf->pattern, pattern, len)) continue; + if (conf->standard) { + snprintf(pattern, sizeof(pattern), "%s", conf->standard); + len = strlen(pattern) + 1; + continue; + } cur_h_data.vibration_data = conf->data; cur_h_data.handle = device_handle; @@ -270,7 +530,7 @@ int standard_vibrate_effect(int device_handle, const char *pattern, int feedback return 0; } -int standard_vibrate_close() +int standard_vibrate_close(void) { cur_h_data.handle = INVALID_HANDLE; cur_h_data.priority = PRIORITY_MIN; diff --git a/src/haptic/standard-vibcore.h b/src/haptic/standard-vibcore.h index a55d7d2..0d4f254 100644 --- a/src/haptic/standard-vibcore.h +++ b/src/haptic/standard-vibcore.h @@ -22,7 +22,7 @@ typedef int (*t_vibrate_monotone)(int device_handle, int duration, int feedback, int priority, int *effect_handle); -int standard_config_parse(void); +void standard_config_parse(void); int standard_is_supported(const char *pattern); int standard_vibrate_effect(int device_handle, const char *pattern, int feedback, int priority); int standard_set_vib_function(t_vibrate_monotone func); diff --git a/src/haptic/standard.c b/src/haptic/standard.c index 6a42bd1..c0436fe 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -678,9 +678,7 @@ static bool is_valid(void) return false; } - ret = standard_config_parse(); - if (ret < 0) - _E("failed to load standard vibration configuration file : %d", ret); + standard_config_parse(); _I("Support standard haptic device"); return true; -- 2.7.4 From cdb9263aab9cc1a1d6c9584cbf20185215977214 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Tue, 8 Jan 2019 14:05:15 +0900 Subject: [PATCH 08/16] Check device_handle is the same with current vibration handle on close_device() - Check device_handle - Remove redundant operations Change-Id: If7597c20ace9b43d1bcbfb5017b983c15da00c7d Signed-off-by: pr.jung --- src/haptic/circle.c | 11 ----------- src/haptic/gpio_haptic.c | 11 ----------- src/haptic/standard.c | 16 +++------------- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 9c756e7..aa1b7a5 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -158,17 +158,6 @@ static int close_device(int device_handle) if (r < 0) _I("already stopped or failed to stop effect : %d", r); - /* unregister existing timer */ - if (r >= 0) { - _D("device handle %d is closed and timer deleted", device_handle); - if (stop_timer) { - g_source_remove(stop_timer); - stop_timer = 0; - } - } - - standard_vibrate_close(); - DD_LIST_REMOVE(handle_list, (gpointer)(long)device_handle); /* if it is the last element */ diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index 3d91b5a..c495d6c 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -188,17 +188,6 @@ static int gpio_haptic_close_device(int handle) if (r < 0) _I("already stopped or failed to stop effect : %d", r); - /* unregister existing timer */ - if (r >= 0) { - if (stop_timer) { - //ecore_timer_del(stop_timer); - g_source_remove(stop_timer); - stop_timer = 0; - } - } - - standard_vibrate_close(); - _D("handle %d is closed and timer deleted", handle); DD_LIST_REMOVE(handle_list, (gpointer)(long)handle); diff --git a/src/haptic/standard.c b/src/haptic/standard.c index c0436fe..dd162b2 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -75,6 +75,7 @@ static dd_list *handle_list; static char ff_path[PATH_MAX]; static int unique_number; +static int stop_device(int device_handle); struct ff_info *read_from_list(int handle) { struct ff_info *temp; @@ -358,7 +359,7 @@ static int open_device(int device_index, int *device_handle) static int close_device(int device_handle) { struct ff_info *info; - int r, n; + int n; info = read_from_list(device_handle); if (!info) @@ -371,18 +372,7 @@ static int close_device(int device_handle) return -ENODEV; /* stop vibration */ - r = ff_stop(ff_fd, &info->effect); - if (r < 0) - _I("already stopped or failed to stop effect : %d", r); - - /* unregister existing timer */ - if (r >= 0 && info->timer) { - _D("device handle %d is closed and timer deleted", device_handle); - g_source_remove(info->timer); - info->timer = 0; - } - - standard_vibrate_close(); + stop_device(device_handle); DD_LIST_REMOVE(handle_list, (gpointer)(long)info->handle); -- 2.7.4 From 02b9cb54b69adba2204951a67378867b954f3e29 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Tue, 8 Jan 2019 18:54:36 +0900 Subject: [PATCH 09/16] Add unlimit operation - Repeats vibration pattern when requested pattern is defined as an unlimit pattern Change-Id: I3eefc7eb73a386987b54d6bbf79848f9c7c66daf Signed-off-by: pr.jung --- src/haptic/standard-vibcore.c | 76 +++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 358942b..92bed2f 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -421,7 +421,6 @@ int standard_is_supported(const char *pattern) static gboolean haptic_duration_play(void *data) { dd_list *head, *n, *next; - struct haptic_data *h_data; struct duration_data *node; int ret = 0; @@ -431,44 +430,49 @@ static gboolean haptic_duration_play(void *data) } if (!data) { - cur_h_data.handle = INVALID_HANDLE; - cur_h_data.priority = PRIORITY_MIN; - goto out; - } + 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; - h_data = (struct haptic_data *)data; - if (h_data->stop) { - h_data->stop = false; + 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; } - head = h_data->vibration_data; DD_LIST_FOREACH_SAFE(head, n, next, node) { - _D("Play: %dms and Wait: %dms", node->duration, node->wait); - if (!node->duration) { - cur_h_data.handle = INVALID_HANDLE; - cur_h_data.priority = PRIORITY_MIN; - break; + _D("Handle %d play: %dms and Wait: %dms (with f:%d o:%d) %s type", + cur_h_data.handle, node->duration, node->wait, + node->frequency, node->overdriving, + 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 (next) { - h_data->vibration_data = next; - duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)h_data); - } else - duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, NULL); + duration_timer = g_timeout_add((node->duration + node->wait), haptic_duration_play, (void *)next); - ret = real_vibrate_monotone(h_data->handle, node->duration, h_data->level, h_data->priority, NULL); - if (!next) - goto out; + ret = real_vibrate_monotone(cur_h_data.handle, node->duration, cur_h_data.level, cur_h_data.priority, NULL); break; } if (ret != 0) { _D("auto stop vibration"); - if (h_data) - h_data->stop = true; + cur_h_data.stop = true; } out: return G_SOURCE_REMOVE; @@ -487,8 +491,9 @@ int standard_vibrate_effect(int device_handle, const char *requested_pattern, in size_t len; char pattern[PATH_MAX]; int ret; + int unlimit = 0; - if (device_handle < 0) + if (device_handle < 0 || !requested_pattern) return -EINVAL; /* Same or higher priority pattern should be played */ @@ -505,27 +510,36 @@ int standard_vibrate_effect(int device_handle, const char *requested_pattern, in if (strncmp(conf->pattern, pattern, len)) continue; if (conf->standard) { + unlimit = conf->unlimit; snprintf(pattern, sizeof(pattern), "%s", conf->standard); len = strlen(pattern) + 1; 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; - _D("Play %s", conf->pattern); + _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; - ret = device_power_request_lock(POWER_LOCK_CPU, conf->pattern_duration); - if (ret != DEVICE_ERROR_NONE) - _E("Failed to request power lock"); - haptic_duration_play((void *)&cur_h_data); - break; + if (!cur_h_data.unlimit && conf->pattern_duration > 0) { + ret = device_power_request_lock(POWER_LOCK_CPU, 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; } -- 2.7.4 From c9df1e784aa577a0db061db3dfd5a598db2fd565 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Thu, 10 Jan 2019 17:23:27 +0900 Subject: [PATCH 10/16] Add level configuration - Add 2 level configuration rpms: conf-level3, conf-level6 - Calculate level with intensity Change-Id: Ied3de559b9ac2dfb6c3e197dce98c44c4969c0c7 Signed-off-by: pr.jung --- CMakeLists.txt | 2 + packaging/feedbackd.spec | 35 +++++++++++++++- src/haptic/haptic.c | 97 ++++++++++++++++++++++++++++++++++++------- src/haptic/standard-vibcore.c | 11 ++++- 4 files changed, 128 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad93c9b..8950c06 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,5 +70,7 @@ INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/systemd/ DESTINATION lib/systemd/system FILES_MATCHING PATTERN "feedbackd.service") INSTALL(FILES ${CMAKE_SOURCE_DIR}/systemd/org.tizen.system.vibrator.service DESTINATION /usr/share/dbus-1/system-services) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/haptic/conf/haptic-level3.conf DESTINATION /etc/feedbackd) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/haptic/conf/haptic-level6.conf DESTINATION /etc/feedbackd) ADD_SUBDIRECTORY(src/auto-test) diff --git a/packaging/feedbackd.spec b/packaging/feedbackd.spec index 0c9fc13..6b801fc 100644 --- a/packaging/feedbackd.spec +++ b/packaging/feedbackd.spec @@ -30,6 +30,9 @@ Requires(post): /usr/bin/vconftool Requires: %{name}-compat = %{version}-%{release} Recommends: %{name}-driver-standard = %{version}-%{release} +Requires: configuration-compat = %{version}-%{release} +Recommends: %{name}-conf-level6 = %{version}-%{release} + %description feedback daemon @@ -91,6 +94,20 @@ Conflicts: %{name}-driver-standard %description driver-circle Feedbackd binaries with circle plugin. Required by main feedbackd package +%package conf-level3 +Summary: Feedbackd level configuration file +Provides: configuration-compat = %{version}-%{release} +Conflicts: %{name}-conf-level6 +%description conf-level3 +Feedbackd level configuration file. Required by main feedbackd package + +%package conf-level6 +Summary: Feedbackd level configuration file +Provides: configuration-compat = %{version}-%{release} +Conflicts: %{name}-conf-level3 +%description conf-level6 +Feedbackd level configuration file. Required by main feedbackd package + %package auto-test Summary: Feedbackd auto test tool Group: System/Utilities @@ -262,7 +279,13 @@ if [ "$1" == "0" ]; then systemctl stop feedbackd.service fi -%files -n feedbackd +%post conf-level3 +mv %{_sysconfdir}/feedbackd/haptic-level3.conf %{_sysconfdir}/feedbackd/haptic.conf + +%post conf-level6 +mv %{_sysconfdir}/feedbackd/haptic-level6.conf %{_sysconfdir}/feedbackd/haptic.conf + +%files -n feedbackd %manifest %{name}.manifest %license LICENSE.Apache-2.0 %config %{_sysconfdir}/dbus-1/system.d/feedbackd.conf @@ -295,6 +318,16 @@ fi %manifest %{name}.manifest %{_bindir}/feedbackd.circle +%files conf-level3 +%license LICENSE.Apache-2.0 +%manifest %{name}.manifest +%config %{_sysconfdir}/feedbackd/haptic-level3.conf + +%files conf-level6 +%license LICENSE.Apache-2.0 +%manifest %{name}.manifest +%config %{_sysconfdir}/feedbackd/haptic-level6.conf + %files auto-test %license LICENSE.Apache-2.0 %manifest %{name}.manifest diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 818210c..30cbaeb 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -33,6 +33,7 @@ #include "core/config-parser.h" #include "haptic.h" +#define HAPTIC_CONF_PATH "/etc/feedbackd/haptic.conf" #define SIGNAL_CHANGE_HARDKEY "ChangeHardkey" #define SIGNAL_POWEROFF_STATE "ChangeState" #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator" @@ -86,6 +87,8 @@ static enum haptic_type h_type; static bool haptic_disabled; struct haptic_config { + int level; + int *level_arr; int sound_capture; }; @@ -139,6 +142,27 @@ static int haptic_module_load(void) return 0; } +static int convert_magnitude_by_conf(int level) +{ + int i, step; + + if (level < LOW_FEEDBACK_LEVEL) + level = LOW_FEEDBACK_LEVEL; + else if (level > HIGH_FEEDBACK_LEVEL) + level = HIGH_FEEDBACK_LEVEL; + + step = 100 / (haptic_conf.level-1); + for (i = 0; i < haptic_conf.level; ++i) { + if (level <= i*step) { + _D("Level changed : %d -> %d", level, haptic_conf.level_arr[i]); + return haptic_conf.level_arr[i]; + } + } + + _D("Play default level"); + return DEFAULT_FEEDBACK_LEVEL * HAPTIC_FEEDBACK_STEP; +} + GVariant *hdbus_get_count(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) @@ -329,10 +353,12 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn, g_variant_get(param, "(uiii)", &handle, &duration, &level, &priority); - if (level < LOW_FEEDBACK_LEVEL) - level = LOW_FEEDBACK_LEVEL; - else if (level > HIGH_FEEDBACK_LEVEL) - level = HIGH_FEEDBACK_LEVEL; + /* convert as per conf value */ + level = convert_magnitude_by_conf(level); + if (level < 0) { + ret = -EINVAL; + goto exit; + } if (priority < PRIORITY_MIN) priority = PRIORITY_MIN; @@ -367,10 +393,12 @@ GVariant *hdbus_vibrate_buffer(GDBusConnection *conn, data = g_variant_get_fixed_array(pvar, &size, sizeof(char)); g_variant_unref(pvar); - if (level < LOW_FEEDBACK_LEVEL) - level = LOW_FEEDBACK_LEVEL; - else if (level > HIGH_FEEDBACK_LEVEL) - level = HIGH_FEEDBACK_LEVEL; + /* convert as per conf value */ + level = convert_magnitude_by_conf(level); + if (level < 0) { + ret = -EINVAL; + goto exit; + } ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle); if (ret >= 0) @@ -407,10 +435,12 @@ GVariant *hdbus_vibrate_effect(GDBusConnection *conn, g_variant_get(param, "(usii)", &handle, &pattern, &level, &priority); - if (level < LOW_FEEDBACK_LEVEL) - level = LOW_FEEDBACK_LEVEL; - else if (level > HIGH_FEEDBACK_LEVEL) - level = HIGH_FEEDBACK_LEVEL; + /* convert as per conf value */ + level = convert_magnitude_by_conf(level); + if (level < 0) { + ret = -EINVAL; + goto exit; + } if (priority < PRIORITY_MIN) priority = PRIORITY_MIN; else if (priority > PRIORITY_TOP) @@ -717,7 +747,6 @@ static void sound_capturing_cb(keynode_t *key, void *data) haptic_start(); } -/* Left for the case of sound_capture in use static int parse_section(struct parse_result *result, void *user_data, int index) { struct haptic_config *conf = (struct haptic_config *)user_data; @@ -730,6 +759,21 @@ static int parse_section(struct parse_result *result, void *user_data, int index if (MATCH(result->name, "sound_capture")) { conf->sound_capture = atoi(result->value); + } else if (MATCH(result->name, "level")) { + conf->level = atoi(result->value); + if (conf->level < 0 || conf->level >= INT_MAX - 1) { + _E("You must set level with positive number in integer range"); + return -EINVAL; + } + conf->level_arr = calloc(sizeof(int), conf->level); + if (!conf->level_arr) { + _E("failed to allocate memory for level"); + return -errno; + } + } else if (MATCH(result->name, "value")) { + if (index < 0) + return -EINVAL; + conf->level_arr[index] = atoi(result->value); } return 0; @@ -737,7 +781,10 @@ static int parse_section(struct parse_result *result, void *user_data, int index static int haptic_load_config(struct parse_result *result, void *user_data) { + struct haptic_config *conf = (struct haptic_config *)user_data; + char name[NAME_MAX]; int ret; + static int index; if (!result) return 0; @@ -755,10 +802,22 @@ static int haptic_load_config(struct parse_result *result, void *user_data) goto out; } + // Parsing 'level' section + for (index = 0; index < conf->level; ++index) { + snprintf(name, sizeof(name), "level%d", index); + if (MATCH(result->section, name)) { + ret = parse_section(result, user_data, index); + if (ret < 0) { + _E("failed to parse [level] section : %d", ret); + return ret; + } + goto out; + } + } + out: return 0; } -*/ static const dbus_method_s hdbus_methods[] = { { "GetCount", NULL, "i", hdbus_get_count }, @@ -800,6 +859,13 @@ void haptic_init(void) { int r; + /* get haptic data from configuration file */ + r = config_parse(HAPTIC_CONF_PATH, haptic_load_config, &haptic_conf); + if (r < 0) { + _E("failed to load configuration file(%s) : %d", HAPTIC_CONF_PATH, r); + safe_free(haptic_conf.level_arr); + } + /* init dbus interface */ r = dbus_handle_register_dbus_object(NULL, VIBRATOR_PATH_HAPTIC, &dbus_interface); if (r < 0) @@ -852,6 +918,9 @@ void haptic_exit(void) unsubscribe_dbus_signal(NULL, id_sig_change_hardkey); unsubscribe_dbus_signal(NULL, id_sig_pwr_off_state); + /* release haptic data memory */ + safe_free(haptic_conf.level_arr); + if (!CHECK_VALID_OPS(h_ops, r)) return; diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 92bed2f..0d8f5c0 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -33,6 +33,7 @@ #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 */ @@ -407,7 +408,7 @@ int standard_is_supported(const char *pattern) len = strlen(pattern) + 1; ret = 0; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern || conf->len != len) + if (!conf->pattern || conf->len != len) continue; if (!strncmp(conf->pattern, pattern, len)) { ret = true; @@ -422,6 +423,7 @@ static gboolean haptic_duration_play(void *data) { dd_list *head, *n, *next; struct duration_data *node; + int level; int ret = 0; if (duration_timer) { @@ -464,9 +466,14 @@ static gboolean haptic_duration_play(void *data) } } + 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, cur_h_data.level, cur_h_data.priority, NULL); + ret = real_vibrate_monotone(cur_h_data.handle, node->duration, level, cur_h_data.priority, NULL); break; } -- 2.7.4 From 3719296ebfe952a1aa6cbf0de064a628f370b9f2 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Fri, 11 Jan 2019 15:49:09 +0900 Subject: [PATCH 11/16] Add conf files - Add level3 and level6 conf files - Modify not to change the value of input parameter - Change strncmp to strcmp for pattern string comparison Change-Id: I1e2a00cb211fd6d1fb4fdf8b9ad72eaee86a65c1 Signed-off-by: pr.jung --- src/haptic/conf/haptic-level3.conf | 15 +++++++++++++++ src/haptic/conf/haptic-level6.conf | 24 ++++++++++++++++++++++++ src/haptic/standard-vibcore.c | 11 ++++------- src/haptic/standard.c | 1 + 4 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 src/haptic/conf/haptic-level3.conf create mode 100644 src/haptic/conf/haptic-level6.conf diff --git a/src/haptic/conf/haptic-level3.conf b/src/haptic/conf/haptic-level3.conf new file mode 100644 index 0000000..6e52318 --- /dev/null +++ b/src/haptic/conf/haptic-level3.conf @@ -0,0 +1,15 @@ +[Haptic] +# level +# how much does the vibration level to subdivide. +# The max value of vibration level fixed at 100. +# The min value of vibration level fixed at 0. +level=3 + +[level0] +value=0 + +[level1] +value=58 + +[level2] +value=100 diff --git a/src/haptic/conf/haptic-level6.conf b/src/haptic/conf/haptic-level6.conf new file mode 100644 index 0000000..84271f1 --- /dev/null +++ b/src/haptic/conf/haptic-level6.conf @@ -0,0 +1,24 @@ +[Haptic] +# level +# how much does the vibration level to subdivide. +# The max value of vibration level fixed at 100. +# The min value of vibration level fixed at 0. +level=6 + +[level0] +value=0 + +[level1] +value=20 + +[level2] +value=40 + +[level3] +value=60 + +[level4] +value=80 + +[level5] +value=100 diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 0d8f5c0..2a1cf3e 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -84,7 +84,6 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update) // to debug : // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdriving, data->wait); DD_LIST_APPEND(*conf_data, data); - memset(update, 0, sizeof(struct duration_data)); return 0; } @@ -240,6 +239,7 @@ static int load_standard_format(char *pattern) if (insert_conf_data(&conf->data, &update) < 0) goto error_out; + memset(&update, 0, sizeof(struct duration_data)); break; case 3: /* F */ if (intensity != 0) @@ -410,7 +410,7 @@ int standard_is_supported(const char *pattern) DD_LIST_FOREACH(vib_conf_list, elem, conf) { if (!conf->pattern || conf->len != len) continue; - if (!strncmp(conf->pattern, pattern, len)) { + if (!strcmp(conf->pattern, pattern)) { ret = true; break; } @@ -495,7 +495,6 @@ int standard_vibrate_effect(int device_handle, const char *requested_pattern, in { dd_list *elem; struct vibration_config *conf; - size_t len; char pattern[PATH_MAX]; int ret; int unlimit = 0; @@ -510,16 +509,14 @@ int standard_vibrate_effect(int device_handle, const char *requested_pattern, in } snprintf(pattern, sizeof(pattern), "%s", requested_pattern); - len = strlen(pattern) + 1; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern || conf->len != len) + if (!conf->pattern) continue; - if (strncmp(conf->pattern, pattern, len)) + if (strcmp(conf->pattern, pattern)) continue; if (conf->standard) { unlimit = conf->unlimit; snprintf(pattern, sizeof(pattern), "%s", conf->standard); - len = strlen(pattern) + 1; continue; } diff --git a/src/haptic/standard.c b/src/haptic/standard.c index dd162b2..d43f965 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -76,6 +76,7 @@ static char ff_path[PATH_MAX]; static int unique_number; static int stop_device(int device_handle); + struct ff_info *read_from_list(int handle) { struct ff_info *temp; -- 2.7.4 From 914f3bd32d606383f278e2e0897c1eda09d6fedb Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 21 Jan 2019 19:09:03 +0900 Subject: [PATCH 12/16] Fix svace issues - An integer underflow may occur due to arithmetic operation (unsigned subtraction) between values '0' and '1', where the first value comes from the expression 'len - strlen(value)' - An integer underflow may occur due to arithmetic operation (unsigned subtraction) between variable 'len' and value { [0, 4294967295] } of 'strlen(value)', when 'len' is in range { [1, 2147483647] } - Possible integer overflow: right operand is tainted. An integer overflow may occur due to arithmetic operation (addition) between value { [-2147483648, 2147483647] } and variable 'duration', where the value comes from 'conf->pattern_duration' and when 'duration' is tainted { [-2147483648, 2147483647] } - Simplifying loop in insert_raw_data_format Change-Id: I70d7e24b8473d22207ce0197c04eac97c155eadf Signed-off-by: pr.jung --- src/haptic/standard-vibcore.c | 190 ++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 101 deletions(-) diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 2a1cf3e..eb2403d 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -40,25 +40,22 @@ /* 1,A_W or A,A_W or 250D250W250D750W - 85,10000,205,0, - 90,0,205,0, - 105,10000,205,0, + 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 */ - int pattern_duration; - int len; /* string length of pattern */ + unsigned int pattern_duration; int unlimit; }; struct duration_data { int duration; int intensity; - int frequency; - int overdriving; int wait; }; @@ -71,7 +68,7 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update) { struct duration_data *data; - if (update->duration < 0 || update->intensity < 0 || update->frequency < 0 || update->overdriving < 0) + if (update->duration < 0 || update->intensity < 0) return 0; data = (struct duration_data *)calloc(1, sizeof(struct duration_data)); @@ -87,73 +84,63 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update) return 0; } +static void get_pattern_property(char **iter, char property, int *value) +{ + char *check = strchr(*iter, property); + long int val; + + if (!check) + return; + + *check = '\0'; + val = strtol(*iter, NULL, 10); + if (val < 0) + val = 0; + else if (val > VIB_LOCK_TIMEOUT_MAX) + val = VIB_LOCK_TIMEOUT_MAX; + + *value = (int)val; + + *iter = check + 1; +} /* [A]xxxDxxxIxxxFxxxOxxxW format */ -static int insert_law_data_format(dd_list **conf_data, char *value) +static int insert_raw_data_format(dd_list **conf_data, const char *value) { - struct duration_data update; - int len = 0; - char *check; + struct duration_data update = {0, }; + char *iter; + char *end; int pattern_duration = 0; - if (!value) { - memset(&update, 0, sizeof(struct duration_data)); + if (!value) return insert_conf_data(conf_data, &update); - } - len = strlen(value); - do { + iter = strdup(value); + end = iter + strlen(iter); + while (iter < end) { memset(&update, 0, sizeof(struct duration_data)); - check = strchr(value, 'D'); - if (check) { - *check = '\0'; - update.duration = strtol(value, NULL, 10); - pattern_duration += update.duration; - if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { - _D("reached max pattern duration"); - pattern_duration = VIB_LOCK_TIMEOUT_MAX; - } - len = len - strlen(value) - 1; - value = check + 1; - check = strchr(value, 'I'); - if (check) { - *check = '\0'; - update.intensity = strtol(value, NULL, 10); - len = len - strlen(value) - 1; - value = check + 1; - } - check = strchr(value, 'F'); - if (check) { - *check = '\0'; - update.frequency = strtol(value, NULL, 10); - len = len - strlen(value) - 1; - value = check + 1; - } - check = strchr(value, 'O'); - if (check) { - *check = '\0'; - update.overdriving = strtol(value, NULL, 10); - len = len - strlen(value) - 1; - value = check + 1; - } - } - check = strchr(value, 'W'); - if (check) { - *check = '\0'; - update.wait = strtol(value, NULL, 10); - pattern_duration += update.wait; - if (pattern_duration > VIB_LOCK_TIMEOUT_MAX) { - _D("reached max pattern duration"); - pattern_duration = VIB_LOCK_TIMEOUT_MAX; - } - len = len - strlen(value) - 1; - value = check + 1; - } + get_pattern_property(&iter, 'D', &update.duration); + if (update.duration > VIB_LOCK_TIMEOUT_MAX) + update.duration = VIB_LOCK_TIMEOUT_MAX; + 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.wait > VIB_LOCK_TIMEOUT_MAX) + update.wait = VIB_LOCK_TIMEOUT_MAX; + if (update.duration == 0 && update.wait == 0) 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; - } while (len > 0); + } return pattern_duration; } @@ -161,17 +148,19 @@ static int insert_law_data_format(dd_list **conf_data, char *value) /* duration, intensity, frequency, overdriving waiting duration, intensity=0, frequency, overdriving - 85,10000,205,0, - 90,0,205,0, - 105,10000,205,0, + 85,10000, + 90,0, + 105,10000, 0,end */ -static int load_standard_format(char *pattern) +static int load_standard_format(const char *pattern) { struct vibration_config *conf; struct duration_data update = {0, }; bool packed = false; - int duration = 0, intensity = 0, ret = 0, count = 0, end = 2; + long int duration = 0, intensity = 0; + int ret = 0, count = 0, end = 2; + int index = 0; int fd; char path[PATH_MAX], elem, val[VALUE_MAX_LEN] = {0, }; @@ -193,13 +182,12 @@ static int load_standard_format(char *pattern) ret = -errno; goto error_out; } - conf->len = strlen(conf->pattern) + 1; /* 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; + goto error_out; break; } if (elem == 'e' || elem == 'n' || elem == 'd') { @@ -212,22 +200,32 @@ static int load_standard_format(char *pattern) } if (elem == ',') { count++; - val[ret] = '\0'; - ret = 0; + val[index] = '\0'; + index = 0; switch (count) { case 1: /* D */ duration = strtol(val, NULL, 10); - conf->pattern_duration += duration; + if (duration < 0) + duration = 0; + else if (duration > VIB_LOCK_TIMEOUT_MAX) + duration = VIB_LOCK_TIMEOUT_MAX; + conf->pattern_duration += (int)duration; if (conf->pattern_duration > VIB_LOCK_TIMEOUT_MAX) { _D("Reached max pattern duration"); conf->pattern_duration = VIB_LOCK_TIMEOUT_MAX; } break; case 2: /* I or W */ + count = 0; intensity = strtol(val, NULL, 10); + if (intensity < 0) + intensity = 0; + else if (intensity > INTENSITY_BASE_RATE) + intensity = INTENSITY_BASE_RATE; if (!packed) { - update.duration = duration; - update.intensity = intensity; + update.duration = (int)duration; + update.intensity = (int)intensity; + packed = true; break; } /* Intensity should be 0 for wait(off) time */ @@ -241,28 +239,17 @@ static int load_standard_format(char *pattern) goto error_out; memset(&update, 0, sizeof(struct duration_data)); break; - case 3: /* F */ - if (intensity != 0) - update.frequency = strtol(val, NULL, 10); - break; - case 4: /* O */ - count = 0; - if (intensity != 0) { - packed = true; - update.overdriving = strtol(val, NULL, 10); - } - break; default: break; } } else { - if (ret < (VALUE_MAX_LEN - 2)) - val[ret++] = elem; + if (index < (VALUE_MAX_LEN - 2)) /* Temporal limit */ + val[index++] = elem; } } close(fd); DD_LIST_APPEND(vib_conf_list, conf); - return 0; + return ret; error_out: if (fd >= 0) @@ -281,6 +268,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) char *value; char *check; int len; + int duration; if (!result) return 0; @@ -306,13 +294,12 @@ static int vibration_load_config(struct parse_result *result, void *user_data) _E("fail to copy %s pattern data", result->name); goto error_out; } - conf->len = strlen(conf->pattern) + 1; value = result->value; len = strlen(value); if (len == 0) { - if (insert_law_data_format(&conf->data, NULL) < 0) + if (insert_raw_data_format(&conf->data, NULL) < 0) goto error_out; DD_LIST_APPEND(vib_conf_list, conf); return 0; @@ -346,11 +333,12 @@ static int vibration_load_config(struct parse_result *result, void *user_data) len = len - strlen(value) - 1; value = check + 1; } - conf->pattern_duration = insert_law_data_format(&conf->data, value); - if (conf->pattern_duration < 0) { + 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; @@ -369,6 +357,7 @@ static void load_standard_vibration_patterns(void) { DIR *dir; struct dirent *dent; + int ret; dir = opendir(STANDARD_FILE_PATH); if (!dir) { @@ -378,7 +367,9 @@ static void load_standard_vibration_patterns(void) while ((dent = readdir(dir))) { if (dent->d_type == DT_DIR) continue; - load_standard_format(dent->d_name); + 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); @@ -399,16 +390,14 @@ int standard_is_supported(const char *pattern) { dd_list *elem; struct vibration_config *conf; - size_t len; int ret; if (!pattern) return -EINVAL; - len = strlen(pattern) + 1; ret = 0; DD_LIST_FOREACH(vib_conf_list, elem, conf) { - if (!conf->pattern || conf->len != len) + if (!conf->pattern) continue; if (!strcmp(conf->pattern, pattern)) { ret = true; @@ -451,9 +440,8 @@ static gboolean haptic_duration_play(void *data) } DD_LIST_FOREACH_SAFE(head, n, next, node) { - _D("Handle %d play: %dms and Wait: %dms (with f:%d o:%d) %s type", + _D("Handle %d play: %dms and Wait: %dms %s type", cur_h_data.handle, node->duration, node->wait, - node->frequency, node->overdriving, cur_h_data.unlimit ? "Unlimit" : "Once"); if ((node->duration + node->wait) <= 0) { if (!cur_h_data.unlimit) { @@ -536,7 +524,7 @@ int standard_vibrate_effect(int device_handle, const char *requested_pattern, in break; if (!cur_h_data.unlimit && conf->pattern_duration > 0) { - ret = device_power_request_lock(POWER_LOCK_CPU, conf->pattern_duration); + ret = device_power_request_lock(POWER_LOCK_CPU, (int)conf->pattern_duration); if (ret != DEVICE_ERROR_NONE) _E("Failed to request power lock"); } -- 2.7.4 From 45d9dec31c7af129eded87785b53ad78d3556b51 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Thu, 24 Jan 2019 16:21:48 +0900 Subject: [PATCH 13/16] Change strtol to strtoul Change-Id: I65a94fcaf0fc4a737ffc64e498a9b2f9c3cc7379 Signed-off-by: pr.jung --- src/haptic/standard-vibcore.c | 132 ++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 57 deletions(-) diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index eb2403d..09ae445 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -68,9 +68,6 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update) { struct duration_data *data; - if (update->duration < 0 || update->intensity < 0) - return 0; - data = (struct duration_data *)calloc(1, sizeof(struct duration_data)); if (!data) { _E("not enough memory"); @@ -86,25 +83,29 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update) static void get_pattern_property(char **iter, char property, int *value) { - char *check = strchr(*iter, property); - long int val; + char *check; + unsigned long int val; + check = strchr(*iter, property); if (!check) return; *check = '\0'; - val = strtol(*iter, NULL, 10); - if (val < 0) + val = strtoul(*iter, NULL, 10); + if (errno == EINVAL || errno == ERANGE) { val = 0; - else if (val > VIB_LOCK_TIMEOUT_MAX) + _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, const char *value) +static int insert_raw_data_format(dd_list **conf_data, char *value) { struct duration_data update = {0, }; char *iter; @@ -113,24 +114,26 @@ static int insert_raw_data_format(dd_list **conf_data, const char *value) if (!value) return insert_conf_data(conf_data, &update); + if (!conf_data) { + _E("Invalid parameter: Configuration list is null"); + return -EINVAL; + } - iter = strdup(value); + iter = value; end = iter + strlen(iter); while (iter < end) { memset(&update, 0, sizeof(struct duration_data)); get_pattern_property(&iter, 'D', &update.duration); - if (update.duration > VIB_LOCK_TIMEOUT_MAX) - update.duration = VIB_LOCK_TIMEOUT_MAX; 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.wait > VIB_LOCK_TIMEOUT_MAX) - update.wait = VIB_LOCK_TIMEOUT_MAX; - if (update.duration == 0 && update.wait == 0) + 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) { @@ -145,6 +148,52 @@ static int insert_raw_data_format(dd_list **conf_data, const char *value) 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 paramger"); + 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 @@ -155,10 +204,9 @@ static int insert_raw_data_format(dd_list **conf_data, const char *value) */ static int load_standard_format(const char *pattern) { - struct vibration_config *conf; struct duration_data update = {0, }; bool packed = false; - long int duration = 0, intensity = 0; + struct vibration_config *conf; int ret = 0, count = 0, end = 2; int index = 0; int fd; @@ -200,51 +248,23 @@ static int load_standard_format(const char *pattern) } if (elem == ',') { count++; - val[index] = '\0'; + val[index] = 'C'; index = 0; - switch (count) { - case 1: /* D */ - duration = strtol(val, NULL, 10); - if (duration < 0) - duration = 0; - else if (duration > VIB_LOCK_TIMEOUT_MAX) - duration = VIB_LOCK_TIMEOUT_MAX; - conf->pattern_duration += (int)duration; - if (conf->pattern_duration > VIB_LOCK_TIMEOUT_MAX) { - _D("Reached max pattern duration"); - conf->pattern_duration = VIB_LOCK_TIMEOUT_MAX; - } - break; - case 2: /* I or W */ - count = 0; - intensity = strtol(val, NULL, 10); - if (intensity < 0) - intensity = 0; - else if (intensity > INTENSITY_BASE_RATE) - intensity = INTENSITY_BASE_RATE; - if (!packed) { - update.duration = (int)duration; - update.intensity = (int)intensity; - packed = true; - break; - } - /* Intensity should be 0 for wait(off) time */ - if (intensity == 0) - update.wait = duration; - else - update.wait = 0; - packed = false; + 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)); - break; - default: - break; - } + } 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); @@ -273,9 +293,7 @@ static int vibration_load_config(struct parse_result *result, void *user_data) if (!result) return 0; - if (!MATCH(result->section, "vibration") && - !MATCH(result->section, "Vibration") && - !MATCH(result->section, "VIBRATION")) + if (!MATCH(result->section, "Vibration")) return 0; -- 2.7.4 From 4b3066240ea114924d9c62464d76096ecbee2ef8 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 14 Jan 2019 16:45:07 +0900 Subject: [PATCH 14/16] Delete unused dbus methods - Delete "SaveBinary" - Delete "CreateEffect" Change-Id: I72674cb67ad7dd8cb5b8dd4beec36a2f805e4884 Signed-off-by: pr.jung --- src/haptic/circle.c | 28 --------- src/haptic/emulator.c | 41 ------------- src/haptic/gpio_haptic.c | 28 --------- src/haptic/haptic-plugin-intf.h | 4 -- src/haptic/haptic.c | 124 ------------------------------------- src/haptic/standard-vibcore.c | 2 +- src/haptic/standard.c | 132 ---------------------------------------- 7 files changed, 1 insertion(+), 358 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index aa1b7a5..30d3d0d 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -222,12 +222,6 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p return 0; } -static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - _E("Not support feature"); - return -EACCES; -} - static int stop_device(int device_handle) { int ret; @@ -272,24 +266,6 @@ static int get_device_state(int device_index, int *effect_state) *effect_state = state; return 0; } - -static int create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not support feature"); - return -EACCES; -} - -static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - _E("Not support feature"); - return -EACCES; -} - -static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not support feature"); - return -EACCES; -} /* END: Haptic Module APIs */ static const struct haptic_plugin_ops default_plugin = { @@ -297,14 +273,10 @@ static const struct haptic_plugin_ops default_plugin = { .open_device = open_device, .close_device = close_device, .vibrate_monotone = vibrate_monotone, - .vibrate_buffer = vibrate_buffer, .vibrate_effect = standard_vibrate_effect, .is_supported = standard_is_supported, .stop_device = stop_device, .get_device_state = get_device_state, - .create_effect = create_effect, - .get_buffer_duration = get_buffer_duration, - .convert_binary = convert_binary, }; static bool is_valid(void) diff --git a/src/haptic/emulator.c b/src/haptic/emulator.c index 4548952..fdcc2e2 100644 --- a/src/haptic/emulator.c +++ b/src/haptic/emulator.c @@ -83,20 +83,6 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p return 0; } -static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - dd_list *elem; - - elem = DD_LIST_FIND(handle_list, (gpointer)(long)device_handle); - if (!elem) - return -EINVAL; - - if (effect_handle) - *effect_handle = DEFAULT_EFFECT_HANDLE; - - return 0; -} - static int vibrate_effect(int device_handle, const char *pattern, int feedback, int priority) { dd_list *elem; @@ -132,29 +118,6 @@ static int get_device_state(int device_index, int *effect_state) return 0; } -static int create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not support feature"); - return -EACCES; -} - -static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - dd_list *elem; - - elem = DD_LIST_FIND(handle_list, (gpointer)(long)device_handle); - if (!elem) - return -EINVAL; - - _E("Not support feature"); - return -EACCES; -} - -static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not support feature"); - return -EACCES; -} /* END: Haptic Module APIs */ static const struct haptic_plugin_ops default_plugin = { @@ -162,14 +125,10 @@ static const struct haptic_plugin_ops default_plugin = { .open_device = open_device, .close_device = close_device, .vibrate_monotone = vibrate_monotone, - .vibrate_buffer = vibrate_buffer, .vibrate_effect = vibrate_effect, .is_supported = is_supported, .stop_device = stop_device, .get_device_state = get_device_state, - .create_effect = create_effect, - .get_buffer_duration = get_buffer_duration, - .convert_binary = convert_binary, }; static bool is_valid(void) diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index c495d6c..da213a3 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -292,30 +292,6 @@ static int gpio_haptic_get_device_state(int index, int *effect_state) *effect_state = state; return 0; } - -static int gpio_haptic_vibrate_buffer(int handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - _E("Not support feature"); - return -EACCES; -} - -static int gpio_haptic_create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not support feature"); - return -EACCES; -} - -static int gpio_haptic_get_buffer_duration(int handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - _E("Not support feature"); - return -EACCES; -} - -static int gpio_haptic_convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not support feature"); - return -EACCES; -} /* END: Haptic Module APIs */ static const struct haptic_plugin_ops default_plugin = { @@ -323,14 +299,10 @@ static const struct haptic_plugin_ops default_plugin = { .open_device = gpio_haptic_open_device, .close_device = gpio_haptic_close_device, .vibrate_monotone = gpio_haptic_vibrate_monotone, - .vibrate_buffer = gpio_haptic_vibrate_buffer, .vibrate_effect = standard_vibrate_effect, .is_supported = standard_is_supported, .stop_device = gpio_haptic_stop_device, .get_device_state = gpio_haptic_get_device_state, - .create_effect = gpio_haptic_create_effect, - .get_buffer_duration = gpio_haptic_get_buffer_duration, - .convert_binary = gpio_haptic_convert_binary, }; static bool is_valid(void) diff --git a/src/haptic/haptic-plugin-intf.h b/src/haptic/haptic-plugin-intf.h index 3565d71..f3d0e11 100644 --- a/src/haptic/haptic-plugin-intf.h +++ b/src/haptic/haptic-plugin-intf.h @@ -27,14 +27,10 @@ struct haptic_plugin_ops { int (*open_device) (int, int*); int (*close_device) (int); int (*vibrate_monotone) (int, int, int, int, int*); - int (*vibrate_buffer) (int, const unsigned char*, int, int, int, int*); int (*vibrate_effect) (int, const char*, int, int); int (*is_supported) (const char*); int (*stop_device) (int); int (*get_device_state) (int, int*); - int (*create_effect) (unsigned char*, int, const haptic_module_effect_element*, int); - int (*get_buffer_duration) (int, const unsigned char*, int*); - int (*convert_binary) (const unsigned char*, int, const char*); }; const struct haptic_plugin_ops *get_haptic_plugin_interface(); diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 30cbaeb..148d63f 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -373,41 +373,6 @@ exit: return g_variant_new("(i)", ret); } -GVariant *hdbus_vibrate_buffer(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - unsigned int handle; - const unsigned char *data = NULL; - GVariant *pvar = NULL; - gsize size = 0; - int iteration, level, priority, e_handle, ret = 0; - - if (!CHECK_VALID_OPS(h_ops, ret)) - goto exit; - - if (haptic_disabled) - goto exit; - - g_variant_get(param, "(u@ayiii)", &handle, &pvar, &iteration, &level, &priority); - data = g_variant_get_fixed_array(pvar, &size, sizeof(char)); - g_variant_unref(pvar); - - /* convert as per conf value */ - level = convert_magnitude_by_conf(level); - if (level < 0) { - ret = -EINVAL; - goto exit; - } - - ret = h_ops->vibrate_buffer(handle, data, iteration, level, priority, &e_handle); - if (ret >= 0) - ret = e_handle; - -exit: - return g_variant_new("(i)", ret); -} - static void vibrate_effect_idler_cb(void *data) { struct vibrate_effect_info *vibrate_info = (struct vibrate_effect_info *)data; @@ -511,91 +476,6 @@ exit: return g_variant_new("(i)", ret); } -GVariant *hdbus_create_effect(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - static unsigned char data[MAX_EFFECT_BUFFER]; - //static unsigned char *p = data; - const haptic_module_effect_element *elem_arr; - int i, cnt, ret, bufsize = sizeof(data); - GVariant *pvar = NULL; - gsize size = 0; - - if (!CHECK_VALID_OPS(h_ops, ret)) - goto exit; - - g_variant_get(param, "(i@ayi)", &bufsize, &pvar, &cnt); - elem_arr = g_variant_get_fixed_array(pvar, &size, sizeof(char)); - g_variant_unref(pvar); - - if (bufsize > MAX_EFFECT_BUFFER) { - ret = -ENOMEM; - goto exit; - } - - for (i = 0; i < cnt; ++i) - _D("[%2d] %d %d", i, elem_arr[i].haptic_duration, elem_arr[i].haptic_level); - - memset(data, 0, MAX_EFFECT_BUFFER); - ret = h_ops->create_effect(data, bufsize, elem_arr, cnt); - -exit: - pvar = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, data, sizeof(data), sizeof(char)); - return g_variant_new("(@ayi)", pvar, ret); -} - -GVariant *hdbus_get_duration(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - unsigned int handle; - const unsigned char *data; - int duration, ret; - GVariant *pvar = NULL; - gsize size = 0; - - if (!CHECK_VALID_OPS(h_ops, ret)) - goto exit; - - g_variant_get(param, "(u@ay)", &handle, &pvar); - data = g_variant_get_fixed_array(pvar, &size, sizeof(char)); - g_variant_unref(pvar); - - ret = h_ops->get_buffer_duration(handle, data, &duration); - if (ret >= 0) - ret = duration; - -exit: - return g_variant_new("(i)", ret); -} - -GVariant *hdbus_save_binary(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) - -{ - const unsigned char *data = NULL; - char *file_path = NULL; - int ret; - GVariant *pvar; - gsize size = 0; - - if (!CHECK_VALID_OPS(h_ops, ret)) - goto exit; - - g_variant_get(param, "(@ays)", &pvar, &file_path); - data = g_variant_get_fixed_array(pvar, &size, sizeof(char)); - g_variant_unref(pvar); - - _D("file path : %s", file_path); - ret = h_ops->convert_binary(data, size, file_path); - -exit: - g_free(file_path); - return g_variant_new("(i)", ret); -} - GVariant *hdbus_show_handle_list(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) @@ -825,12 +705,8 @@ static const dbus_method_s hdbus_methods[] = { { "CloseDevice", "u", "i", hdbus_close_device }, { "StopDevice", "u", "i", hdbus_stop_device }, { "VibrateMonotone", "uiii", "i", hdbus_vibrate_monotone }, - { "VibrateBuffer", "uayiii", "i", hdbus_vibrate_buffer }, { "VibrateEffect", "usii", "i", hdbus_vibrate_effect }, { "GetState", "i", "i", hdbus_get_state }, - { "GetDuration", "uay", "i", hdbus_get_duration }, - { "CreateEffect", "iayi", "ayi", hdbus_create_effect }, - { "SaveBinary", "ays", "i", hdbus_save_binary }, { "ShowHandleList", NULL, NULL, hdbus_show_handle_list }, { "IsSupported", "s", "i", hdbus_pattern_is_supported }, /* Add methods here */ diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 09ae445..3f4d851 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -159,7 +159,7 @@ static int get_config_data(int count, bool *packed, char *val, unsigned int *pat } if (!packed || !val || !pattern_duration || !update) { - _E("Invalid paramger"); + _E("Invalid parameter: %p %p %p %p", packed, val, pattern_duration, update); return -EINVAL; } diff --git a/src/haptic/standard.c b/src/haptic/standard.c index d43f965..c73840f 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -455,116 +455,6 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p return 0; } -static gboolean _buffer_play(void *cbdata) -{ - struct ff_info *info = (struct ff_info *)cbdata; - struct ff_info_header *header = &info->ffinfobuffer->header; - struct ff_info_data *data = info->ffinfobuffer->data; - int index = info->currentindex; - int play_type = (index < header->ff_info_data_count) ? data[index].type : 0; - int length = (index < header->ff_info_data_count) ? data[index].length : 1; - int ret; - - ff_set_effect(&info->effect, length, 1); - if (play_type != 0) { - _D("Going to play for %d ms", length); - ret = ff_play(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to play the effect %d", ret); - } else { - _D("Going to stop for %d ms", length); - ret = ff_stop(ff_fd, &info->effect); - if (ret < 0) - _D("Failed to stop the effect %d", ret); - } - - if (info->currentindex < header->ff_info_data_count) { - info->currentindex++; - info->timer = g_timeout_add(length, _buffer_play, info); - } else { - --header->iteration; - if (header->iteration > 0) { - info->currentindex = 0; - info->timer = g_timeout_add(0, _buffer_play, info); - } else - info->timer = 0; - } - - return G_SOURCE_REMOVE; -} - -static void print_buffer(const unsigned char *vibe_buffer) -{ - struct ff_info_buffer fb; - int i = 0; - memcpy(&fb.header, vibe_buffer, sizeof(struct ff_info_header)); - memcpy(&fb.data, (unsigned char *)vibe_buffer+sizeof(struct ff_info_header), - sizeof(struct ff_info_data) * fb.header.ff_info_data_count); - _D("\nMagic %x\niteration %d\ncount %d\n", fb.header.magic, - fb.header.iteration, fb.header.ff_info_data_count); - - for (i = 0; i < fb.header.ff_info_data_count; i++) - _D("type %d\nmagn 0x%x\nlen %d\n", fb.data[i].type, - fb.data[i].magnitude, fb.data[i].length); -} - -static int vibrate_custom_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - struct ff_info *info; - struct ff_info_header *header; - struct ff_info_data *data; - - info = read_from_list(device_handle); - if (!info) - return -EINVAL; - - if (!check_valid_handle(info)) - return -EINVAL; - - if (!check_fd(&ff_fd)) - return -ENODEV; - - if (!info->ffinfobuffer) - info->ffinfobuffer = (struct ff_info_buffer *)calloc(sizeof(struct ff_info_buffer), 1); - if (!info->ffinfobuffer) - return -ENOMEM; - - header = &info->ffinfobuffer->header; - data = info->ffinfobuffer->data; - - memcpy(header, vibe_buffer, sizeof(struct ff_info_header)); - if (header->ff_info_data_count < 0 || header->ff_info_data_count > MAX_DATA) - return -EINVAL; - - memcpy(data, vibe_buffer+sizeof(struct ff_info_header), sizeof(struct ff_info_data) * header->ff_info_data_count); - - info->currentindex = 0; - if (info->timer) - g_source_remove(info->timer); - - if (header->iteration > 0) - _buffer_play(info); - - return 0; -} - -static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle) -{ - int magic = 0; - - if (!device_handle) - return -EINVAL; - - if (vibe_buffer) - magic = *(int *)vibe_buffer; - - if (magic == FF_INFO_MAGIC) { - print_buffer(vibe_buffer); - return vibrate_custom_buffer(device_handle, vibe_buffer, iteration, feedback, priority, effect_handle); - } else - return vibrate_monotone(device_handle, 300, feedback, priority, effect_handle); -} - static int stop_device(int device_handle) { struct ff_info *info; @@ -624,24 +514,6 @@ static int get_device_state(int device_index, int *effect_state) *effect_state = status; return 0; } - -static int create_effect(unsigned char *vibe_buffer, int max_bufsize, const haptic_module_effect_element *elem_arr, int max_elemcnt) -{ - _E("Not support feature"); - return -EACCES; -} - -static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration) -{ - _E("Not support feature"); - return -EACCES; -} - -static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path) -{ - _E("Not support feature"); - return -EACCES; -} /* END: Haptic Module APIs */ static const struct haptic_plugin_ops default_plugin = { @@ -649,14 +521,10 @@ static const struct haptic_plugin_ops default_plugin = { .open_device = open_device, .close_device = close_device, .vibrate_monotone = vibrate_monotone, - .vibrate_buffer = vibrate_buffer, .vibrate_effect = standard_vibrate_effect, .is_supported = standard_is_supported, .stop_device = stop_device, .get_device_state = get_device_state, - .create_effect = create_effect, - .get_buffer_duration = get_buffer_duration, - .convert_binary = convert_binary, }; static bool is_valid(void) -- 2.7.4 From 879053e9b3e1b4b2bf571811fe8deb8ebcb7edf5 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Mon, 14 Jan 2019 17:37:24 +0900 Subject: [PATCH 15/16] Vibrate when poweroff_type is POWER_OFF_DIRECT or POWER_OFF_RESTART Change-Id: Ia7f222768ffc6c3413a00f90e4d40e3302802450 Signed-off-by: pr.jung --- src/haptic/haptic.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/haptic/haptic.c b/src/haptic/haptic.c index 148d63f..4a60b85 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -41,7 +41,6 @@ /* hardkey vibration variable */ #define HARDKEY_VIB_ITERATION 1 #define HARDKEY_VIB_FEEDBACK 3 -#define HARDKEY_VIB_PRIORITY 2 #define HARDKEY_VIB_DURATION 30 #define HAPTIC_FEEDBACK_STEP 20 #define DEFAULT_FEEDBACK_LEVEL 3 @@ -63,6 +62,13 @@ #define CHECK_VALID_OPS(ops, r) ((ops) ? true : !(r = -ENODEV)) #define RETRY_CNT 3 +enum poweroff_type { + POWER_OFF_NONE = 0, + POWER_OFF_POPUP, + POWER_OFF_DIRECT, + POWER_OFF_RESTART, +}; + struct haptic_info { char *sender; dd_list *handle_list; @@ -573,7 +579,7 @@ static void haptic_hardkey_changed_cb(GDBusConnection *conn, } ret = h_ops->vibrate_monotone(g_handle, HARDKEY_VIB_DURATION, - level*HAPTIC_FEEDBACK_STEP, HARDKEY_VIB_PRIORITY, &e_handle); + level*HAPTIC_FEEDBACK_STEP, PRIORITY_HIGH, &e_handle); if (ret < 0) _E("fail to vibrate buffer : %d", ret); @@ -588,9 +594,17 @@ static void haptic_poweroff_cb(GDBusConnection *conn, GVariant *param, gpointer data) { + int type = POWER_OFF_NONE; int e_handle, ret; struct timespec time = {0,}; + g_variant_get(param, "(i)", &type); + + if (type != POWER_OFF_DIRECT && type != POWER_OFF_RESTART) + return; + + _D("Poweroff: %d", type); + if (!CHECK_VALID_OPS(h_ops, ret)) { ret = haptic_module_load(); if (ret < 0) @@ -601,8 +615,10 @@ static void haptic_poweroff_cb(GDBusConnection *conn, haptic_internal_init(); /* power off vibration */ + _I("Handle %d dur %dms pri %d level %d", + g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, POWER_VIB_FEEDBACK); ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, - POWER_VIB_FEEDBACK, HARDKEY_VIB_PRIORITY, &e_handle); + POWER_VIB_FEEDBACK, PRIORITY_HIGH, &e_handle); if (ret < 0) { _E("fail to vibrate_monotone : %d", ret); return; -- 2.7.4 From 2ac7e22abdf003279401415233c4b3af6598d003 Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Wed, 16 Jan 2019 15:30:24 +0900 Subject: [PATCH 16/16] Use idler callback for VibrateMonotone - Return immdiately after parameters checked Change-Id: I21b37f0eeb7c7a99454039a8004a97724c064c43 Signed-off-by: pr.jung --- src/haptic/circle.c | 6 +-- src/haptic/emulator.c | 7 +-- src/haptic/external.c | 6 ++- src/haptic/gpio_haptic.c | 5 +- src/haptic/haptic-plugin-intf.h | 2 +- src/haptic/haptic.c | 61 ++++++++++++++++++++---- src/haptic/haptic.h | 1 + src/haptic/standard-vibcore.c | 3 +- src/haptic/standard-vibcore.h | 2 +- src/haptic/standard.c | 102 +++++++++++++++++++++++++--------------- 10 files changed, 128 insertions(+), 67 deletions(-) diff --git a/src/haptic/circle.c b/src/haptic/circle.c index 30d3d0d..f17007a 100644 --- a/src/haptic/circle.c +++ b/src/haptic/circle.c @@ -177,7 +177,7 @@ static int close_device(int device_handle) return 0; } -static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +static int vibrate_monotone(int device_handle, int duration, int feedback, int priority) { int ret; char buf[BUF_SIZE]; @@ -212,12 +212,10 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p stop_timer = g_timeout_add(duration, timer_cb, (void *)(long)device_handle); if (!stop_timer) - _E("Failed to add timer callback"); + _E("Handle %d Failed to add timer callback", device_handle); } _D("device handle %d %dms", device_handle, duration); - if (effect_handle) - *effect_handle = device_handle; return 0; } diff --git a/src/haptic/emulator.c b/src/haptic/emulator.c index fdcc2e2..326444c 100644 --- a/src/haptic/emulator.c +++ b/src/haptic/emulator.c @@ -24,8 +24,6 @@ #include "core/list.h" #include "haptic.h" -#define DEFAULT_EFFECT_HANDLE 0xFFFA - static dd_list *handle_list; static int unique_number = 0; @@ -69,7 +67,7 @@ static int close_device(int device_handle) return 0; } -static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +static int vibrate_monotone(int device_handle, int duration, int feedback, int priority) { dd_list *elem; @@ -77,9 +75,6 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p if (!elem) return -EINVAL; - if (effect_handle) - *effect_handle = DEFAULT_EFFECT_HANDLE; - return 0; } diff --git a/src/haptic/external.c b/src/haptic/external.c index 32eb6b3..3e4b4e0 100644 --- a/src/haptic/external.c +++ b/src/haptic/external.c @@ -36,10 +36,12 @@ static const struct haptic_plugin_ops *plugin_intf; static bool is_valid(void) { struct stat buf; + int ret; const struct haptic_plugin_ops *(*get_haptic_plugin_interface) () = NULL; - if (stat(HAPTIC_MODULE_PATH, &buf)) { - _E("file(%s) is not presents", HAPTIC_MODULE_PATH); + ret = stat(HAPTIC_MODULE_PATH, &buf); + if (ret < 0) { + _E("stat file(%s) error : %d", HAPTIC_MODULE_PATH, errno); goto error; } diff --git a/src/haptic/gpio_haptic.c b/src/haptic/gpio_haptic.c index da213a3..8b7ff7b 100644 --- a/src/haptic/gpio_haptic.c +++ b/src/haptic/gpio_haptic.c @@ -206,7 +206,7 @@ static int gpio_haptic_close_device(int handle) return 0; } -static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int priority, int *e_handle) +static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int priority) { bool found; @@ -243,9 +243,6 @@ static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int } _D("device handle %d %dms", handle, duration); - if (e_handle) - *e_handle = handle; - return 0; } diff --git a/src/haptic/haptic-plugin-intf.h b/src/haptic/haptic-plugin-intf.h index f3d0e11..cd6c6bf 100644 --- a/src/haptic/haptic-plugin-intf.h +++ b/src/haptic/haptic-plugin-intf.h @@ -26,7 +26,7 @@ struct haptic_plugin_ops { int (*get_device_count) (int*); int (*open_device) (int, int*); int (*close_device) (int); - int (*vibrate_monotone) (int, int, int, int, 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 4a60b85..b01cd96 100644 --- a/src/haptic/haptic.c +++ b/src/haptic/haptic.c @@ -82,6 +82,13 @@ struct vibrate_effect_info { int priority; }; +struct vibrate_monotone_info { + unsigned int handle; + int duration; + int level; + int priority; +}; + /* for playing */ static int g_handle; @@ -219,6 +226,11 @@ static struct haptic_info *add_haptic_info(const char *sender) return NULL; info->sender = strdup(sender); + if (!info->sender) { + free(info); + return NULL; + } + DD_LIST_APPEND(haptic_handle_list, info); info->id_watch = dbus_handle_watch_name(sender, NULL, haptic_name_owner_changed, info, NULL); @@ -344,12 +356,26 @@ exit: return g_variant_new("(i)", ret); } +static void vibrate_monotone_idler_cb(void *data) +{ + struct vibrate_monotone_info *vibrate_info = (struct vibrate_monotone_info *)data; + int ret; + + 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(vibrate_info->handle, vibrate_info->duration, + vibrate_info->level, vibrate_info->priority); + free(vibrate_info); +} + GVariant *hdbus_vibrate_monotone(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { + struct vibrate_monotone_info *vibrate_info; unsigned int handle; - int duration, level, priority, e_handle, ret = 0; + int duration, level, priority, ret = 0; if (!CHECK_VALID_OPS(h_ops, ret)) goto exit; @@ -371,10 +397,25 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn, else if (priority > PRIORITY_TOP) priority = PRIORITY_TOP; - ret = h_ops->vibrate_monotone(handle, duration, level, priority, &e_handle); - if (ret >= 0) - ret = e_handle; + if (duration <= 0) { + _E("Skip vibrate handle %d requested less than 0", handle); + ret = -EINVAL; + goto exit; + } + + vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info)); + if (!vibrate_info) { + _E("failed to allocate memory for vibrate_info"); + ret = -errno; + goto exit; + } + + vibrate_info->handle = handle; + vibrate_info->duration = duration; + vibrate_info->level = level; + vibrate_info->priority = priority; + ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info); exit: return g_variant_new("(i)", ret); } @@ -452,8 +493,10 @@ GVariant *hdbus_stop_device(GDBusConnection *conn, if (!CHECK_VALID_OPS(h_ops, ret)) goto exit; - if (haptic_disabled) + if (haptic_disabled) { + _I("Haptic disabled"); goto exit; + } g_variant_get(param, "(u)", &handle); @@ -548,7 +591,7 @@ static void haptic_hardkey_changed_cb(GDBusConnection *conn, GVariant *param, gpointer data) { - int level, status, e_handle, ret; + int level, status, ret; if (!CHECK_VALID_OPS(h_ops, ret)) { ret = haptic_module_load(); @@ -579,7 +622,7 @@ static void haptic_hardkey_changed_cb(GDBusConnection *conn, } ret = h_ops->vibrate_monotone(g_handle, HARDKEY_VIB_DURATION, - level*HAPTIC_FEEDBACK_STEP, PRIORITY_HIGH, &e_handle); + level*HAPTIC_FEEDBACK_STEP, PRIORITY_HIGH); if (ret < 0) _E("fail to vibrate buffer : %d", ret); @@ -595,7 +638,7 @@ static void haptic_poweroff_cb(GDBusConnection *conn, gpointer data) { int type = POWER_OFF_NONE; - int e_handle, ret; + int ret; struct timespec time = {0,}; g_variant_get(param, "(i)", &type); @@ -618,7 +661,7 @@ static void haptic_poweroff_cb(GDBusConnection *conn, _I("Handle %d dur %dms pri %d level %d", g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, POWER_VIB_FEEDBACK); ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, - POWER_VIB_FEEDBACK, PRIORITY_HIGH, &e_handle); + POWER_VIB_FEEDBACK, PRIORITY_HIGH); if (ret < 0) { _E("fail to vibrate_monotone : %d", ret); return; diff --git a/src/haptic/haptic.h b/src/haptic/haptic.h index 7951d4b..c77d64c 100644 --- a/src/haptic/haptic.h +++ b/src/haptic/haptic.h @@ -20,6 +20,7 @@ #ifndef __FEEDBACKD_HAPTIC_H__ #define __FEEDBACKD_HAPTIC_H__ +#include #include #include "core/common.h" #include "core/list.h" diff --git a/src/haptic/standard-vibcore.c b/src/haptic/standard-vibcore.c index 3f4d851..3e7d0d1 100644 --- a/src/haptic/standard-vibcore.c +++ b/src/haptic/standard-vibcore.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "core/log.h" #include "core/list.h" @@ -479,7 +478,7 @@ static gboolean haptic_duration_play(void *data) 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, NULL); + ret = real_vibrate_monotone(cur_h_data.handle, node->duration, level, cur_h_data.priority); break; } diff --git a/src/haptic/standard-vibcore.h b/src/haptic/standard-vibcore.h index 0d4f254..5f731ba 100644 --- a/src/haptic/standard-vibcore.h +++ b/src/haptic/standard-vibcore.h @@ -20,7 +20,7 @@ #ifndef __FEEDBACKD_STANDARD_VIBCORE_H__ #define __FEEDBACKD_STANDARD_VIBCORE_H__ -typedef int (*t_vibrate_monotone)(int device_handle, int duration, int feedback, int priority, int *effect_handle); +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); diff --git a/src/haptic/standard.c b/src/haptic/standard.c index c73840f..4831c06 100644 --- a/src/haptic/standard.c +++ b/src/haptic/standard.c @@ -119,21 +119,25 @@ static bool check_fd(int *fd) return true; } -static int ff_stop(int fd, struct ff_effect *effect); +static int ff_stop(const char *func, int fd, struct ff_effect *effect); static gboolean timer_cb(void *data) { struct ff_info *info = (struct ff_info *)data; - if (!info) + if (!info) { + _E("Failed to check info"); return G_SOURCE_REMOVE; + } - if (!check_valid_handle(info)) + if (!check_valid_handle(info)) { + _E("Failed to check valied info"); return G_SOURCE_REMOVE; + } _I("stop vibration by timer : id(%d)", info->effect.id); /* stop previous vibration */ - ff_stop(ff_fd, &info->effect); + ff_stop(__func__, ff_fd, &info->effect); /* reset timer */ info->timer = 0; @@ -165,8 +169,10 @@ static int ff_find_device(void) snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name); fd = open(ev_path, O_RDWR); - if (fd < 0) + if (fd < 0) { + _E("Failed to open %s(%d)", ev_path, errno); continue; + } /* get force feedback device */ memset(features, 0, sizeof(features)); @@ -236,22 +242,22 @@ static int ff_set_effect(struct ff_effect *effect, int length, int level) return 0; } -static int ff_play(int fd, struct ff_effect *effect) +static int ff_play(const char *func, int fd, struct ff_effect *effect) { struct input_event play; int ret; if (fd < 0 || !effect) { if (fd < 0) - _E("fail to check fd"); + _E("%s: failed to check fd", func); else - _E("fail to check effect"); + _E("%s: failed to check effect", func); return -EINVAL; } /* upload an effect */ if (ioctl(fd, EVIOCSFF, effect) == -1) { - _E("fail to ioctl"); + _E("%s: failed to ioctl", func); return -errno; } @@ -262,19 +268,19 @@ static int ff_play(int fd, struct ff_effect *effect) ret = write(fd, (const void *)&play, sizeof(play)); if (ret == -1) { - _E("fail to write"); + _E("%s: failed to write", func); return -errno; } return 0; } -static int ff_stop(int fd, struct ff_effect *effect) +static int ff_stop(const char *func, int fd, struct ff_effect *effect) { struct input_event stop; int ret; - if (fd < 0) + if (fd < 0 || !effect) return -EINVAL; /* Stop vibration */ @@ -363,14 +369,20 @@ static int close_device(int device_handle) int n; info = read_from_list(device_handle); - if (!info) - return -EINVAL; + if (!info) { + _E("Handle %d failed to check info", device_handle); + return -ENOENT; /* 2 */ + } - if (!check_valid_handle(info)) - return -EINVAL; + if (!check_valid_handle(info)) { + _E("Handle %d failed to check valid handle", device_handle); + return -EINVAL; /* 22 */ + } - if (!check_fd(&ff_fd)) - return -ENODEV; + if (!check_fd(&ff_fd)) { + _E("Handle %d failed to check fd", device_handle); + return -ENODEV; /* 19 */ + } /* stop vibration */ stop_device(device_handle); @@ -394,32 +406,42 @@ static int close_device(int device_handle) return 0; } -static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle) +static int vibrate_monotone(int device_handle, int duration, int feedback, int priority) { struct ff_info *info; 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; + } + info = read_from_list(device_handle); if (!info) { - _E("fail to check list"); + _E("Handle %d failed to check list", device_handle); return -EINVAL; } if (!check_valid_handle(info)) { - _E("fail to check handle"); + _E("Handle %d failed to check handle", device_handle); return -EINVAL; } if (!check_fd(&ff_fd)) return -ENODEV; + if (duration <= 0) { + _I("Handle %d skip requests with duration 0", device_handle); + return 0; + } + /* Zero(0) is the infinitely vibration value */ if (duration == HAPTIC_MODULE_DURATION_UNLIMITED) duration = 0; /* unregister existing timer */ if (info->timer) { - ff_stop(ff_fd, &info->effect); + ff_stop(__func__, ff_fd, &info->effect); g_source_remove(info->timer); info->timer = 0; } @@ -428,16 +450,16 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p ff_init_effect(&info->effect); ret = ff_set_effect(&info->effect, duration, feedback); if (ret < 0) { - _E("failed to set effect(duration:%d, feedback:%d) : %d", - duration, feedback, ret); + _E("Handle %d fail to set effect(duration:%d, feedback:%d) : %d", + device_handle, duration, feedback, ret); return ret; } /* play effect as per arguments */ - ret = ff_play(ff_fd, &info->effect); + ret = ff_play(__func__, ff_fd, &info->effect); if (ret < 0) { - _E("failed to play haptic effect(fd:%d id:%d) : %d", - ff_fd, info->effect.id, ret); + _E("Handle %d fail to play haptic effect(fd:%d id:%d) : %d", + device_handle, ff_fd, info->effect.id, ret); return ret; } @@ -445,12 +467,10 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p if (duration) { info->timer = g_timeout_add(duration, timer_cb, info); if (!info->timer) - _E("Failed to add timer callback"); + _E("Handle %d failed to add timer callback", device_handle); } - _D("device handle %d effect id : %d %dms", device_handle, info->effect.id, duration); - if (effect_handle) - *effect_handle = info->effect.id; + _D("Handle %d effect id : %d %dms", device_handle, info->effect.id, duration); return 0; } @@ -461,14 +481,20 @@ static int stop_device(int device_handle) int r; info = read_from_list(device_handle); - if (!info) - return -EINVAL; + if (!info) { + _E("Handle %d fail to check info", device_handle); + return -ENOENT; /* 2 */ + } - if (!check_valid_handle(info)) - return -EINVAL; + if (!check_valid_handle(info)) { + _E("Handle %d fail to check handle", device_handle); + return -EINVAL; /* 22 */ + } - if (!check_fd(&ff_fd)) - return -ENODEV; + if (!check_fd(&ff_fd)) { + _E("Handle %d fail to check fd", device_handle); + return -ENODEV; /* 19 */ + } if (cur_h_data.handle > 0 && cur_h_data.handle != info->handle) { _E("Only same handle can stop current vibration"); @@ -479,7 +505,7 @@ static int stop_device(int device_handle) standard_vibrate_close(); /* stop effect */ - r = ff_stop(ff_fd, &info->effect); + r = ff_stop(__func__, ff_fd, &info->effect); if (r < 0) _E("failed to stop effect(id:%d) : %d", info->effect.id, r); else -- 2.7.4