+++ /dev/null
-/*
- * 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 <stdio.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <linux/input.h>
-
-#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(x))
-#define LONG(x) ((x)/BITS_PER_LONG)
-#define test_bit(bit, array) ((array[LONG(bit)] >> 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)