diff options
-rw-r--r-- | aidl/Android.bp | 43 | ||||
-rw-r--r-- | aidl/Vibrator.cpp | 7 | ||||
-rw-r--r-- | aidl/VibratorOffload.cpp | 310 | ||||
-rw-r--r-- | aidl/include/Vibrator.h | 30 | ||||
-rw-r--r-- | aidl/vendor.qti.hardware.vibrator.offload.service.rc | 4 | ||||
-rw-r--r-- | aidl/vendor.qti.hardware.vibrator.offload.service.xml | 33 | ||||
-rw-r--r-- | effect/Android.bp | 18 | ||||
-rw-r--r-- | effect/VibratorPatterns.cpp | 520 | ||||
-rw-r--r-- | effect/VibratorPatterns.h | 74 | ||||
-rw-r--r-- | vibrator-vendor-product.mk | 6 |
10 files changed, 1041 insertions, 4 deletions
diff --git a/aidl/Android.bp b/aidl/Android.bp index 6ae219e..32a9f59 100644 --- a/aidl/Android.bp +++ b/aidl/Android.bp @@ -41,3 +41,46 @@ cc_binary { "vendor.qti.hardware.vibrator.impl", ], } + +cc_library_shared { + name: "vendor.qti.hardware.vibrator.offload.impl", + vendor: true, + cflags: Common_CFlags + ["-DTARGET_SUPPORTS_OFFLOAD"], + srcs: [ + "Vibrator.cpp", + "VibratorOffload.cpp", + ], + shared_libs: [ + "libcutils", + "libutils", + "liblog", + "libqtivibratoreffect", + "libqtivibratoreffectoffload", + "libsoc_helper", + "libbinder_ndk", + "android.hardware.vibrator-ndk_platform", + ], + export_include_dirs: ["include"] +} + +cc_binary { + name: "vendor.qti.hardware.vibrator.offload.service", + vendor: true, + relative_install_path: "hw", + init_rc: ["vendor.qti.hardware.vibrator.offload.service.rc"], + vintf_fragments: [ + "vendor.qti.hardware.vibrator.offload.service.xml", + ], + cflags: Common_CFlags + ["-DTARGET_SUPPORTS_OFFLOAD"], + srcs: [ + "service.cpp", + ], + shared_libs: [ + "libcutils", + "libutils", + "libbase", + "libbinder_ndk", + "android.hardware.vibrator-ndk_platform", + "vendor.qti.hardware.vibrator.offload.impl", + ], +} diff --git a/aidl/Vibrator.cpp b/aidl/Vibrator.cpp index 8e1c674..d844e74 100644 --- a/aidl/Vibrator.cpp +++ b/aidl/Vibrator.cpp @@ -495,9 +495,14 @@ ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_retu if (ledVib.mDetected) return ndk::ScopedAStatus::ok(); +#ifdef TARGET_SUPPORTS_OFFLOAD + *_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD, + Effect::POP, Effect::HEAVY_CLICK, Effect::RINGTONE_12, + Effect::RINGTONE_13, Effect::RINGTONE_14, Effect::RINGTONE_15}; +#else *_aidl_return = {Effect::CLICK, Effect::DOUBLE_CLICK, Effect::TICK, Effect::THUD, Effect::POP, Effect::HEAVY_CLICK}; - +#endif return ndk::ScopedAStatus::ok(); } diff --git a/aidl/VibratorOffload.cpp b/aidl/VibratorOffload.cpp new file mode 100644 index 0000000..e9a4616 --- /dev/null +++ b/aidl/VibratorOffload.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define LOG_TAG "vendor.qti.vibrator.offload" + +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <thread> +#include <linux/input.h> +#include <log/log.h> +#include <fcntl.h> +#include <cutils/log.h> +#include <cutils/uevent.h> +#include <sys/poll.h> +#include <sys/ioctl.h> + +#include "include/Vibrator.h" +#include "VibratorPatterns.h" + +extern "C" { +#include "libsoc_helper.h" +} + +namespace aidl { +namespace android { +namespace hardware { +namespace vibrator { + +#define UEVENT_MSG_LEN 1024 +#define SLATE_EVENT "SLATE_EVENT=" +#define SLATE_EVENT_STRING_LEN 12 //length of SLATE_EVENT +/* + * TODO Need to work on solution to get this from kernel header + * without effecting other kernel versions where this change + * goes in. + */ +#define SLATE_AFTER_POWER_UP 4 + +PatternOffload::PatternOffload() +{ + std::thread t(&PatternOffload::SSREventListener, this); + t.detach(); +} + +void PatternOffload::SSREventListener(void) +{ + int device_fd, n, ssr_event = 0; + char msg[UEVENT_MSG_LEN + 2]; + char *msg_ptr = msg; + + /* Offload during the bootup */ + SendPatterns(); + + device_fd = uevent_open_socket(64*1024, true); + if(device_fd < 0) + { + ALOGE("open socket failed: %d", device_fd); + return; + } + + while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) { + if (n <= 0 || n >= UEVENT_MSG_LEN) { + ALOGE("Message length %d is not correct\n", n); + continue; + } + msg[n] = '\0'; + msg[n+1] = '\0'; + if (strstr(msg, "slate_com_dev")) { + while(*msg_ptr) { + if(!strncmp(msg_ptr, SLATE_EVENT, SLATE_EVENT_STRING_LEN)) { + msg_ptr += SLATE_EVENT_STRING_LEN; + ssr_event = (atoi(msg_ptr)); + switch(ssr_event) { + case SLATE_AFTER_POWER_UP: + ALOGD("SLATE is powered up"); + SendPatterns(); + break; + } + } + while(*msg_ptr++); + } + } + } +} + +/** Offload patterns + * The sequence of steps in offloading patterns. + * 1. Open the Glink channel to offload the patterns + * 2. Send the configuration/meta data to co-proc + * 3. Wait for the response from the co-proc + * 4. Send the pattern data to co-proc + * 5. Wait for the response + * 6. Exit + */ +void PatternOffload::SendPatterns() +{ + uint8_t *data; + uint32_t len; + int32_t rc; + + rc = initChannel(); + if (rc < 0) + return; + + rc = get_pattern_config(&data, &len); + if (rc < 0 || !data) + return; + + /* Send config data */ + rc = sendData(data, len); + if (rc < 0) + return; + + rc = get_pattern_data(&data, &len); + if (rc < 0 || !data) + return; + + /* Send pattern data */ + rc = sendData(data, len); + if (rc < 0) + return; + + free_pattern_mem(data); + + ALOGI("Patterns offloaded successfully\n"); +} + +int PatternOffload::sendData(uint8_t *data, int len) +{ + int rc, status = 0; + + if (!data || !len) + return -EINVAL; + + rc = GlinkCh.GlinkWrite(data, len); + if (rc < 0) + return rc; + + rc = GlinkCh.GlinkPoll(); + if (rc < 0) + return rc; + + rc = GlinkCh.GlinkRead((uint8_t *)&status, 4); + if (rc < 0) + return rc; + + if (status != OFFLOAD_SUCCESS) + return -EIO; + + return 0; +} + + +int PatternOffload::initChannel() +{ + std::string chname = "/dev/glinkpkt_slate_haptics_offload"; + int rc; + + rc = GlinkCh.GlinkOpen(chname); + if (rc < 0) + { + ALOGE("Failed to open Glink channel name %s\n", chname.c_str()); + return rc; + } + + return 0; +} + +#define GLINK_MAX_CONN_RETRIES 60 +int OffloadGlinkConnection::GlinkOpen(std::string& dev) +{ + int tries = GLINK_MAX_CONN_RETRIES; + dev_name = dev; + + do { + fd = ::open(dev_name.c_str(), O_RDWR); + tries--; + if (fd < 0) + { + ALOGE("%s: %s: open error(%s)", __func__, dev.c_str(), strerror(errno)); + sleep(1); + } + } while(-ETIMEDOUT == errno && tries > 0 ); + + return fd; +} + +int OffloadGlinkConnection::GlinkClose() +{ + if (fd >= 0) + { + ::close(fd); + fd = -1; + } + return 0; +} + +int OffloadGlinkConnection::GlinkPoll() +{ + ssize_t rc = 0; + struct pollfd poll_fd; + + // wait for Rx data available in fd, for 2 seconds timeout + poll_fd.fd = fd; + poll_fd.events = POLLIN; + + rc = ::poll(&poll_fd, 1, 2000); + + if(rc > 0) + { + if (poll_fd.revents & POLLIN) + return 0; + } else if (rc == 0) { + ALOGE("Glink poll timeout"); + } else { + ALOGE("Glink poll error: %s\n", strerror(errno)); + } + + return -1; +} + +int OffloadGlinkConnection::GlinkRead(uint8_t *data, size_t size) +{ + int rc = 0; + size_t bytes_read = 0; + + if (fd < 0) + return -1; + + if (0 != GlinkPoll()) + return -1; + + while (bytes_read < size) + { + rc = ::read(fd, data+bytes_read, size-bytes_read); + if (rc < 0) { + if (errno != EAGAIN) { + ALOGE("%s: Read error: %s, rc %d", __func__, + strerror(errno), rc); + goto read_error; + } + } else if (rc == 0) { + ALOGE("%s: Zero length packet received or hardware connection went off", + __func__); + } + bytes_read += rc; + } + return 0; + +read_error: + return -1; +} + +int OffloadGlinkConnection::GlinkWrite(uint8_t *buf, size_t buflen) +{ + size_t bytes_written_out = 0; + int rc = 0; + + if (fd < 0) + return -1; + + if (!buflen) { + ALOGE("%s: Invalid buffer len", __func__); + return 0; + } + + while (bytes_written_out < buflen) { + rc = ::write (fd, buf+bytes_written_out, buflen-bytes_written_out); + if (rc < 0) { + ALOGE("%s: Write returned failure %d", __func__, rc); + return errno; + } + bytes_written_out += rc; + } + rc = 0; + + return rc; +} + +} // namespace vibrator +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/aidl/include/Vibrator.h b/aidl/include/Vibrator.h index e0694ca..8bfa9f5 100644 --- a/aidl/include/Vibrator.h +++ b/aidl/include/Vibrator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018,2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018,2020-2021, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -64,10 +64,38 @@ private: int write_value(const char *file, const char *value); }; +#ifdef TARGET_SUPPORTS_OFFLOAD +class OffloadGlinkConnection { +public: + int GlinkOpen(std::string& dev); + int GlinkClose(); + int GlinkPoll(); + int GlinkRead(uint8_t *data, size_t size); + int GlinkWrite(uint8_t *buf, size_t buflen); +private: + std::string dev_name; + int fd; +}; + +class PatternOffload { +public: + PatternOffload(); + void SSREventListener(void); + void SendPatterns(); +private: + OffloadGlinkConnection GlinkCh; + int initChannel(); + int sendData(uint8_t *data, int len); +}; +#endif + class Vibrator : public BnVibrator { public: class InputFFDevice ff; class LedVibratorDevice ledVib; +#ifdef TARGET_SUPPORTS_OFFLOAD + class PatternOffload Offload; +#endif ndk::ScopedAStatus getCapabilities(int32_t* _aidl_return) override; ndk::ScopedAStatus off() override; ndk::ScopedAStatus on(int32_t timeoutMs, diff --git a/aidl/vendor.qti.hardware.vibrator.offload.service.rc b/aidl/vendor.qti.hardware.vibrator.offload.service.rc new file mode 100644 index 0000000..8675c62 --- /dev/null +++ b/aidl/vendor.qti.hardware.vibrator.offload.service.rc @@ -0,0 +1,4 @@ +service vendor.qti.vibrator /vendor/bin/hw/vendor.qti.hardware.vibrator.offload.service + class hal + user system + group system input diff --git a/aidl/vendor.qti.hardware.vibrator.offload.service.xml b/aidl/vendor.qti.hardware.vibrator.offload.service.xml new file mode 100644 index 0000000..c8c5a51 --- /dev/null +++ b/aidl/vendor.qti.hardware.vibrator.offload.service.xml @@ -0,0 +1,33 @@ +<!-- Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<manifest version="1.0" type="device"> + <hal format="aidl"> + <name>android.hardware.vibrator</name> + <fqname>IVibrator/default</fqname> + </hal> +</manifest> diff --git a/effect/Android.bp b/effect/Android.bp index 19f6cfe..145c469 100644 --- a/effect/Android.bp +++ b/effect/Android.bp @@ -5,7 +5,23 @@ cc_library_shared { name: "libqtivibratoreffect", vendor: true, cflags: Common_CFlags, - srcs: ["effect.cpp"], + srcs: [ + "effect.cpp", + ], + shared_libs: [ + "libcutils", + "libutils", + ], + export_include_dirs: ["."] +} + +cc_library_shared { + name: "libqtivibratoreffectoffload", + vendor: true, + cflags: Common_CFlags, + srcs: [ + "VibratorPatterns.cpp" + ], shared_libs: [ "libcutils", "libutils", diff --git a/effect/VibratorPatterns.cpp b/effect/VibratorPatterns.cpp new file mode 100644 index 0000000..18a3857 --- /dev/null +++ b/effect/VibratorPatterns.cpp @@ -0,0 +1,520 @@ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <errno.h> + +#include "VibratorPatterns.h" + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) + +static const uint8_t effect_0[] = { + /* (Amp MSB 1 bit) (Amp LSB 8bit) (Period) FLRA */ + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_1[] = { + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_2[] = { + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_3[] = { + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_4[] = { + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_5[] = { + 0x00, 0x1F, S_PERIOD_T_LRA, 0, + 0x00, 0x3F, S_PERIOD_T_LRA, 0, + 0x00, 0x5F, S_PERIOD_T_LRA, 0, + 0x00, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x7F, S_PERIOD_T_LRA, 0, + 0x01, 0x5F, S_PERIOD_T_LRA, 0, + 0x01, 0x3F, S_PERIOD_T_LRA, 0, + 0x01, 0x1F, S_PERIOD_T_LRA, 0, +}; + +static const uint8_t effect_6[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t effect_7[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t effect_8[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +static const uint8_t effect_9[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, + 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 0x07, 0x08, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x06, 0x05, 0x03, 0x01, 0x00, 0xff, 0xfd, 0xfa, 0xf8, 0xf6, + 0xf3, 0xf1, 0xee, 0xec, 0xe9, 0xe6, 0xe3, 0xe0, 0xdc, 0xd9, + 0xd5, 0xd1, 0xcd, 0xc8, 0xc4, 0xbf, 0xbb, 0xb9, 0xb7, 0xb6, + 0xb7, 0xb8, 0xba, 0xbd, 0xc1, 0xc5, 0xcb, 0xd1, 0xd7, 0xde, + 0xe5, 0xed, 0xf5, 0xfd, 0x04, 0x0d, 0x15, 0x1e, 0x26, 0x2e, + 0x36, 0x3d, 0x44, 0x4b, 0x51, 0x56, 0x5b, 0x5f, 0x62, 0x64, + 0x65, 0x65, 0x64, 0x63, 0x5f, 0x5b, 0x56, 0x50, 0x4a, 0x45, + 0x3f, 0x3a, 0x34, 0x2f, 0x29, 0x24, 0x1f, 0x1a, 0x14, 0x0f, + 0x0a, 0x05, 0x00, 0xfc, 0xf8, 0xf3, 0xef, 0xea, 0xe6, 0xe2, + 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd1, + 0xd2, 0xd4, 0xd7, 0xda, 0xde, 0xe2, 0xe8, 0xee, 0xf6, 0xfd, + 0x02, 0x08, 0x0d, 0x12, 0x16, 0x1a, 0x1d, 0x20, 0x23, 0x26, + 0x28, 0x2a, 0x2b, 0x2d, 0x2e, 0x2f, 0x30, 0x30, 0x30, 0x31, + 0x31, 0x31, 0x31, 0x30, 0x30, 0x2f, 0x2f, 0x2e, 0x2d, 0x2c, + 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25, 0x24, 0x23, 0x22, + 0x21, 0x20, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, + 0x0b, 0x0a, 0x0a, 0x09, 0x08, 0x07, 0x07, 0x06, 0x05, 0x04, + 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc, + 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, + 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, + 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +#define OFFSET_EFFECT_0 0 + +#define OFFSET_EFFECT_1 ARRAY_SIZE(effect_0) + +#define OFFSET_EFFECT_2 OFFSET_EFFECT_1 + ARRAY_SIZE(effect_1) + +#define OFFSET_EFFECT_3 OFFSET_EFFECT_2 + ARRAY_SIZE(effect_2) + +#define OFFSET_EFFECT_4 OFFSET_EFFECT_3 + ARRAY_SIZE(effect_3) + +#define OFFSET_EFFECT_5 OFFSET_EFFECT_4 + ARRAY_SIZE(effect_4) + +#define OFFSET_EFFECT_6 OFFSET_EFFECT_5 + ARRAY_SIZE(effect_5) + +#define OFFSET_EFFECT_7 OFFSET_EFFECT_6 + ARRAY_SIZE(effect_6) + +#define OFFSET_EFFECT_8 OFFSET_EFFECT_7 + ARRAY_SIZE(effect_7) + +#define OFFSET_EFFECT_9 OFFSET_EFFECT_8 + ARRAY_SIZE(effect_8) + +#define LEN_TOTAL_PATTERNS OFFSET_EFFECT_9 + ARRAY_SIZE(effect_9) + +#define NUM_TOTAL_PATTERNS 10 + +const static struct effect config_data[] = { + { + .effect_id = 0, /* CLICK */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_0), + .offset = OFFSET_EFFECT_0, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 1, /* DOUBLE_CLICK */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_1), + .offset = OFFSET_EFFECT_1, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 2, /* TICK */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_2), + .offset = OFFSET_EFFECT_2, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 3, /* THUD */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_3), + .offset = OFFSET_EFFECT_3, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 4, /* POP */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_4), + .offset = OFFSET_EFFECT_4, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 5, /* HEAVY_CLICK */ + .effect_type = EFFECT_TYPE_PATTERN, + .effect_len = ARRAY_SIZE(effect_5), + .offset = OFFSET_EFFECT_5, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 17, /* RINGTONE_12 */ + .effect_type = EFFECT_TYPE_FIFO_ENVELOPE, + .effect_len = ARRAY_SIZE(effect_6), + .offset = OFFSET_EFFECT_6, + .play_rate = S_PERIOD_T_LRA, + }, + + { + .effect_id = 18, /* RINGTONE_13 */ + .effect_type = EFFECT_TYPE_FIFO_ENVELOPE, + .effect_len = ARRAY_SIZE(effect_7), + .offset = OFFSET_EFFECT_7, + .play_rate = S_PERIOD_T_LRA_X_8, + }, + + { + .effect_id = 19, /* RINGTONE_14 */ + .effect_type = EFFECT_TYPE_FIFO_ENVELOPE, + .effect_len = ARRAY_SIZE(effect_8), + .offset = OFFSET_EFFECT_8, + .play_rate = S_PERIOD_T_LRA_X_8, + }, + + { + .effect_id = 20, /* RINGTONE_15 */ + .effect_type = EFFECT_TYPE_FIFO_ENVELOPE, + .effect_len = ARRAY_SIZE(effect_9), + .offset = OFFSET_EFFECT_9, + .play_rate = S_PERIOD_T_LRA_X_8, + }, +}; + +int get_pattern_config(uint8_t **ptr, uint32_t *size) +{ + *ptr = (uint8_t *)config_data; + *size = sizeof(config_data); + return 0; +} + +int get_pattern_data(uint8_t **ptr, uint32_t *size) +{ + uint8_t *pattern_data; + uint8_t *pbuf; + int i; + const uint8_t *pattern[] = {effect_0, effect_1, effect_2, effect_3, effect_4, + effect_5, effect_6, effect_7, effect_8, effect_9}; + + uint32_t pattern_size[] = {sizeof(effect_0), sizeof(effect_1), + sizeof(effect_2), sizeof(effect_3), + sizeof(effect_4), sizeof(effect_5), + sizeof(effect_6), sizeof(effect_7), + sizeof(effect_8), sizeof(effect_9)}; + + pattern_data = new uint8_t[LEN_TOTAL_PATTERNS]; + if (!pattern_data) { + *ptr = NULL; + return -ENOMEM; + } + + pbuf = pattern_data; + for (i = 0; i < NUM_TOTAL_PATTERNS; i++) { + memcpy(pbuf, pattern[i], pattern_size[i]); + pbuf = pbuf + pattern_size[i]/sizeof(char); + } + + *ptr = pattern_data; + *size = LEN_TOTAL_PATTERNS; + + return 0; +} + +void free_pattern_mem(uint8_t *ptr) +{ + delete ptr; +} diff --git a/effect/VibratorPatterns.h b/effect/VibratorPatterns.h new file mode 100644 index 0000000..0550a21 --- /dev/null +++ b/effect/VibratorPatterns.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VIBRATOR_PATTERNS_H +#define VIBRATOR_PATTERNS_H + +#include <sys/types.h> + +struct effect { + uint16_t effect_id; + uint16_t effect_type; + uint16_t effect_len; + uint16_t offset; + uint32_t play_rate; +}; + +enum period { + S_PERIOD_T_LRA = 0, + S_PERIOD_T_LRA_DIV_2, + S_PERIOD_T_LRA_DIV_4, + S_PERIOD_T_LRA_DIV_8, + S_PERIOD_T_LRA_X_2, + S_PERIOD_T_LRA_X_4, + S_PERIOD_T_LRA_X_8, + /* F_8KHZ to F_48KHZ can be specified only for FIFO patterns */ + S_PERIOD_F_8KHZ = 8, + S_PERIOD_F_16KHZ, + S_PERIOD_F_24KHZ, + S_PERIOD_F_32KHZ, + S_PERIOD_F_44P1KHZ, + S_PERIOD_F_48KHZ, +}; + +enum effect_type { + EFFECT_TYPE_PATTERN = 1, + EFFECT_TYPE_FIFO_ENVELOPE, + EFFECT_TYPE_FIFO_STREAMING, +}; + +enum offload_status { + OFFLOAD_SUCCESS = 0, + OFFLOAD_FAILURE = 1 +}; + +int get_pattern_config(uint8_t **ptr, uint32_t *size); +int get_pattern_data(uint8_t **ptr, uint32_t *size); +void free_pattern_mem(uint8_t *ptr); +#endif diff --git a/vibrator-vendor-product.mk b/vibrator-vendor-product.mk index 4d97341..df83d1d 100644 --- a/vibrator-vendor-product.mk +++ b/vibrator-vendor-product.mk @@ -1,6 +1,10 @@ +ifeq ($(HAPTICS_OFFLOAD_SUPPORT),true) +QTI_VIBRATOR_HAL_SERVICE := \ + vendor.qti.hardware.vibrator.offload.service +else QTI_VIBRATOR_HAL_SERVICE := \ vendor.qti.hardware.vibrator.service - +endif PRODUCT_PACKAGES += $(QTI_VIBRATOR_HAL_SERVICE) ifneq ($(BOARD_OPENSOURCE_DIR), ) |