mirror of
https://github.com/ndeadly/MissionControl
synced 2025-02-16 13:18:27 +00:00
mc.mitm: update bluetooth circular buffer code style and simplify logic
This commit is contained in:
parent
2e67e80675
commit
b993d8ef82
3 changed files with 165 additions and 175 deletions
|
@ -18,52 +18,50 @@
|
|||
namespace ams::bluetooth {
|
||||
|
||||
CircularBuffer::CircularBuffer() {
|
||||
this->readOffset = 0;
|
||||
this->writeOffset = 0;
|
||||
this->isInitialized = false;
|
||||
this->event = nullptr;
|
||||
m_read_offset = 0;
|
||||
m_write_offset = 0;
|
||||
m_initialized = false;
|
||||
m_event = nullptr;
|
||||
}
|
||||
|
||||
void CircularBuffer::Initialize(const char *name) {
|
||||
if (!name || this->isInitialized)
|
||||
fatalThrow(-1);
|
||||
AMS_ABORT_UNLESS(!(m_initialized || name == nullptr));
|
||||
|
||||
this->readOffset = 0;
|
||||
this->writeOffset = 0;
|
||||
std::strncpy(this->name, name, sizeof(this->name) - 1);
|
||||
this->_unk1 = 0;
|
||||
this->size = BLUETOOTH_BUFFER_SIZE;
|
||||
this->isInitialized = true;
|
||||
m_read_offset = 0;
|
||||
m_write_offset = 0;
|
||||
std::strncpy(m_name, name, CircularBuffer::MaxNameLength);
|
||||
m_name[CircularBuffer::MaxNameLength] = '\0';
|
||||
m_size = CircularBuffer::BufferSize;
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
void CircularBuffer::Finalize() {
|
||||
if (!this->isInitialized)
|
||||
fatalThrow(-1);
|
||||
AMS_ABORT_UNLESS(m_initialized);
|
||||
|
||||
this->isInitialized = false;
|
||||
this->event = nullptr;
|
||||
m_initialized = false;
|
||||
m_event = nullptr;
|
||||
}
|
||||
|
||||
bool CircularBuffer::IsInitialized() {
|
||||
return this->isInitialized;
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
u64 CircularBuffer::GetWriteableSize() {
|
||||
u32 readOffset = this->readOffset;
|
||||
u32 writeOffset = this->writeOffset;
|
||||
|
||||
if (!this->isInitialized) {
|
||||
if (!m_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 read_offset = this->_getReadOffset();
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
|
||||
u64 size;
|
||||
if (readOffset <= writeOffset) {
|
||||
size = (BLUETOOTH_BUFFER_SIZE - 1) - writeOffset + readOffset;
|
||||
if (read_offset <= write_offset) {
|
||||
size = (CircularBuffer::BufferSize - 1) - write_offset + read_offset;
|
||||
} else {
|
||||
size = readOffset - writeOffset - 1;
|
||||
size = read_offset - write_offset - 1;
|
||||
}
|
||||
|
||||
if (size > BLUETOOTH_BUFFER_SIZE) {
|
||||
if (size > CircularBuffer::BufferSize) {
|
||||
size = 0;
|
||||
}
|
||||
|
||||
|
@ -71,65 +69,66 @@ namespace ams::bluetooth {
|
|||
}
|
||||
|
||||
void CircularBuffer::SetWriteCompleteEvent(os::EventType *event) {
|
||||
this->event = event;
|
||||
m_event = event;
|
||||
}
|
||||
|
||||
u64 CircularBuffer::Write(u8 type, void *data, size_t size) {
|
||||
|
||||
if (!this->isInitialized) {
|
||||
return -1;
|
||||
Result CircularBuffer::Write(u8 type, const void *data, size_t size) {
|
||||
if (!m_initialized) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
std::scoped_lock lk(this->mutex);
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
if (this->event)
|
||||
os::SignalEvent(this->event);
|
||||
if (m_event) {
|
||||
os::SignalEvent(m_event);
|
||||
}
|
||||
};
|
||||
|
||||
if (size + sizeof(CircularBufferPacketHeader) <= this->GetWriteableSize()) {
|
||||
if (size + 2*sizeof(CircularBufferPacketHeader) > BLUETOOTH_BUFFER_SIZE - this->writeOffset) {
|
||||
if (const auto res = this->_write(0xff, nullptr, (BLUETOOTH_BUFFER_SIZE - this->writeOffset) - sizeof(CircularBufferPacketHeader)); res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto res = this->_write(type, data, size); res != 0) {
|
||||
return res;
|
||||
}
|
||||
this->_updateUtilization();
|
||||
|
||||
return 0;
|
||||
if (size + sizeof(CircularBufferPacketHeader) > this->GetWriteableSize()) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
if (size + 2*sizeof(CircularBufferPacketHeader) > CircularBuffer::BufferSize - write_offset) {
|
||||
R_TRY(this->_write(0xff, nullptr, (CircularBuffer::BufferSize - write_offset) - sizeof(CircularBufferPacketHeader)));
|
||||
}
|
||||
|
||||
R_TRY(this->_write(type, data, size));
|
||||
|
||||
this->_updateUtilization();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void CircularBuffer::DiscardOldPackets(u8 type, u32 ageLimit) {
|
||||
if (this->isInitialized) {
|
||||
void CircularBuffer::DiscardOldPackets(u8 type, u32 age_limit) {
|
||||
while (m_initialized) {
|
||||
u32 read_offset = this->_getReadOffset();
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
|
||||
CircularBufferPacket *packet;
|
||||
TimeSpan timespan;
|
||||
do {
|
||||
if (this->readOffset == this->writeOffset) {
|
||||
if (read_offset == write_offset) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]);
|
||||
if (packet->header.type != 0xff) {
|
||||
|
||||
if (packet->header.type != type) {
|
||||
return;
|
||||
}
|
||||
|
||||
packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]);
|
||||
if (packet->header.type != 0xff) {
|
||||
|
||||
if (packet->header.type != type) {
|
||||
return;
|
||||
}
|
||||
|
||||
timespan = os::ConvertToTimeSpan(os::GetSystemTick() - packet->header.timestamp);
|
||||
if (timespan.GetMilliSeconds() <= ageLimit) {
|
||||
return;
|
||||
}
|
||||
TimeSpan timespan = os::ConvertToTimeSpan(os::GetSystemTick() - packet->header.timestamp);
|
||||
if (timespan.GetMilliSeconds() <= age_limit) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this->Free();
|
||||
} while (this->isInitialized);
|
||||
u32 new_offset = read_offset + packet->header.size + sizeof(packet->header);
|
||||
if (new_offset >= CircularBuffer::BufferSize) {
|
||||
new_offset = 0;
|
||||
}
|
||||
|
||||
this->_setReadOffset(new_offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,120 +136,107 @@ namespace ams::bluetooth {
|
|||
return this->_read();
|
||||
}
|
||||
|
||||
u64 CircularBuffer::Free() {
|
||||
if (!this->isInitialized) {
|
||||
return -1;
|
||||
Result CircularBuffer::Free() {
|
||||
if (!m_initialized) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
if (this->readOffset == this->writeOffset) {
|
||||
return -1;
|
||||
u32 read_offset = this->_getReadOffset();
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
|
||||
if (read_offset == write_offset) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]);
|
||||
u32 newOffset = this->readOffset + packet->header.size + sizeof(packet->header);
|
||||
|
||||
if (newOffset >= BLUETOOTH_BUFFER_SIZE) {
|
||||
newOffset = 0;
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]);
|
||||
u32 new_offset = read_offset + packet->header.size + sizeof(packet->header);
|
||||
if (new_offset >= CircularBuffer::BufferSize) {
|
||||
new_offset = 0;
|
||||
}
|
||||
|
||||
if (newOffset < BLUETOOTH_BUFFER_SIZE) {
|
||||
this->readOffset = newOffset;
|
||||
return 0;
|
||||
}
|
||||
this->_setReadOffset(new_offset);
|
||||
|
||||
fatalThrow(-1);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void CircularBuffer::_setReadOffset(u32 offset) {
|
||||
if (offset >= BLUETOOTH_BUFFER_SIZE) {
|
||||
fatalThrow(-1);
|
||||
}
|
||||
AMS_ABORT_UNLESS(offset < CircularBuffer::BufferSize);
|
||||
|
||||
this->readOffset = offset;
|
||||
m_read_offset = offset;
|
||||
}
|
||||
|
||||
void CircularBuffer::_setWriteOffset(u32 offset) {
|
||||
if (offset >= BLUETOOTH_BUFFER_SIZE) {
|
||||
fatalThrow(-1);
|
||||
}
|
||||
AMS_ABORT_UNLESS(offset < CircularBuffer::BufferSize);
|
||||
|
||||
this->writeOffset = offset;
|
||||
m_write_offset = offset;
|
||||
}
|
||||
|
||||
u32 CircularBuffer::_getWriteOffset() {
|
||||
return this->writeOffset;
|
||||
return m_write_offset;
|
||||
}
|
||||
|
||||
u32 CircularBuffer::_getReadOffset() {
|
||||
return this->readOffset;
|
||||
return m_read_offset;
|
||||
}
|
||||
|
||||
u64 CircularBuffer::_write(u8 type, void *data, size_t size) {
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->writeOffset]);
|
||||
Result CircularBuffer::_write(u8 type, const void *data, size_t size) {
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[write_offset]);
|
||||
packet->header.type = type;
|
||||
packet->header.timestamp = os::GetSystemTick();
|
||||
packet->header.size = size;
|
||||
|
||||
if (type != 0xff) {
|
||||
if (data && (size > 0)) {
|
||||
memcpy(&packet->data, data, size);
|
||||
} else {
|
||||
return -1;
|
||||
if (!(data && size)) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
memcpy(&packet->data, data, size);
|
||||
}
|
||||
|
||||
u32 newOffset = this->writeOffset + size + sizeof(CircularBufferPacketHeader);
|
||||
if (newOffset > BLUETOOTH_BUFFER_SIZE) {
|
||||
return -1;
|
||||
u32 new_offset = write_offset + size + sizeof(CircularBufferPacketHeader);
|
||||
if (new_offset == CircularBuffer::BufferSize) {
|
||||
new_offset = 0;
|
||||
} else if (new_offset > CircularBuffer::BufferSize) {
|
||||
R_RETURN(-1);
|
||||
}
|
||||
|
||||
if (newOffset == BLUETOOTH_BUFFER_SIZE) {
|
||||
this->writeOffset = 0;
|
||||
} else {
|
||||
this->writeOffset = newOffset;
|
||||
}
|
||||
this->_setWriteOffset(new_offset);
|
||||
|
||||
return 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void CircularBuffer::_updateUtilization() {
|
||||
u32 newCapacity = this->isInitialized ? this->GetWriteableSize() : 0;
|
||||
u32 new_capacity = m_initialized ? this->GetWriteableSize() : 0;
|
||||
|
||||
if (this->size > newCapacity + 1000) {
|
||||
this->size = newCapacity;
|
||||
if (m_size > new_capacity + 1000) {
|
||||
m_size = new_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
CircularBufferPacket *CircularBuffer::_read() {
|
||||
if (this->isInitialized) {
|
||||
CircularBufferPacket *packet;
|
||||
u32 newOffset;
|
||||
do {
|
||||
if (this->readOffset == this->writeOffset) {
|
||||
return nullptr;
|
||||
}
|
||||
while (m_initialized) {
|
||||
u32 read_offset = this->_getReadOffset();
|
||||
u32 write_offset = this->_getWriteOffset();
|
||||
|
||||
packet = reinterpret_cast<CircularBufferPacket *>(&this->data[this->readOffset]);
|
||||
if (read_offset == write_offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet->header.type != 0xff) {
|
||||
return packet;
|
||||
}
|
||||
auto packet = reinterpret_cast<CircularBufferPacket *>(&m_data[read_offset]);
|
||||
|
||||
if (!this->isInitialized) {
|
||||
return nullptr;
|
||||
}
|
||||
if (packet->header.type != 0xff) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
if (this->readOffset != this->writeOffset) {
|
||||
newOffset = this->readOffset + packet->header.size + sizeof(packet->header);
|
||||
if (newOffset >= BLUETOOTH_BUFFER_SIZE) {
|
||||
newOffset = 0;
|
||||
}
|
||||
u32 new_offset = read_offset + packet->header.size + sizeof(packet->header);
|
||||
if (new_offset >= CircularBuffer::BufferSize) {
|
||||
new_offset = 0;
|
||||
}
|
||||
|
||||
this->_setReadOffset(newOffset);
|
||||
}
|
||||
|
||||
} while (this->isInitialized);
|
||||
}
|
||||
this->_setReadOffset(new_offset);
|
||||
};
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -21,29 +21,21 @@
|
|||
|
||||
namespace ams::bluetooth {
|
||||
|
||||
constexpr int BLUETOOTH_BUFFER_SIZE = 10000;
|
||||
|
||||
enum CircularBufferType {
|
||||
CircularBufferType_Other,
|
||||
CircularBufferType_HidReport,
|
||||
CircularBufferType_Bluetooth,
|
||||
CircularBufferType_Ble,
|
||||
CircularBufferType_BleCore,
|
||||
CircularBufferType_BleHid,
|
||||
};
|
||||
|
||||
struct CircularBufferPacketHeader{
|
||||
struct CircularBufferPacketHeader {
|
||||
u8 type;
|
||||
os::Tick timestamp;
|
||||
u64 size;
|
||||
};
|
||||
|
||||
struct CircularBufferPacket{
|
||||
struct CircularBufferPacket {
|
||||
CircularBufferPacketHeader header;
|
||||
HidReportEventInfo data;
|
||||
};
|
||||
|
||||
class CircularBuffer {
|
||||
public:
|
||||
static constexpr size_t BufferSize = 10000;
|
||||
static constexpr size_t MaxNameLength = 16;
|
||||
|
||||
public:
|
||||
CircularBuffer();
|
||||
|
@ -53,36 +45,45 @@ namespace ams::bluetooth {
|
|||
bool IsInitialized();
|
||||
u64 GetWriteableSize();
|
||||
void SetWriteCompleteEvent(os::EventType *event);
|
||||
u64 Write(u8 type, void *data, size_t size);
|
||||
void DiscardOldPackets(u8 type, u32 ageLimit);
|
||||
Result Write(u8 type, const void *data, size_t size);
|
||||
void DiscardOldPackets(u8 type, u32 age_limit);
|
||||
CircularBufferPacket *Read();
|
||||
u64 Free();
|
||||
Result Free();
|
||||
|
||||
private:
|
||||
void _setReadOffset(u32 offset);
|
||||
void _setWriteOffset(u32 offset);
|
||||
u32 _getWriteOffset();
|
||||
u32 _getReadOffset();
|
||||
u64 _write(u8 type, void *data, size_t size);
|
||||
void _updateUtilization();
|
||||
CircularBufferPacket *_read();
|
||||
ALWAYS_INLINE void _setReadOffset(u32 offset);
|
||||
ALWAYS_INLINE void _setWriteOffset(u32 offset);
|
||||
ALWAYS_INLINE u32 _getWriteOffset();
|
||||
ALWAYS_INLINE u32 _getReadOffset();
|
||||
ALWAYS_INLINE Result _write(u8 type, const void *data, size_t size);
|
||||
ALWAYS_INLINE void _updateUtilization();
|
||||
ALWAYS_INLINE CircularBufferPacket *_read();
|
||||
|
||||
os::SdkMutex mutex;
|
||||
os::EventType *event;
|
||||
|
||||
u8 data[BLUETOOTH_BUFFER_SIZE];
|
||||
std::atomic<u32> writeOffset;
|
||||
std::atomic<u32> readOffset;
|
||||
s64 size;
|
||||
char name[16];
|
||||
u8 _unk1;
|
||||
bool isInitialized;
|
||||
u8 _unk2[6];
|
||||
private:
|
||||
os::SdkMutex m_mutex;
|
||||
os::EventType *m_event;
|
||||
|
||||
public:
|
||||
CircularBufferType type;
|
||||
bool _unk3;
|
||||
//u8 _unk3[4];
|
||||
u8 m_data[BufferSize];
|
||||
util::Atomic<u32> m_write_offset;
|
||||
util::Atomic<u32> m_read_offset;
|
||||
s64 m_size;
|
||||
char m_name[MaxNameLength + 1];
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
enum EventBufferType {
|
||||
EventBufferType_None,
|
||||
EventBufferType_HidReport,
|
||||
EventBufferType_Bluetooth,
|
||||
EventBufferType_Ble,
|
||||
EventBufferType_BleCore,
|
||||
EventBufferType_BleHid,
|
||||
};
|
||||
|
||||
struct BufferedEventInfo {
|
||||
CircularBuffer buffer;
|
||||
EventBufferType type;
|
||||
bool ready;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -129,10 +129,13 @@ namespace ams::bluetooth::hid::report {
|
|||
|
||||
Result InitializeReportBuffer() {
|
||||
g_fake_bt_shmem.Map(os::MemoryPermission_ReadWrite);
|
||||
g_fake_buffer = reinterpret_cast<bluetooth::CircularBuffer *>(g_fake_bt_shmem.GetMappedAddress());
|
||||
g_fake_buffer->Initialize("HID Report");
|
||||
g_fake_buffer->type = bluetooth::CircularBufferType_HidReport;
|
||||
g_fake_buffer->_unk3 = 1;
|
||||
|
||||
auto event_info = reinterpret_cast<bluetooth::BufferedEventInfo *>(g_fake_bt_shmem.GetMappedAddress());
|
||||
event_info->buffer.Initialize("HID Report");
|
||||
event_info->type = bluetooth::EventBufferType_HidReport;
|
||||
event_info->ready = true;
|
||||
|
||||
g_fake_buffer = &event_info->buffer;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue