standard: Support multi effect pattern 78/227178/1 accepted/tizen/5.5/unified/20200311.131011 submit/tizen_5.5/20200311.031543
authorYunmi Ha <yunmi.ha@samsung.com>
Mon, 17 Feb 2020 10:05:07 +0000 (19:05 +0900)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Tue, 10 Mar 2020 06:56:22 +0000 (06:56 +0000)
- Remove rescaling code of level
- Add intensity, overdrive, frequency parameters for play
- Change rumble structure interface with kernel

Change-Id: I68a5862ee19f7278e6b15cf947258605d299ae17
Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
(cherry picked from commit 5ee0ad79431301ce2b235759c2a1c83a4f626018)

src/haptic/circle.c
src/haptic/emulator.c
src/haptic/gpio_haptic.c
src/haptic/haptic-plugin-intf.h
src/haptic/haptic.c
src/haptic/standard.c

index 02a8760..42fa1f7 100644 (file)
@@ -180,7 +180,7 @@ static int close_device(int device_handle)
        return 0;
 }
 
-static int vibrate_monotone(int device_handle, int duration, int feedback, int priority)
+static int vibrate_monotone(int device_handle, int duration, int frequency, int overdrive, int level, int intensity, int priority)
 {
        int ret;
        char buf[BUF_SIZE];
index 31496e9..21b1dee 100644 (file)
@@ -67,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)
+static int vibrate_monotone(int device_handle, int duration, int frequency, int overdrive, int level, int intensity, int priority)
 {
        dd_list *elem;
 
index 29b8134..2ba2b88 100644 (file)
@@ -67,6 +67,9 @@
 #define LRA_LIBRARY_E          6
 #define TS2200_LIBRARY_F       7
 
+#define MAX_LEVEL              2
+#define MAX_INTENSITY  10000
+
 static peripheral_i2c_h device_handle = NULL;
 
 static dd_list *handle_list;
@@ -205,9 +208,14 @@ static int gpio_haptic_close_device(int handle)
        return 0;
 }
 
