|
1 | 1 | /*
|
2 | 2 | * Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
| 3 | + * Copyright (C) 2022-2023 The LineageOS Project |
3 | 4 | *
|
4 | 5 | * Redistribution and use in source and binary forms, with or without
|
5 | 6 | * modification, are permitted provided that the following conditions are
|
|
31 | 32 | * SPDX-License-Identifier: BSD-3-Clause-Clear
|
32 | 33 | */
|
33 | 34 |
|
| 35 | +#define LOG_TAG "libqtivibratoreffect.xiaomi" |
| 36 | + |
| 37 | +#include <android-base/logging.h> |
| 38 | +#include <filesystem> |
| 39 | +#include <fstream> |
| 40 | +#include <iostream> |
| 41 | +#include <unordered_map> |
| 42 | +#include <vector> |
| 43 | + |
34 | 44 | #include "effect.h"
|
35 | 45 |
|
36 |
| -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) |
37 |
| - |
38 |
| -/* ~170 HZ sine waveform */ |
39 |
| -static const int8_t effect_0[] = { |
40 |
| - 17, 34, 50, 65, 79, 92, 103, 112, 119, 124, |
41 |
| - 127, 127, 126, 122, 116, 108, 98, 86, 73, 58, |
42 |
| - 42, 26, 9, -8, -25, -41, -57, -72, -85, -97, |
43 |
| - -108, -116, -122, -126, -127, -127, -125, -120, |
44 |
| - -113, -104, -93, -80, -66, -51, -35, -18, -1, |
45 |
| -}; |
46 |
| - |
47 |
| -static const int8_t effect_1[] = { |
48 |
| - -1, -18, -35, -51, -66, -80, -93, -104, -113, |
49 |
| - -120, -125, -127, -127, -126, -122, -116, -108, |
50 |
| - -97, -85, -72, -57, -41, -25, -8, 9, 26, 42, |
51 |
| - 58, 73, 86, 98, 108, 116, 122, 126, 127, 127, |
52 |
| - 124, 119, 112, 103, 92, 79, 65, 50, 34, 17, |
53 |
| -}; |
54 |
| - |
55 |
| -static const int8_t primitive_0[] = { |
56 |
| - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
57 |
| -}; |
58 |
| - |
59 |
| -static const int8_t primitive_1[] = { |
60 |
| - 17, 34, 50, 65, 79, 92, 103, 112, 119, 124, |
61 |
| - 127, 127, 126, 122, 116, 108, 98, 86, 73, 58, |
62 |
| - 42, 26, 9, -8, -25, -41, -57, -72, -85, -97, |
63 |
| - -108, -116, -122, -126, -127, -127, -125, -120, |
64 |
| - -113, -104, -93, -80, -66, -51, -35, -18, -1, |
65 |
| -}; |
66 |
| - |
67 |
| -static const int8_t primitive_2[] = { |
68 |
| - 17, 34, 50, 65, 79, 92, 103, 112, 119, 124, |
69 |
| - 127, 127, 126, 122, 116, 108, 98, 86, 73, 58, |
70 |
| - 42, 26, 9, -8, -25, -41, -57, -72, -85, -97, |
71 |
| - -108, -116, -122, -126, -127, -127, -125, -120, |
72 |
| - -113, -104, -93, -80, -66, -51, -35, -18, -1, |
73 |
| -}; |
74 |
| - |
75 |
| -static const struct effect_stream effects[] = { |
76 |
| - { |
77 |
| - .effect_id = 0, |
78 |
| - .data = effect_0, |
79 |
| - .length = ARRAY_SIZE(effect_0), |
80 |
| - .play_rate_hz = 8000, |
81 |
| - }, |
82 |
| - |
83 |
| - { |
84 |
| - .effect_id = 1, |
85 |
| - .data = effect_1, |
86 |
| - .length = ARRAY_SIZE(effect_1), |
87 |
| - .play_rate_hz = 8000, |
88 |
| - }, |
89 |
| -}; |
90 |
| - |
91 |
| -static const struct effect_stream primitives[] = { |
92 |
| - { |
93 |
| - .effect_id = 0, |
94 |
| - .data = primitive_0, |
95 |
| - .length = ARRAY_SIZE(primitive_0), |
96 |
| - .play_rate_hz = 8000, |
97 |
| - }, |
98 |
| - |
99 |
| - { |
100 |
| - .effect_id = 1, |
101 |
| - .data = primitive_1, |
102 |
| - .length = ARRAY_SIZE(primitive_1), |
103 |
| - .play_rate_hz = 8000, |
104 |
| - }, |
105 |
| - |
106 |
| - { |
107 |
| - .effect_id = 2, |
108 |
| - .data = primitive_2, |
109 |
| - .length = ARRAY_SIZE(primitive_2), |
110 |
| - .play_rate_hz = 8000, |
111 |
| - }, |
112 |
| -}; |
113 |
| - |
114 |
| -const struct effect_stream *get_effect_stream(uint32_t effect_id) |
115 |
| -{ |
116 |
| - int i; |
117 |
| - |
118 |
| - if ((effect_id & 0x8000) != 0) { |
119 |
| - effect_id = effect_id & 0x7fff; |
120 |
| - |
121 |
| - for (i = 0; i < ARRAY_SIZE(primitives); i++) { |
122 |
| - if (effect_id == primitives[i].effect_id) |
123 |
| - return &primitives[i]; |
124 |
| - } |
| 46 | +namespace { |
| 47 | + |
| 48 | +const uint32_t kDefaultPlayRateHz = 24000; |
| 49 | +const uint16_t kPrimitiveMask = (1 << 15); |
| 50 | + |
| 51 | +std::unordered_map<uint32_t, effect_stream> sEffectStreams; |
| 52 | +std::unordered_map<uint32_t, std::vector<int8_t>> sEffectFifoData; |
| 53 | + |
| 54 | +std::unique_ptr<effect_stream> readEffectStreamFromFile(uint32_t uniqueEffectId) { |
| 55 | + std::filesystem::path filePath; |
| 56 | + |
| 57 | + uint32_t effectId = uniqueEffectId & ~kPrimitiveMask; |
| 58 | + |
| 59 | + if ((uniqueEffectId & kPrimitiveMask) != 0) { |
| 60 | + filePath = "/vendor/etc/vibrator/primitive_effect_" + std::to_string(effectId) + ".bin"; |
125 | 61 | } else {
|
126 |
| - for (i = 0; i < ARRAY_SIZE(effects); i++) { |
127 |
| - if (effect_id == effects[i].effect_id) |
128 |
| - return &effects[i]; |
| 62 | + filePath = "/vendor/etc/vibrator/effect_" + std::to_string(effectId) + ".bin"; |
| 63 | + } |
| 64 | + |
| 65 | + LOG(VERBOSE) << "Reading fifo data for effect " << effectId << " from " << filePath; |
| 66 | + |
| 67 | + std::ifstream data(filePath, std::ios::in | std::ios::binary); |
| 68 | + if (!data.is_open()) { |
| 69 | + LOG(ERROR) << "Failed to open " << filePath << " for effect " << effectId; |
| 70 | + return nullptr; |
| 71 | + } |
| 72 | + |
| 73 | + std::uint32_t fileSize = std::filesystem::file_size(filePath); |
| 74 | + |
| 75 | + std::vector<int8_t> fifoData(fileSize); |
| 76 | + data.read(reinterpret_cast<char*>(fifoData.data()), fileSize); |
| 77 | + |
| 78 | + auto result = sEffectFifoData.emplace(uniqueEffectId, std::move(fifoData)); |
| 79 | + |
| 80 | + return std::make_unique<effect_stream>(effectId, fileSize, kDefaultPlayRateHz, |
| 81 | + result.first->second.data()); |
| 82 | +} |
| 83 | + |
| 84 | +} // namespace |
| 85 | + |
| 86 | +const struct effect_stream* get_effect_stream(uint32_t effectId) { |
| 87 | + auto it = sEffectStreams.find(effectId); |
| 88 | + if (it == sEffectStreams.end()) { |
| 89 | + std::unique_ptr<effect_stream> newEffectStream = readEffectStreamFromFile(effectId); |
| 90 | + |
| 91 | + if (newEffectStream) { |
| 92 | + auto result = sEffectStreams.emplace(effectId, *newEffectStream); |
| 93 | + return &result.first->second; |
129 | 94 | }
|
| 95 | + } else { |
| 96 | + return &it->second; |
130 | 97 | }
|
131 | 98 |
|
132 |
| - return NULL; |
| 99 | + return nullptr; |
133 | 100 | }
|
0 commit comments