From 836fbe09201491698bd471ca06e9140a720b9d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Thu, 6 Mar 2025 10:29:38 +0100 Subject: [PATCH 1/7] treewide: Fix typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guido Günther --- NEWS | 4 ++-- README.md | 2 +- data/org.sigxcpu.feedbackd.gschema.xml | 2 +- debian/changelog | 18 +++++++++--------- doc/feedback-themes.rst | 2 +- doc/initialization.md | 2 +- libfeedback/lfb-main.c | 2 +- src/fbd-dev-led-multicolor.c | 2 +- src/fbd-haptic-manager.c | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/NEWS b/NEWS index 42fbac2..5cd5a2c 100644 --- a/NEWS +++ b/NEWS @@ -36,7 +36,7 @@ feedbackd 0.4.1 --------------- Released August 2024 * Simplify udev rule installation -* Dont' fail tests with newer json-glib +* Don't fail tests with newer json-glib * Issues fixed: * https://source.puri.sm/Librem5/feedbackd/-/issues/79 * Contributors: @@ -50,7 +50,7 @@ Released June 2024 * Internal cleanups and restructuring to cater for different LED types. * Support RGB color mixing for multicolor leds -* Allow to use (camera) flash LEDs as notificaton LED +* Allow to use (camera) flash LEDs as notification LED * Immediately end "too noisy" feedbacks when switching profile levels * Issues fixed: * https://source.puri.sm/Librem5/feedbackd/-/issues/77 diff --git a/README.md b/README.md index f6fdf70..f7f031c 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,7 @@ modified theme file in If multiple theme files exist, the selection logic follows these steps: 1. It picks an identifier from the devicetree, until none are left -1. It searches through the folders in `XDG_DATA_DIRS` in order of appearence, +1. It searches through the folders in `XDG_DATA_DIRS` in order of appearance, until none are left 1. If a theme file is found in the current location with the current name, **it will be chosen** and other themes are ignored. diff --git a/data/org.sigxcpu.feedbackd.gschema.xml b/data/org.sigxcpu.feedbackd.gschema.xml index df76971..732726b 100644 --- a/data/org.sigxcpu.feedbackd.gschema.xml +++ b/data/org.sigxcpu.feedbackd.gschema.xml @@ -28,7 +28,7 @@ false Prefer camera flash LED over notification LED - Prefer the (camera) flash LED over other notifiction LEDs. + Prefer the (camera) flash LED over other notification LEDs. diff --git a/debian/changelog b/debian/changelog index 9c5ca24..67e39c1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -33,9 +33,9 @@ feedbackd (0.6.0) experimental; urgency=medium [ Guido Günther ] * event-naming-spec: Fix section description - * event-naming-spec: Expand on notifiction events. + * event-naming-spec: Expand on notification events. We move them to the system category as the notification server - is a system component and add an event for now notifictions + is a system component and add an event for new notifications for the notification server to use * theme: Add notification-missed-new. We'll remove message-new-notification somewhat later to not break @@ -101,7 +101,7 @@ feedbackd (0.5.0) experimental; urgency=medium [ Guido Günther ] * packaging: Update lintian overrides * packaging: Install NEWS and README. They contain useful information - * packaging: Use pkgconf. It's prefered over pkg-config in Debian + * packaging: Use pkgconf. It's preferred over pkg-config in Debian * doc: Document gsettings used by feedbackd * udev: Add support for haptics on Oneplus Enchilada / Fajita. The spmi_haptics driver isn't in mainline Linux as of Linux 6.11. @@ -266,7 +266,7 @@ feedbackd (0.4.0) experimental; urgency=medium even if the device is suspended. * fbd-dev-led-qcom-multicolor: Support QCOM LPG LED multicolor. QCOM LPG LEDs can also operate in a multicolor fashion. - Re-use the probing sequence of multicolor LEDs and the hw_pattern + Reuse the probing sequence of multicolor LEDs and the hw_pattern configuration of single color QCOM LPG LEDs. * fbd-dev-leds: Probe QCOM HW LED types. Try first the QCOM hardware LED types which require the most features of @@ -486,7 +486,7 @@ feedbackd (0.0.2) experimental; urgency=medium * Include specifications in the documentation. Now that we can use markdown easily add them as they provide help to the developer what events exist, etc. - * dir-locals: Simlify consistent JS indenting + * dir-locals: Simplify consistent JS indenting * feedback-vibra: Fix indentation * tests: Test feedback theme name * feedback-theme: No need for constructed. @@ -700,13 +700,13 @@ feedbackd (0.0.0+git20210426) byzantium; urgency=medium * event: Make log-domain match source file name * tests: Run event tests too * event: Remove 'g' prefix from common C types. - This matchs phosh's style. + This matches phosh's style. * fbd-event: Add sender property. This allows us to store the DBus sender * fbd-manager: Keep DBus sender around * feedback-manager: Track DBus clients and end feedbacks if they go away. When the client goes away we build up a list of events to end feedback - for to make sure the hash table isn't modified in place. tThe alternative + for to make sure the hash table isn't modified in place. the alternative approach would be to disconnect the on_event_feedbacks_ended handler, duplicate the DBus signal emission and use g_hash_table_foreach_remove but that looks less robust than using the same code path. (Closes: #25) @@ -838,7 +838,7 @@ feedbackd (0.0.0+git20200714) amber-phone; urgency=medium [ Guido Günther ] * lfb-event: Clarify return values of `finished` functions. - They just inidicate that we talked to feedbackd successfully. + They just indicate that we talked to feedbackd successfully. * lfb-event: Connect done handler in async case too. Otherwise the event state is not updated properly * tests: Don't quit mainloop on event end. @@ -886,7 +886,7 @@ feedbackd (0.0.0+git20200707) amber-phone; urgency=medium trigger. * data: Use LED feedback for missed calls, IMs and SMS * Add generic missed notification. - This can be used e.g. by the shell for general purpose notifictions + This can be used e.g. by the shell for general purpose notifications but also for in app notifications of the foreground app. * feedback-manager: Add hint to select feedback profile per event. This e.g. allows events that are meant for haptic only to avoid diff --git a/doc/feedback-themes.rst b/doc/feedback-themes.rst index dea3682..7490847 100644 --- a/doc/feedback-themes.rst +++ b/doc/feedback-themes.rst @@ -51,7 +51,7 @@ The `Led` feedback type uses two properties to specify the way a LED blinks. `green`, `blue` and `white` as well as values in the RGB HEX format (`#RRGGBB`) where `RR`, `GG` and `BB` are two digit hex value between `00` and `FF` specifying the value of each component. E.g. `#00FFFF` corresponds to cyan color. -- `frequency`: The LEDs blinkinig frequencey in mHz. +- `frequency`: The LEDs blinkinig frequency in mHz. See also ======== diff --git a/doc/initialization.md b/doc/initialization.md index a5d58c1..843de94 100644 --- a/doc/initialization.md +++ b/doc/initialization.md @@ -8,7 +8,7 @@ call [func@Lfb.init]() with the id of your application (usually the desktop file name without the .desktop extension). For that you include the `libfeedback.h` header. Since the API is considered unstable at this point in time you need to acknowledge this by -definining `LIBFEEDBACK_USE_UNSTABLE_API`: +defining `LIBFEEDBACK_USE_UNSTABLE_API`: ```c #define LIBFEEDBACK_USE_UNSTABLE_API diff --git a/libfeedback/lfb-main.c b/libfeedback/lfb-main.c index b317305..7059f9e 100644 --- a/libfeedback/lfb-main.c +++ b/libfeedback/lfb-main.c @@ -28,7 +28,7 @@ lfb_cancel_feedbacks (void) while (g_hash_table_iter_next (&iter, &key, &value)) { guint id = GPOINTER_TO_UINT(key); g_hash_table_iter_remove (&iter); - g_debug ("Cancellling feedback on shutdown %d", id); + g_debug ("Cancelling feedback on shutdown %d", id); /* Need to use a sync call here since there might not be a main loop anymore */ lfb_gdbus_feedback_call_end_feedback_sync (_proxy, id, NULL, NULL); } diff --git a/src/fbd-dev-led-multicolor.c b/src/fbd-dev-led-multicolor.c index e330155..287f200 100644 --- a/src/fbd-dev-led-multicolor.c +++ b/src/fbd-dev-led-multicolor.c @@ -79,7 +79,7 @@ fbd_dev_led_multicolor_probe (FbdDevLed *led, GError **error) priv->blue_index = counter; counter++; } else { - g_warning ("Unsupport LED color index: %d %s", counter, index[i]); + g_warning ("Unsupported LED color index: %d %s", counter, index[i]); } } diff --git a/src/fbd-haptic-manager.c b/src/fbd-haptic-manager.c index a886f35..d1fb3c3 100644 --- a/src/fbd-haptic-manager.c +++ b/src/fbd-haptic-manager.c @@ -133,7 +133,7 @@ fbd_feedback_manager_handle_vibrate (LfbGdbusFeedbackHaptic *object, fbd_feedback_end (FBD_FEEDBACK_BASE (self->vibra)); if (fbd_dev_vibra_is_busy (vibra_dev)) { g_debug ("Haptic busy"); - /* If there's an event with haptic deny haptic patter */ + /* If there's an event with haptic deny haptic pattern */ lfb_gdbus_feedback_haptic_complete_vibrate (object, invocation, FALSE); return TRUE; } From 70fd0a87593930eda48858dc7d11ab253ad4cd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 23:16:26 +0100 Subject: [PATCH 2/7] data/haptic: Document duration unit in the protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guido Günther --- data/org.sigxcpu.Feedback.Haptic.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/org.sigxcpu.Feedback.Haptic.xml b/data/org.sigxcpu.Feedback.Haptic.xml index ea6c4ee..4e2a192 100644 --- a/data/org.sigxcpu.Feedback.Haptic.xml +++ b/data/org.sigxcpu.Feedback.Haptic.xml @@ -19,7 +19,8 @@ Triggers the given vibration pattern on the haptic device. The pattern is a sequence of relative amplitude and duration pairs. - The amplitude must be between 0.0 and 1.0. + The amplitude must be between 0.0 and 1.0, durations are in + milliseconds. --> From 88dd60413e416fa039471d29f20825e1eac0fa03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 22:50:20 +0100 Subject: [PATCH 3/7] vibra-pattern: Reset pos when done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to reuse the feedback. Signed-off-by: Guido Günther --- src/fbd-feedback-vibra-pattern.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/fbd-feedback-vibra-pattern.c b/src/fbd-feedback-vibra-pattern.c index b74c44c..571af9d 100644 --- a/src/fbd-feedback-vibra-pattern.c +++ b/src/fbd-feedback-vibra-pattern.c @@ -157,6 +157,7 @@ on_timer_expired (gpointer data) self->pos++; if (self->pos == self->durations->len) { + self->pos = 0; self->timer_id = 0; return; } @@ -172,10 +173,8 @@ fbd_feedback_vibra_pattern_end_vibra (FbdFeedbackVibra *vibra) FbdFeedbackManager *manager = fbd_feedback_manager_get_default (); FbdDevVibra *dev = fbd_feedback_manager_get_dev_vibra (manager); - if (self->timer_id) { - self->pos = 0; - g_clear_handle_id (&self->timer_id, g_source_remove); - } + self->pos = 0; + g_clear_handle_id (&self->timer_id, g_source_remove); fbd_dev_vibra_stop (dev); } From e92df04e80a332d375e434d45a51fd21ba931491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 23:27:28 +0100 Subject: [PATCH 4/7] vibra-pattern: Check for NULL dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When running e.g. in the theme validator we might not have a vibra dev. Signed-off-by: Guido Günther --- src/fbd-feedback-vibra-pattern.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fbd-feedback-vibra-pattern.c b/src/fbd-feedback-vibra-pattern.c index 571af9d..7361d01 100644 --- a/src/fbd-feedback-vibra-pattern.c +++ b/src/fbd-feedback-vibra-pattern.c @@ -176,7 +176,8 @@ fbd_feedback_vibra_pattern_end_vibra (FbdFeedbackVibra *vibra) self->pos = 0; g_clear_handle_id (&self->timer_id, g_source_remove); - fbd_dev_vibra_stop (dev); + if (dev) + fbd_dev_vibra_stop (dev); } From 54060b4e383efd1e6f29511aa9adde2837df6224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 23:09:43 +0100 Subject: [PATCH 5/7] vibra-pattern: End pending vibra when a new one is triggered This wasn't much of an issue for the DBus API but when using it as event feedback it matters as we might start the new feedback just before the old one ended due to timers being slighlty late. --- src/fbd-feedback-vibra-pattern.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fbd-feedback-vibra-pattern.c b/src/fbd-feedback-vibra-pattern.c index 7361d01..48b5733 100644 --- a/src/fbd-feedback-vibra-pattern.c +++ b/src/fbd-feedback-vibra-pattern.c @@ -192,7 +192,9 @@ fbd_feedback_vibra_pattern_start_vibra (FbdFeedbackVibra *vibra) g_return_if_fail (self->magnitudes); g_return_if_fail (self->durations); g_return_if_fail (self->durations->len == self->magnitudes->len); - g_return_if_fail (self->pos == 0); + + if (self->pos) + fbd_feedback_vibra_pattern_end_vibra (FBD_FEEDBACK_VIBRA (self)); g_debug ("Pattern Vibra: %u elements", self->durations->len); From 7b19feb25f4122eae0d448e36e165dfa38e3e051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 21:20:29 +0100 Subject: [PATCH 6/7] fbd-feedback-vibra-pattern: Deserialize properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to use them in feedback themes Signed-off-by: Guido Günther --- src/fbd-feedback-profile.c | 2 + src/fbd-feedback-vibra-pattern.c | 70 +++++++++++++++++++++++++++++++- tests/meson.build | 3 ++ tests/test-fbd-feedback-vibra.c | 66 ++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/test-fbd-feedback-vibra.c diff --git a/src/fbd-feedback-profile.c b/src/fbd-feedback-profile.c index 94cbb36..d1bb605 100644 --- a/src/fbd-feedback-profile.c +++ b/src/fbd-feedback-profile.c @@ -10,6 +10,7 @@ #include "fbd-feedback-profile.h" #include "fbd-feedback-sound.h" #include "fbd-feedback-led.h" +#include "fbd-feedback-vibra-pattern.h" #include "fbd-feedback-vibra-periodic.h" #include "fbd-feedback-vibra-rumble.h" @@ -85,6 +86,7 @@ feedback_get_type (JsonNode *feedback_node) /* Ensure all feedback types so the json parsing can use them */ g_type_ensure (FBD_TYPE_FEEDBACK_DUMMY); g_type_ensure (FBD_TYPE_FEEDBACK_LED); + g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_PATTERN); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_PERIODIC); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_RUMBLE); g_type_ensure (FBD_TYPE_FEEDBACK_SOUND); diff --git a/src/fbd-feedback-vibra-pattern.c b/src/fbd-feedback-vibra-pattern.c index 48b5733..4807ede 100644 --- a/src/fbd-feedback-vibra-pattern.c +++ b/src/fbd-feedback-vibra-pattern.c @@ -13,6 +13,8 @@ #include "fbd-feedback-vibra-priv.h" #include "fbd-feedback-manager.h" +#include + /** * FbdFeedbackVibraPattern: * @@ -41,7 +43,68 @@ typedef struct _FbdFeedbackVibraPattern { guint timer_id; } FbdFeedbackVibraPattern; -G_DEFINE_TYPE (FbdFeedbackVibraPattern, fbd_feedback_vibra_pattern, FBD_TYPE_FEEDBACK_VIBRA); +static void json_serializable_iface_init (JsonSerializableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (FbdFeedbackVibraPattern, fbd_feedback_vibra_pattern, + FBD_TYPE_FEEDBACK_VIBRA, + G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, + json_serializable_iface_init)); + + +static gboolean +fbd_feedback_vibra_pattern_serializable_deserialize_property (JsonSerializable *serializable, + const gchar *property_name, + GValue *value, + GParamSpec *pspec, + JsonNode *property_node) +{ + if (g_strcmp0 (property_name, "magnitudes") == 0) { + if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) { + JsonArray *array = json_node_get_array (property_node); + guint array_len = json_array_get_length (array); + g_autoptr (GArray) magnitudes = g_array_sized_new (FALSE, FALSE, sizeof (double), array_len); + + for (guint i = 0; i < array_len; i++) { + JsonNode *element_node = json_array_get_element (array, i); + + if (JSON_NODE_HOLDS_VALUE (element_node)) { + double magnitude; + + magnitude = json_node_get_double (element_node); + magnitude = MAX (0.0, MIN (magnitude, 1.0)); + g_array_append_val (magnitudes, magnitude); + } else { + return FALSE; + } + } + g_value_set_boxed (value, magnitudes); + return TRUE; + } + } else if (g_strcmp0 (property_name, "durations") == 0) { + if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) { + JsonArray *array = json_node_get_array (property_node); + guint array_len = json_array_get_length (array); + g_autoptr (GArray) durations = g_array_sized_new (FALSE, FALSE, sizeof (guint), array_len); + + for (guint i = 0; i < array_len; i++) { + JsonNode *element_node = json_array_get_element (array, i); + + if (JSON_NODE_HOLDS_VALUE (element_node)) { + guint duration; + + duration = json_node_get_int (element_node); + g_array_append_val (durations, duration); + } else { + return FALSE; + } + } + g_value_set_boxed (value, durations); + return TRUE; + } + } + + return FALSE; +} static void @@ -227,6 +290,11 @@ fbd_feedback_vibra_pattern_finalize (GObject *object) G_OBJECT_CLASS (fbd_feedback_vibra_pattern_parent_class)->finalize (object); } +static void +json_serializable_iface_init (JsonSerializableIface *iface) +{ + iface->deserialize_property = fbd_feedback_vibra_pattern_serializable_deserialize_property; +} static void fbd_feedback_vibra_pattern_class_init (FbdFeedbackVibraPatternClass *klass) diff --git a/tests/meson.build b/tests/meson.build index f9d4264..20c9c74 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -14,6 +14,8 @@ if get_option('tests') test_env.set('MALLOC_CHECK_', '2') test_env.set('XDG_CONFIG_HOME', meson.current_source_dir() / 'data' / 'user-config') test_env.set('XDG_CONFIG_DIRS', meson.current_source_dir()) + # Override desktop so we don't depend on GNOME schemas in the tests + test_env.set('XDG_CURRENT_DESKTOP', 'doesnotexist') # Shared library Unit tests @@ -66,6 +68,7 @@ if get_option('tests') fbd_tests = [ 'fbd-feedback-led', 'fbd-feedback-profile', + 'fbd-feedback-vibra', 'fbd-feedback-theme', 'fbd-event', 'fbd-theme-expander', diff --git a/tests/test-fbd-feedback-vibra.c b/tests/test-fbd-feedback-vibra.c new file mode 100644 index 0000000..fca6845 --- /dev/null +++ b/tests/test-fbd-feedback-vibra.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2025 The Phosh Developers + * + * SPDX-License-Identifier: GPL-3.0+ + * + * Author: Guido Günther + */ + +#define GMOBILE_USE_UNSTABLE_API +#include "fbd-feedback-manager.h" +#include "fbd-feedback-vibra-pattern.h" + +#include + + +static void +test_fbd_feedback_vibra_pattern (void) +{ + /* Create manager upfront so we can dispose it, otherwise creating + * any feedback would create it implicitly */ + FbdFeedbackManager *manager = fbd_feedback_manager_get_default (); + g_autoptr (GError) err = NULL; + g_autoptr (JsonNode) node = NULL; + g_autoptr (GArray) durations = NULL, magnitudes = NULL; + GObject *object; + guint *duration; + double *magnitude; + + node = json_from_string("{" + " \"event-name\" : \"button-pressed\"," + " \"type\" : \"VibraPattern\"," + " \"magnitudes\" : [ 0.2, 1.0 ]," + " \"durations\" : [ 7, 3 ]" + "}", &err); + g_assert_no_error (err); + + object = json_gobject_deserialize (FBD_TYPE_FEEDBACK_VIBRA_PATTERN, node); + g_object_get (object, "durations", &durations, "magnitudes", &magnitudes, NULL); + + g_assert_nonnull(durations); + g_assert_nonnull(magnitudes); + + duration = &g_array_index (durations, guint, 0); + g_assert_cmpint (*duration, ==, 7); + duration = &g_array_index (durations, guint, 1); + g_assert_cmpint (*duration, ==, 3); + + magnitude = &g_array_index (magnitudes, double, 0); + g_assert_cmpfloat (*magnitude, ==, 0.2); + magnitude = &g_array_index (magnitudes, double, 1); + g_assert_cmpfloat (*magnitude, ==, 1.0); + + g_assert_finalize_object (object); + g_assert_finalize_object (manager); +} + + +gint +main (gint argc, gchar *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func("/feedbackd/fbd/feedback-vibra/pattern", test_fbd_feedback_vibra_pattern); + + return g_test_run(); +} From 85c4545adfe1a260e8b3fd408fb8fe1b2a8a37a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 23:20:27 +0100 Subject: [PATCH 7/7] doc: Document the `VibraPattern` feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guido Günther --- doc/feedback-themes.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/feedback-themes.rst b/doc/feedback-themes.rst index 7490847..12c583d 100644 --- a/doc/feedback-themes.rst +++ b/doc/feedback-themes.rst @@ -27,6 +27,7 @@ To build a theme you can use several different feedback types: - `Sound`: Plays a sound from the installed sound theme - `VibraRumble`: A single rumble using the haptic motor - `VibraPeriodic`: A periodic rumble using the haptic motor +- `VibraPattern`: A pattern specifying the rumbling of the haptic motor - `Led`: A LED blinking in a periodic pattern Sound feedback @@ -42,6 +43,16 @@ The `VibraRumble` feedback uses a single property - `duration`: The duration of the rumble in ms. +VibraPattern feedback +~~~~~~~~~~~~~~~~~~~~~ + +The `VibraPattern` feedback has these properties + +- `magnitudes`: The relative magnitude of each rumble ``[0, 1]`` as array of doubles. +- `durations`: The durations of each rumble in ms as array of unsigned integers. + +Both arrays must have the same length. + LED feedback ~~~~~~~~~~~~