|
18 | 18 | namespace ams::bluetooth {
|
19 | 19 |
|
20 | 20 | CircularBuffer::CircularBuffer() {
|
21 |
| - this->readOffset = 0; |
22 |
| - this->writeOffset = 0; |
23 |
| - this->isInitialized = false; |
24 |
| - this->event = nullptr; |
| 21 | + m_read_offset = 0; |
| 22 | + m_write_offset = 0; |
| 23 | + m_initialized = false; |
| 24 | + m_event = nullptr; |
25 | 25 | }
|
26 | 26 |
|
27 | 27 | void CircularBuffer::Initialize(const char *name) {
|
28 |
| - if (!name || this->isInitialized) |
29 |
| - fatalThrow(-1); |
30 |
| - |
31 |
| - this->readOffset = 0; |
32 |
| - this->writeOffset = 0; |
33 |
| - std::strncpy(this->name, name, sizeof(this->name) - 1); |
34 |
| - this->_unk1 = 0; |
35 |
| - this->size = BLUETOOTH_BUFFER_SIZE; |
36 |
| - this->isInitialized = true; |
| 28 | + AMS_ABORT_UNLESS(!(m_initialized || name == nullptr)); |
| 29 | + |
| 30 | + m_read_offset = 0; |
| 31 | + m_write_offset = 0; |
| 32 | + std::strncpy(m_name, name, CircularBuffer::MaxNameLength); |
| 33 | + m_name[CircularBuffer::MaxNameLength] = '\0'; |
| 34 | + m_size = CircularBuffer::BufferSize; |
| 35 | + m_initialized = true; |
37 | 36 | }
|
38 | 37 |
|
39 | 38 | void CircularBuffer::Finalize() {
|
40 |
| - if (!this->isInitialized) |
41 |
| - fatalThrow(-1); |
| 39 | + AMS_ABORT_UNLESS(m_initialized); |
42 | 40 |
|
43 |
| - this->isInitialized = false; |
44 |
| - this->event = nullptr; |
| 41 | + m_initialized = false; |
| 42 | + m_event = nullptr; |
45 | 43 | }
|
46 | 44 |
|
47 | 45 | bool CircularBuffer::IsInitialized() {
|
48 |
| - return this->isInitialized; |
| 46 | + return m_initialized; |
49 | 47 | }
|
50 | 48 |
|
51 | 49 | u64 CircularBuffer::GetWriteableSize() {
|
52 |
| - u32 readOffset = this->readOffset; |
53 |
| - u32 writeOffset = this->writeOffset; |
54 |
| - |
55 |
| - if (!this->isInitialized) { |
| 50 | + if (!m_initialized) { |
56 | 51 | return 0;
|
57 | 52 | }
|
58 | 53 |
|
| 54 | + u32 read_offset = this->_getReadOffset(); |
| 55 | + u32 write_offset = this->_getWriteOffset(); |
| 56 | + |
59 | 57 | u64 size;
|
60 |
| - if (readOffset <= writeOffset) { |
61 |
| - size = (BLUETOOTH_BUFFER_SIZE - 1) - writeOffset + readOffset; |
| 58 | + if (read_offset <= write_offset) { |
| 59 | + size = (CircularBuffer::BufferSize - 1) - write_offset + read_offset; |
62 | 60 | } else {
|
63 |
| - size = readOffset - writeOffset - 1; |
| 61 | + size = read_offset - write_offset - 1; |
64 | 62 | }
|
65 | 63 |
|
66 |
| - if (size > BLUETOOTH_BUFFER_SIZE) { |
| 64 | + if (size > CircularBuffer::BufferSize) { |
67 | 65 | size = 0;
|
68 | 66 | }
|
69 | 67 |
|
70 | 68 | return size;
|
71 | 69 | }
|
72 | 70 |
|
73 | 71 | void CircularBuffer::SetWriteCompleteEvent(os::EventType *event) {
|
74 |
| - this->event = event; |
| 72 | + m_event = event; |
75 | 73 | }
|
76 | 74 |
|
77 |
| - u64 CircularBuffer::Write(u8 type, void *data, size_t size) { |
78 |
| - |
79 |
| - if (!this->isInitialized) { |
80 |
| - return -1; |
| 75 | + Result CircularBuffer::Write(u8 type, const void *data, size_t size) { |
| 76 | + if (!m_initialized) { |
| 77 | + R_RETURN(-1); |
81 | 78 | }
|
82 | 79 |
|
83 |
| - std::scoped_lock lk(this->mutex); |
| 80 | + std::scoped_lock lk(m_mutex); |
84 | 81 |
|
85 | 82 | ON_SCOPE_EXIT {
|
86 |
| - if (this->event) |
87 |
| - os::SignalEvent(this->event); |
88 |
| - }; |
89 |
| - |
90 |
| - if (size + sizeof(CircularBufferPacketHeader) <= this->GetWriteableSize()) { |
91 |
| - if (size + 2*sizeof(CircularBufferPacketHeader) > BLUETOOTH_BUFFER_SIZE - this->writeOffset) { |
92 |
| - if (const auto res = this->_write(0xff, nullptr, (BLUETOOTH_BUFFER_SIZE - this->writeOffset) - sizeof(CircularBufferPacketHeader)); res != 0) { |
93 |
| - return res; |
94 |
| - } |
| 83 | + if (m_event) { |
| 84 | + os::SignalEvent(m_event); |
95 | 85 | }
|
| 86 | + }; |
96 | 87 |
|
97 |
| - if (const auto res = this->_write(type, data, size); res != 0) { |
98 |
| - return res; |
99 |
| - } |
100 |
| - this->_updateUtilization(); |
| 88 | + if (size + sizeof(CircularBufferPacketHeader) > this->GetWriteableSize()) { |
| 89 | + R_RETURN(-1); |
| 90 | + } |
101 | 91 |
|
102 |
| - return 0; |
| 92 | + u32 write_offset = this->_getWriteOffset(); |
| 93 | + if (size + 2*sizeof(CircularBufferPacketHeader) > CircularBuffer::BufferSize - write_offset) { |
| 94 | + R_TRY(this->_write(0xff, nullptr, (CircularBuffer::BufferSize - write_offset) - sizeof(CircularBufferPacketHeader))); |
103 | 95 | }
|
104 | 96 |
|
105 |
| - return -1; |
| 97 | + R_TRY(this->_write(type, data, size)); |
| 98 | + |
| 99 | + this->_updateUtilization(); |
| 100 | + |
| 101 | + R_SUCCEED(); |
106 | 102 | }
|
107 | 103 |
|
108 |
| - void CircularBuffer::DiscardOldPackets(u8 type, u32 ageLimit) { |
109 |
| - if (this->isInitialized) { |
| 104 | + void CircularBuffer::DiscardOldPackets(u8 type, u32 age_limit) { |
| 105 | + while (m_initialized) { |
| 106 | + u32 read_offset = this->_getReadOffset(); |
| 107 | + u32 write_offset = this->_getWriteOffset(); |
110 | 108 |
|
111 |
| - CircularBufferPacket *packet; |
112 |
| - TimeSpan timespan; |
113 |
| - do { |
114 |
| - if (this->readOffset == this->writeOffset) { |
115 |
| - return; |
116 |
| - } |
| 109 | + if (read_offset == write_offset) { |
| 110 | + return; |
| 111 | + } |
117 | 112 |
|
118 |
| - packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]); |
119 |
| - if (packet->header.type != 0xff) { |
| 113 | + auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]); |
| 114 | + if (packet->header.type != 0xff) { |
120 | 115 |
|
121 |
| - if (packet->header.type != type) { |
122 |
| - return; |
123 |
| - } |
| 116 | + if (packet->header.type != type) { |
| 117 | + return; |
| 118 | + } |
124 | 119 |
|
125 |
| - timespan = os::ConvertToTimeSpan(os::GetSystemTick() - packet->header.timestamp); |
126 |
| - if (timespan.GetMilliSeconds() <= ageLimit) { |
127 |
| - return; |
128 |
| - } |
| 120 | + TimeSpan timespan = os::ConvertToTimeSpan(os::GetSystemTick() - packet->header.timestamp); |
| 121 | + if (timespan.GetMilliSeconds() <= age_limit) { |
| 122 | + return; |
129 | 123 | }
|
| 124 | + } |
| 125 | + |
| 126 | + u32 new_offset = read_offset + packet->header.size + sizeof(packet->header); |
| 127 | + if (new_offset >= CircularBuffer::BufferSize) { |
| 128 | + new_offset = 0; |
| 129 | + } |
130 | 130 |
|
131 |
| - this->Free(); |
132 |
| - } while (this->isInitialized); |
| 131 | + this->_setReadOffset(new_offset); |
133 | 132 | }
|
134 | 133 | }
|
135 | 134 |
|
136 | 135 | CircularBufferPacket *CircularBuffer::Read() {
|
137 | 136 | return this->_read();
|
138 | 137 | }
|
139 | 138 |
|
140 |
| - u64 CircularBuffer::Free() { |
141 |
| - if (!this->isInitialized) { |
142 |
| - return -1; |
143 |
| - } |
144 |
| - |
145 |
| - if (this->readOffset == this->writeOffset) { |
146 |
| - return -1; |
| 139 | + Result CircularBuffer::Free() { |
| 140 | + if (!m_initialized) { |
| 141 | + R_RETURN(-1); |
147 | 142 | }
|
148 | 143 |
|
149 |
| - auto packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]); |
150 |
| - u32 newOffset = this->readOffset + packet->header.size + sizeof(packet->header); |
| 144 | + u32 read_offset = this->_getReadOffset(); |
| 145 | + u32 write_offset = this->_getWriteOffset(); |
151 | 146 |
|
152 |
| - if (newOffset >= BLUETOOTH_BUFFER_SIZE) { |
153 |
| - newOffset = 0; |
| 147 | + if (read_offset == write_offset) { |
| 148 | + R_RETURN(-1); |
154 | 149 | }
|
155 | 150 |
|
156 |
| - if (newOffset < BLUETOOTH_BUFFER_SIZE) { |
157 |
| - this->readOffset = newOffset; |
158 |
| - return 0; |
| 151 | + auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]); |
| 152 | + u32 new_offset = read_offset + packet->header.size + sizeof(packet->header); |
| 153 | + if (new_offset >= CircularBuffer::BufferSize) { |
| 154 | + new_offset = 0; |
159 | 155 | }
|
160 | 156 |
|
161 |
| - fatalThrow(-1); |
| 157 | + this->_setReadOffset(new_offset); |
| 158 | + |
| 159 | + R_SUCCEED(); |
162 | 160 | }
|
163 | 161 |
|
164 | 162 | void CircularBuffer::_setReadOffset(u32 offset) {
|
165 |
| - if (offset >= BLUETOOTH_BUFFER_SIZE) { |
166 |
| - fatalThrow(-1); |
167 |
| - } |
| 163 | + AMS_ABORT_UNLESS(offset < CircularBuffer::BufferSize); |
168 | 164 |
|
169 |
| - this->readOffset = offset; |
| 165 | + m_read_offset = offset; |
170 | 166 | }
|
171 | 167 |
|
172 | 168 | void CircularBuffer::_setWriteOffset(u32 offset) {
|
173 |
| - if (offset >= BLUETOOTH_BUFFER_SIZE) { |
174 |
| - fatalThrow(-1); |
175 |
| - } |
| 169 | + AMS_ABORT_UNLESS(offset < CircularBuffer::BufferSize); |
176 | 170 |
|
177 |
| - this->writeOffset = offset; |
| 171 | + m_write_offset = offset; |
178 | 172 | }
|
179 | 173 |
|
180 | 174 | u32 CircularBuffer::_getWriteOffset() {
|
181 |
| - return this->writeOffset; |
| 175 | + return m_write_offset; |
182 | 176 | }
|
183 | 177 |
|
184 | 178 | u32 CircularBuffer::_getReadOffset() {
|
185 |
| - return this->readOffset; |
| 179 | + return m_read_offset; |
186 | 180 | }
|
187 | 181 |
|
188 |
| - u64 CircularBuffer::_write(u8 type, void *data, size_t size) { |
189 |
| - auto packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->writeOffset]); |
| 182 | + Result CircularBuffer::_write(u8 type, const void *data, size_t size) { |
| 183 | + u32 write_offset = this->_getWriteOffset(); |
| 184 | + |
| 185 | + auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[write_offset]); |
190 | 186 | packet->header.type = type;
|
191 | 187 | packet->header.timestamp = os::GetSystemTick();
|
192 | 188 | packet->header.size = size;
|
193 | 189 |
|
194 | 190 | if (type != 0xff) {
|
195 |
| - if (data && (size > 0)) { |
196 |
| - memcpy(&packet->data, data, size); |
197 |
| - } else { |
198 |
| - return -1; |
| 191 | + if (!(data && size)) { |
| 192 | + R_RETURN(-1); |
199 | 193 | }
|
200 |
| - } |
201 | 194 |
|
202 |
| - u32 newOffset = this->writeOffset + size + sizeof(CircularBufferPacketHeader); |
203 |
| - if (newOffset > BLUETOOTH_BUFFER_SIZE) { |
204 |
| - return -1; |
| 195 | + memcpy(&packet->data, data, size); |
205 | 196 | }
|
206 | 197 |
|
207 |
| - if (newOffset == BLUETOOTH_BUFFER_SIZE) { |
208 |
| - this->writeOffset = 0; |
209 |
| - } else { |
210 |
| - this->writeOffset = newOffset; |
| 198 | + u32 new_offset = write_offset + size + sizeof(CircularBufferPacketHeader); |
| 199 | + if (new_offset == CircularBuffer::BufferSize) { |
| 200 | + new_offset = 0; |
| 201 | + } else if (new_offset > CircularBuffer::BufferSize) { |
| 202 | + R_RETURN(-1); |
211 | 203 | }
|
212 | 204 |
|
213 |
| - return 0; |
| 205 | + this->_setWriteOffset(new_offset); |
| 206 | + |
| 207 | + R_SUCCEED(); |
214 | 208 | }
|
215 | 209 |
|
216 | 210 | void CircularBuffer::_updateUtilization() {
|
217 |
| - u32 newCapacity = this->isInitialized ? this->GetWriteableSize() : 0; |
| 211 | + u32 new_capacity = m_initialized ? this->GetWriteableSize() : 0; |
218 | 212 |
|
219 |
| - if (this->size > newCapacity + 1000) { |
220 |
| - this->size = newCapacity; |
| 213 | + if (m_size > new_capacity + 1000) { |
| 214 | + m_size = new_capacity; |
221 | 215 | }
|
222 | 216 | }
|
223 | 217 |
|
224 | 218 | CircularBufferPacket *CircularBuffer::_read() {
|
225 |
| - if (this->isInitialized) { |
226 |
| - CircularBufferPacket *packet; |
227 |
| - u32 newOffset; |
228 |
| - do { |
229 |
| - if (this->readOffset == this->writeOffset) { |
230 |
| - return nullptr; |
231 |
| - } |
232 |
| - |
233 |
| - packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]); |
| 219 | + while (m_initialized) { |
| 220 | + u32 read_offset = this->_getReadOffset(); |
| 221 | + u32 write_offset = this->_getWriteOffset(); |
234 | 222 |
|
235 |
| - if (packet->header.type != 0xff) { |
236 |
| - return packet; |
237 |
| - } |
| 223 | + if (read_offset == write_offset) { |
| 224 | + break; |
| 225 | + } |
238 | 226 |
|
239 |
| - if (!this->isInitialized) { |
240 |
| - return nullptr; |
241 |
| - } |
| 227 | + auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]); |
242 | 228 |
|
243 |
| - if (this->readOffset != this->writeOffset) { |
244 |
| - newOffset = this->readOffset + packet->header.size + sizeof(packet->header); |
245 |
| - if (newOffset >= BLUETOOTH_BUFFER_SIZE) { |
246 |
| - newOffset = 0; |
247 |
| - } |
| 229 | + if (packet->header.type != 0xff) { |
| 230 | + return packet; |
| 231 | + } |
248 | 232 |
|
249 |
| - this->_setReadOffset(newOffset); |
250 |
| - } |
| 233 | + u32 new_offset = read_offset + packet->header.size + sizeof(packet->header); |
| 234 | + if (new_offset >= CircularBuffer::BufferSize) { |
| 235 | + new_offset = 0; |
| 236 | + } |
251 | 237 |
|
252 |
| - } while (this->isInitialized); |
253 |
| - } |
| 238 | + this->_setReadOffset(new_offset); |
| 239 | + }; |
254 | 240 |
|
255 | 241 | return nullptr;
|
256 | 242 | }
|
|
0 commit comments