-static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int priority)
+static int gpio_haptic_vibrate_monotone(int handle, int duration, int frequency, int overdrive, int level, int intensity, int priority)
 {
        bool found;
+       int feedback;
+       int max_level;
+
+       if (level <= 0)
+               return -EINVAL;
 
        found = find_from_list(handle);
        if (!found)
@@ -227,11 +235,17 @@ static int gpio_haptic_vibrate_monotone(int handle, int duration, int level, int
        if (stop_timer)
                gpio_haptic_stop_device(handle);
 
+       max_level = (level <= MAX_LEVEL)? MAX_LEVEL: level;
+       if (intensity)
+               feedback = ((level/max_level) * intensity) / 100;
+       else
+               feedback = ((level/max_level) * MAX_INTENSITY) / 100;
+
        /* play vibration */
        peripheral_i2c_write_register_byte(device_handle, DRV2605L_REGISTER_LIBRARY, TS2200_LIBRARY_A);
        /* continuously vibrate*/
        peripheral_i2c_write_register_byte(device_handle, DRV2605L_REGISTER_MODE, MODE_REALTIME_PLAYBACK);
-       peripheral_i2c_write_register_byte(device_handle, DRV2605L_REGISTER_RTPINPUT, (uint8_t)level);
+       peripheral_i2c_write_register_byte(device_handle, DRV2605L_REGISTER_RTPINPUT, (uint8_t)feedback);
 
        /* register timer */
        if (duration) {
index 4c039a7..119c471 100644 (file)
@@ -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 (*vibrate_monotone) (int, int, int, int, int, int, int);
        int (*stop_device) (int);
 };
 
index fa2e33c..bf7410c 100644 (file)
@@ -37,6 +37,8 @@
 #define STANDARD_FILE_PATH         FEEDBACK_BASE_PATH"vibration/"
 #define VIBRATION_CONF_PATH        FEEDBACK_BASE_PATH"vibration.conf"
 
+#define PATTERN_DEFAULT_MONOTONE       "FEEDBACK_PATTERN_DEFAULT"
+
 #define HAPTIC_CONF_PATH                "/etc/feedbackd/haptic.conf"
 #define SIGNAL_POWEROFF_STATE           "ChangeState"
 #define SIGNAL_VIBRATOR_INITIATED       "InitiateVibrator"
@@ -88,6 +90,8 @@ struct vibration_config {
 struct duration_data {
        int duration;
        int intensity;
+       int frequency;
+       int overdrive;
        int wait;
 };
 
@@ -115,6 +119,7 @@ struct vibrate_monotone_info {
        unsigned int handle;
        int duration;
        int level;
+       int intensity;
        int priority;
 };
 
@@ -140,6 +145,7 @@ struct haptic_config {
 };
 
 static struct haptic_config haptic_conf;
+static struct duration_data haptic_default_data;
 
 static int haptic_start(void);
 static int haptic_stop(void);
@@ -170,7 +176,7 @@ static int insert_conf_data(dd_list **conf_data, struct duration_data *update)
        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);
+       // _D("%dD%dI%dF%dO%dW", data->duration, data->intensity, data->frequency, data->overdrive, data->wait);
        DD_LIST_APPEND(*conf_data, data);
        return 0;
 }
@@ -222,6 +228,7 @@ static int insert_raw_data_format(dd_list **conf_data, char *value)
                get_pattern_property(&iter, 'I', &update.intensity);
                if (update.intensity > INTENSITY_BASE_RATE)
                        update.intensity = INTENSITY_BASE_RATE;
+               get_pattern_property(&iter, 'F', &update.frequency);
                get_pattern_property(&iter, 'W', &update.wait);
 
                if (update.duration == 0 && update.wait == 0) {
@@ -262,40 +269,54 @@ static int get_config_data(int count, bool *packed, char *val, unsigned int *pat
        get_pattern_property(&val, 'C', &value);
 
        ret = count;
-       if (count == 1) {               //duration
+       switch (count) {
+       case 1: /* D */
                duration = value;
                *pattern_duration += duration;
                if (*pattern_duration > VIB_LOCK_TIMEOUT_MAX) {
                        _D("Max pattern duration.");
                        *pattern_duration = VIB_LOCK_TIMEOUT_MAX;
                }
-       } else if (count == 2) {
-               /* if intensity is 0, duration use for wait(off) time */
+               break;
+       case 2: /* I or W */
                if (value > INTENSITY_BASE_RATE)
                        value = INTENSITY_BASE_RATE;
                intensity = value;
                if (*packed == false) {
                        update->duration = duration;
                        update->intensity = intensity;
+                       break;
+               }
+                /* if intensity is 0, duration use for wait(off) time */
+               if (intensity == 0)
+                       update->wait = duration;
+               else
+                       update->wait = 0;
+               *packed = false;
+               duration = 0;
+               intensity = 0;
+               ret = -1;
+               break;
+       case 3: /* F */
+               if (intensity != 0)
+                       update->frequency = value;
+               break;
+       case 4:  /* O */
+               if (intensity != 0) {
+                       update->overdrive = value;
                        *packed = true;
-               } else {
-                       if (intensity == 0)
-                               update->wait = duration;
-                       else
-                               update->wait = 0;
-                       *packed = false;
-                       duration = 0;
-                       ret = -1;
                }
-       } else if (count == 4)
                ret = 0;
-
+               break;
+       default:
+               break;
+       }
        return ret;
 }
 
 /*
-       duration, intensity, frequency, overdriving
-       waiting duration, intensity=0, frequency, overdriving
+       duration, intensity, frequency, overdrive
+       waiting duration, intensity=0, frequency, overdrive
        85,10000,
        90,0,
        105,10000,
@@ -503,6 +524,27 @@ void pattern_config_parse(void)
        load_standard_vibration_patterns();
 }
 
+static void get_default_haptic_data()
+{
+       dd_list *elem;
+       struct vibration_config *conf;
+
+       memset(&haptic_default_data, 0, sizeof(struct duration_data));
+
+       DD_LIST_FOREACH(vib_conf_list, elem, conf) {
+               if (!conf->pattern)
+                       continue;
+               if (strcmp(conf->pattern, PATTERN_DEFAULT_MONOTONE))
+                       continue;
+
+               if (conf->data)
+                       memcpy(&haptic_default_data, conf->data->data, sizeof(struct duration_data));
+
+               break;
+       }
+       _D("Default haptic data: intensity=%d, frequency=%d", haptic_default_data.intensity, haptic_default_data.frequency);
+}
+
 static int haptic_module_load(void)
 {
        struct haptic_ops *ops;
@@ -510,6 +552,7 @@ static int haptic_module_load(void)
        int r;
 
        pattern_config_parse();
+       get_default_haptic_data();
        /* find valid plugin */
        DD_LIST_FOREACH(h_head, elem, ops) {
                if (ops->is_valid && ops->is_valid()) {
@@ -535,6 +578,7 @@ static int haptic_module_load(void)
        return 0;
 }
 
+/*
 static int convert_magnitude_by_conf(int level)
 {
        int i, step;
@@ -555,7 +599,7 @@ static int convert_magnitude_by_conf(int level)
        _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)
@@ -800,8 +844,12 @@ static void vibrate_monotone_idler_cb(void *data)
        if (ret != DEVICE_ERROR_NONE)
                _E("Failed to request power lock.");
 
+       _D("Handle(%d) play=%dms, level=%d, intensity=%d, frequency=%d)",
+                       cur_h_data.handle, vibrate_info->duration, cur_h_data.level,
+                       vibrate_info->intensity, haptic_default_data.frequency);
+
        duration_timer = g_timeout_add(vibrate_info->duration, _cb, NULL);
-       h_ops->vibrate_monotone(cur_h_data.handle, vibrate_info->duration, cur_h_data.level, cur_h_data.priority);
+       h_ops->vibrate_monotone(cur_h_data.handle, vibrate_info->duration, haptic_default_data.frequency, 0, cur_h_data.level, vibrate_info->intensity, cur_h_data.priority);
 
        free(vibrate_info);
 }
@@ -812,7 +860,7 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
 {
        struct vibrate_monotone_info *vibrate_info;
        unsigned int handle;
-       int duration, level, priority, ret = 0;
+       int duration, level, intensity, priority, ret = 0;
 
        if (!CHECK_VALID_OPS(h_ops, ret))
                goto exit;
@@ -820,11 +868,9 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
        if (haptic_disabled)
                goto exit;
 
-       g_variant_get(param, "(uiii)", &handle, &duration, &level, &priority);
+       g_variant_get(param, "(uiii)", &handle, &duration, &intensity, &priority);
 
-       /* convert as per conf value */
-       level = convert_magnitude_by_conf(level);
-       if (level < 0) {
+       if (intensity < 0) {
                ret = -EINVAL;
                goto exit;
        }
@@ -840,6 +886,12 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
                goto exit;
        }
 
+       if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
+               _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' value.");
+               ret = -EINVAL;
+               goto exit;
+       }
+
        vibrate_info = calloc(1, sizeof(struct vibrate_monotone_info));
        if (!vibrate_info) {
                _E("Failed to allocate memory for vibrate_info.");
@@ -849,7 +901,8 @@ GVariant *hdbus_vibrate_monotone(GDBusConnection *conn,
 
        vibrate_info->handle = handle;
        vibrate_info->duration = duration;
-       vibrate_info->level = level;
+       vibrate_info->level = (level/2) + 1;
+       vibrate_info->intensity = intensity * 100; // 1~100 (API spec)
        vibrate_info->priority = priority;
 
        ret = add_idle_request(vibrate_monotone_idler_cb, (void *)vibrate_info);
@@ -861,7 +914,6 @@ static gboolean haptic_duration_play(void *data)
 {
        dd_list *head, *n, *next;
        struct duration_data *node;
-       int level;
        int ret = 0;
 
        if (duration_timer) {
@@ -889,9 +941,9 @@ static gboolean haptic_duration_play(void *data)
        }
 
        DD_LIST_FOREACH_SAFE(head, n, next, node) {
-               _D("Handle(%d) play=%dms and Wait=%dms %s type.",
+               _D("Handle(%d) play=%dms and Wait=%dms %s type. (level=%d, intensity=%d, frequency=%d)",
                        cur_h_data.handle, node->duration, node->wait,
-                       cur_h_data.unlimit ? "Unlimit" : "Once");
+                       cur_h_data.unlimit ? "Unlimit" : "Once", cur_h_data.level, node->intensity, node->frequency);
                if ((node->duration + node->wait) <= 0) {
                        if (!cur_h_data.unlimit) {
                                cur_h_data.handle = INVALID_HANDLE;
@@ -903,14 +955,9 @@ 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 = h_ops->vibrate_monotone(cur_h_data.handle, node->duration, level, cur_h_data.priority);
+               ret = h_ops->vibrate_monotone(cur_h_data.handle, node->duration, node->frequency, node->overdrive, cur_h_data.level, node->intensity, cur_h_data.priority);
 
                break;
        }
@@ -1006,12 +1053,11 @@ GVariant *hdbus_vibrate_pattern(GDBusConnection *conn,
 
        g_variant_get(param, "(usii)",  &handle, &pattern, &level, &priority);
 
-       /* 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)
@@ -1162,7 +1208,7 @@ static void haptic_poweroff_cb(GDBusConnection  *conn,
        gpointer          data)
 {
        int type = POWER_OFF_NONE;
-       int ret;
+       int ret, level;
        struct timespec time = {0,};
 
        g_variant_get(param, "(i)", &type);
@@ -1181,11 +1227,18 @@ static void haptic_poweroff_cb(GDBusConnection  *conn,
        if (!g_handle)
                haptic_internal_init();
 
+       if (vconf_get_int(VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT, &level) < 0) {
+               _E("Failed to get '"VCONFKEY_SETAPPL_NOTI_VIBRATION_LEVEL_INT"' vconf value.");
+               return;
+       }
+       level = (level/2) + 1;
+
        /* 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, PRIORITY_HIGH);
+       _I("Handle=%d dur=%dms pri=%d level=%d intensity=%d frequency=%d",
+               g_handle, POWER_OFF_VIB_DURATION, PRIORITY_HIGH, level,
+               POWER_VIB_FEEDBACK * 100, haptic_default_data.frequency);
+       ret = h_ops->vibrate_monotone(g_handle, POWER_OFF_VIB_DURATION, haptic_default_data.frequency, 0,
+                       level, POWER_VIB_FEEDBACK * 100, PRIORITY_HIGH);
        if (ret < 0) {
                _E("Failed to vibrate_monotone: %d", ret);
                return;
index 07779f7..78e1326 100644 (file)
@@ -43,6 +43,9 @@
 #define MAX_DATA 16
 #define FF_INFO_MAGIC 0xDEADFEED
 
+#define SET_OVERDRIVE_BIT(x,value) (x |= ((value > 0)? 1: 0)<<14)
+#define SET_LEVEL_BIT(x,value) (x |= (value<<13))
+
 struct ff_info_header {
        unsigned int magic;
        int iteration;
@@ -194,8 +197,7 @@ static int ff_find_device(void)
                        _D("'%s' type: rumble", ev_path);
 
                if (test_bit(FF_RUMBLE, features)) {
-                       memcpy(ff_path, ev_path, strlen(ev_path));
-                       ff_path[strlen(ev_path)] = '\0';
+                       memcpy(ff_path, ev_path, strlen(ev_path)+1);
                        close(fd);
                        closedir(dir);
                        return 0;
@@ -213,34 +215,41 @@ 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 = 0;
        effect->id = -1;
        effect->u.rumble.strong_magnitude = 0;
+       effect->u.rumble.weak_magnitude = 0;
 
        return 0;
 }
 
-static int ff_set_effect(struct ff_effect *effect, int length, int level)
+static int ff_set_effect(struct ff_effect *effect, int duration, int level, int intensity, int frequency, int overdrive)
 {
-       double magnitude;
-
        if (!effect) {
                _E("There is no valid effect.");
                return -EINVAL;
        }
 
-       magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
-       magnitude *= RUMBLE_MAX_MAGNITUDE;
+       /*
+               __u16 strong_magnitude; // strong_magnitude[15:15] = 0 (Reserved)
+                                      // strong_magnitude[14:14] = Overdrive : 0 (Off) or 1 (On)
+                                      // strong_magnitude[13:0] = Intensity Value : 0 (Stop) or 1 ~ 10000 (Intensity)
+               __u16 weak_magnitude;   // weak_magnitude[15:13] = Intensity Level : 1 ~ 5
+                                      // weak_magnitude[12:0] = Frequency : 0 ~ 8191 (0 ~ 819.1 Hz)
+       */
+
+       effect->u.rumble.strong_magnitude = intensity;
+       SET_OVERDRIVE_BIT(effect->u.rumble.strong_magnitude, overdrive);
 
-       _I("magnitude=%d length=%d", (int)magnitude, length);
+       effect->u.rumble.weak_magnitude = frequency;
+       SET_LEVEL_BIT(effect->u.rumble.weak_magnitude, level);
 
        /* set member variables in effect struct */
-       effect->u.rumble.strong_magnitude = (int)magnitude;
-       effect->replay.length = length;         /* length millisecond */
+       effect->replay.length = duration;               /* length millisecond */
 
+       //_D("rumble data: strong_magnitude = 0x%x, weak_magnitude = 0x%x", effect->u.rumble.strong_magnitude, effect->u.rumble.weak_magnitude);
        return 0;
 }
 
@@ -416,19 +425,19 @@ static int close_device(int device_handle)
        return 0;
 }
 
-static int vibrate_monotone(int device_handle, int duration, int feedback, int priority)
+static int vibrate_monotone(int device_handle, int duration, int frequency, int overdrive, int level, int intensity, int priority)
 {
        struct ff_info *info;
        int ret;
 
        info = read_from_list(device_handle);
        if (!info) {
-               _E("Handle %d failed to check list", device_handle);
+               _E("Handle %d failed to check list.", device_handle);
                return -EINVAL;
        }
 
        if (!check_valid_handle(info)) {
-               _E("Handle %d failed to check handle", device_handle);
+               _E("Handle %d failed to check handle.", device_handle);
                return -EINVAL;
        }
 
@@ -436,7 +445,7 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p
                return -ENODEV;
 
        if (duration <= 0) {
-               _I("Handle %d skip requests with duration 0", device_handle);
+               _I("Handle %d skip requests with duration 0.", device_handle);
                return 0;
        }
 
@@ -453,10 +462,10 @@ static int vibrate_monotone(int device_handle, int duration, int feedback, int p
 
        /* set effect as per arguments */
        ff_init_effect(&info->effect);
-       ret = ff_set_effect(&info->effect, duration, feedback);
+       ret = ff_set_effect(&info->effect, duration, level, intensity, frequency, overdrive);
        if (ret < 0) {
-               _E("Handle %d fail to set effect(duration:%d, feedback:%d) : %d",
-                               device_handle, duration, feedback, ret);
+               _E("Handle %d fail to set effect(duration:%d, level:%d, intensity:%d, frequency:%d, overdrive:%d) : %d",
+                               device_handle, duration, level, intensity, frequency, overdrive, ret);
                return ret;
        }