mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 16:32:05 +00:00
uart.mitm: Implemented fs writing with a seperate thread.
This commit is contained in:
parent
2b3c7fd104
commit
1dd9d46415
5 changed files with 398 additions and 119 deletions
252
stratosphere/ams_mitm/source/uart_mitm/uart_mitm_logger.cpp
Normal file
252
stratosphere/ams_mitm/source/uart_mitm/uart_mitm_logger.cpp
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "uart_mitm_logger.hpp"
|
||||||
|
#include "../amsmitm_fs_utils.hpp"
|
||||||
|
|
||||||
|
namespace ams::mitm::uart {
|
||||||
|
|
||||||
|
alignas(os::ThreadStackAlignment) u8 g_logger_stack[0x4000];
|
||||||
|
|
||||||
|
std::shared_ptr<UartLogger> g_logger;
|
||||||
|
|
||||||
|
UartLogger::UartLogger() : m_request_event(os::EventClearMode_ManualClear), m_finish_event(os::EventClearMode_ManualClear), m_client_queue(m_client_queue_list, this->QueueSize), m_thread_queue(m_thread_queue_list, this->QueueSize) {
|
||||||
|
for (size_t i=0; i<this->QueueSize; i++) {
|
||||||
|
UartLogMessage *msg = &this->m_queue_list_msgs[i];
|
||||||
|
std::memset(msg, 0, sizeof(UartLogMessage));
|
||||||
|
|
||||||
|
msg->data = static_cast<u8 *>(std::malloc(this->QueueBufferSize));
|
||||||
|
if (msg->data != nullptr) {
|
||||||
|
std::memset(msg->data, 0, this->QueueBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_client_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create and start the logger thread. */
|
||||||
|
R_ABORT_UNLESS(os::CreateThread(std::addressof(this->m_thread), this->ThreadEntry, this, g_logger_stack, sizeof(g_logger_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(uart, IpcServer) - 2));
|
||||||
|
os::StartThread(std::addressof(this->m_thread));
|
||||||
|
}
|
||||||
|
|
||||||
|
UartLogger::~UartLogger() {
|
||||||
|
/* Tell the logger thread to exit. */
|
||||||
|
UartLogMessage *msg=nullptr;
|
||||||
|
this->m_client_queue.Receive(reinterpret_cast<uintptr_t *>(&msg));
|
||||||
|
|
||||||
|
msg->type = 0;
|
||||||
|
|
||||||
|
this->m_finish_event.Clear();
|
||||||
|
this->m_thread_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
this->m_request_event.Signal();
|
||||||
|
|
||||||
|
/* Wait on the logger thread, then destroy it. */
|
||||||
|
os::WaitThread(std::addressof(this->m_thread));
|
||||||
|
os::DestroyThread(std::addressof(this->m_thread));
|
||||||
|
|
||||||
|
for (size_t i=0; i<this->QueueSize; i++) {
|
||||||
|
UartLogMessage *msg = &this->m_queue_list_msgs[i];
|
||||||
|
std::free(msg->data);
|
||||||
|
msg->data = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UartLogger::ThreadFunction() {
|
||||||
|
bool exit_flag=false;
|
||||||
|
|
||||||
|
this->m_cache_count = 0;
|
||||||
|
this->m_cache_pos = 0;
|
||||||
|
std::memset(this->m_cache_list, 0, sizeof(this->m_cache_list));
|
||||||
|
std::memset(this->m_cache_buffer, 0, sizeof(this->m_cache_buffer));
|
||||||
|
|
||||||
|
while (!exit_flag) {
|
||||||
|
this->m_request_event.Wait();
|
||||||
|
|
||||||
|
/* Receive messages, process them, then Send them. */
|
||||||
|
UartLogMessage *msg=nullptr;
|
||||||
|
while (this->m_thread_queue.TryReceive(reinterpret_cast<uintptr_t *>(&msg))) {
|
||||||
|
if (msg->type==0) {
|
||||||
|
exit_flag = true;
|
||||||
|
}
|
||||||
|
else if (msg->type==1) {
|
||||||
|
this->WriteCache(msg);
|
||||||
|
}
|
||||||
|
else if (msg->type==2) {
|
||||||
|
this->WriteCmdLog(reinterpret_cast<const char*>(msg->data), reinterpret_cast<const char*>(&msg->data[std::strlen((const char*)msg->data)+1]), msg->file_pos);
|
||||||
|
}
|
||||||
|
else if (msg->type==3) {
|
||||||
|
this->FlushCache();
|
||||||
|
}
|
||||||
|
this->m_client_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_request_event.Clear();
|
||||||
|
this->m_finish_event.Signal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the thread to finish processing messages. */
|
||||||
|
void UartLogger::WaitFinished() {
|
||||||
|
/* Tell the thread to flush the cache. */
|
||||||
|
UartLogMessage *msg=nullptr;
|
||||||
|
this->m_client_queue.Receive(reinterpret_cast<uintptr_t *>(&msg));
|
||||||
|
|
||||||
|
msg->type = 3;
|
||||||
|
|
||||||
|
this->m_finish_event.Clear();
|
||||||
|
this->m_thread_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
this->m_request_event.Signal();
|
||||||
|
|
||||||
|
/* Wait for processing to finish. */
|
||||||
|
m_finish_event.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the specified btsnoop log file. */
|
||||||
|
void UartLogger::InitializeDataLog(FsFile *f, size_t *datalog_pos) {
|
||||||
|
*datalog_pos = 0;
|
||||||
|
|
||||||
|
/* Setup the btsnoop header. */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
char id[8];
|
||||||
|
u32 version;
|
||||||
|
u32 datalink_type;
|
||||||
|
} btsnoop_header = { .id = "btsnoop" };
|
||||||
|
|
||||||
|
u32 version = 1;
|
||||||
|
u32 datalink_type = 1002; /* HCI UART (H4) */
|
||||||
|
ams::util::StoreBigEndian(&btsnoop_header.version, version);
|
||||||
|
ams::util::StoreBigEndian(&btsnoop_header.datalink_type, datalink_type);
|
||||||
|
|
||||||
|
/* Write the btsnoop header to the datalog. */
|
||||||
|
this->WriteLog(f, datalog_pos, &btsnoop_header, sizeof(btsnoop_header));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the cache into the file. */
|
||||||
|
void UartLogger::FlushCache() {
|
||||||
|
for (size_t i=0; i<this->m_cache_count; i++) {
|
||||||
|
UartLogMessage *cache_msg=&this->m_cache_list[i];
|
||||||
|
this->WriteLogPacket(cache_msg->datalog_file, cache_msg->file_pos, cache_msg->dir, cache_msg->data, cache_msg->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_cache_count = 0;
|
||||||
|
this->m_cache_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the specified message into the cache. */
|
||||||
|
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
||||||
|
void UartLogger::WriteCache(UartLogMessage *msg) {
|
||||||
|
if (this->m_cache_count >= this->CacheListSize || this->m_cache_pos + msg->size >= this->CacheBufferSize) {
|
||||||
|
this->FlushCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
UartLogMessage *cache_msg=&this->m_cache_list[this->m_cache_count];
|
||||||
|
*cache_msg = *msg;
|
||||||
|
cache_msg->data = &this->m_cache_buffer[this->m_cache_pos];
|
||||||
|
std::memcpy(cache_msg->data, msg->data, msg->size);
|
||||||
|
this->m_cache_count++;
|
||||||
|
this->m_cache_pos+= msg->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the specified string to the text file. */
|
||||||
|
void UartLogger::WriteCmdLog(const char *path, const char *str, size_t *file_pos) {
|
||||||
|
Result rc=0;
|
||||||
|
FsFile file={};
|
||||||
|
size_t len = std::strlen(str);
|
||||||
|
rc = ams::mitm::fs::OpenAtmosphereSdFile(&file, path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
rc = fsFileWrite(&file, *file_pos, str, len, FsWriteOption_None);
|
||||||
|
}
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*file_pos += len;
|
||||||
|
}
|
||||||
|
fsFileClose(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the specified data to the datalog file. */
|
||||||
|
void UartLogger::WriteLog(FsFile *f, size_t *datalog_pos, const void* buffer, size_t size) {
|
||||||
|
if (R_SUCCEEDED(fsFileWrite(f, *datalog_pos, buffer, size, FsWriteOption_None))) {
|
||||||
|
*datalog_pos += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append the specified packet to the datalog via WriteLog. */
|
||||||
|
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
||||||
|
void UartLogger::WriteLogPacket(FsFile *f, size_t *datalog_pos, bool dir, const void* buffer, size_t size) {
|
||||||
|
struct {
|
||||||
|
u32 original_length;
|
||||||
|
u32 included_length;
|
||||||
|
u32 packet_flags;
|
||||||
|
u32 cumulative_drops;
|
||||||
|
s64 timestamp_microseconds;
|
||||||
|
} pkt_hdr = {};
|
||||||
|
|
||||||
|
u32 flags = 0;
|
||||||
|
if (dir) {
|
||||||
|
flags |= BIT(0);
|
||||||
|
}
|
||||||
|
ams::util::StoreBigEndian(&pkt_hdr.original_length, static_cast<u32>(size));
|
||||||
|
ams::util::StoreBigEndian(&pkt_hdr.included_length, static_cast<u32>(size));
|
||||||
|
ams::util::StoreBigEndian(&pkt_hdr.packet_flags, flags);
|
||||||
|
|
||||||
|
/* Currently we leave the timestamp at value 0. */
|
||||||
|
|
||||||
|
this->WriteLog(f, datalog_pos, &pkt_hdr, sizeof(pkt_hdr));
|
||||||
|
this->WriteLog(f, datalog_pos, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the specified data to the Logger thread. */
|
||||||
|
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
||||||
|
void UartLogger::SendLogData(FsFile *f, size_t *file_pos, bool dir, const void* buffer, size_t size) {
|
||||||
|
/* Ignore log data which is too large. */
|
||||||
|
if (size > this->QueueBufferSize) return;
|
||||||
|
|
||||||
|
UartLogMessage *msg=nullptr;
|
||||||
|
this->m_client_queue.Receive(reinterpret_cast<uintptr_t *>(&msg));
|
||||||
|
if (msg->data == nullptr) return;
|
||||||
|
|
||||||
|
/* Setup the msg and send it. */
|
||||||
|
msg->type = 1;
|
||||||
|
msg->dir = dir;
|
||||||
|
msg->datalog_file = f;
|
||||||
|
msg->file_pos = file_pos;
|
||||||
|
msg->size = size;
|
||||||
|
std::memcpy(msg->data, buffer, size);
|
||||||
|
|
||||||
|
this->m_finish_event.Clear();
|
||||||
|
this->m_thread_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
this->m_request_event.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the specified text log to the Logger thread. */
|
||||||
|
void UartLogger::SendTextLogData(const char *path, size_t *file_pos, const char *str) {
|
||||||
|
/* Ignore log data which is too large. */
|
||||||
|
if (std::strlen(path)+1 + std::strlen(str)+1 > this->QueueBufferSize) return;
|
||||||
|
|
||||||
|
UartLogMessage *msg=nullptr;
|
||||||
|
this->m_client_queue.Receive(reinterpret_cast<uintptr_t *>(&msg));
|
||||||
|
if (msg->data == nullptr) return;
|
||||||
|
|
||||||
|
/* Setup the msg and send it. */
|
||||||
|
msg->type = 2;
|
||||||
|
msg->file_pos = file_pos;
|
||||||
|
std::memcpy(msg->data, path, std::strlen(path)+1);
|
||||||
|
std::memcpy(&msg->data[std::strlen(path)+1], str, std::strlen(str)+1);
|
||||||
|
|
||||||
|
this->m_finish_event.Clear();
|
||||||
|
this->m_thread_queue.Send(reinterpret_cast<uintptr_t>(msg));
|
||||||
|
this->m_request_event.Signal();
|
||||||
|
}
|
||||||
|
}
|
74
stratosphere/ams_mitm/source/uart_mitm/uart_mitm_logger.hpp
Normal file
74
stratosphere/ams_mitm/source/uart_mitm/uart_mitm_logger.hpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::mitm::uart {
|
||||||
|
|
||||||
|
struct UartLogMessage {
|
||||||
|
u8 type;
|
||||||
|
bool dir;
|
||||||
|
FsFile *datalog_file;
|
||||||
|
size_t *file_pos;
|
||||||
|
size_t size;
|
||||||
|
u8 *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UartLogger {
|
||||||
|
private:
|
||||||
|
ams::os::ThreadType m_thread;
|
||||||
|
os::Event m_request_event;
|
||||||
|
os::Event m_finish_event;
|
||||||
|
os::MessageQueue m_client_queue;
|
||||||
|
os::MessageQueue m_thread_queue;
|
||||||
|
|
||||||
|
static constexpr inline size_t QueueSize = 0x20;
|
||||||
|
static constexpr inline size_t QueueBufferSize = 0x400;
|
||||||
|
static constexpr inline size_t CacheListSize = 0x80;
|
||||||
|
static constexpr inline size_t CacheBufferSize = 0x1000;
|
||||||
|
|
||||||
|
uintptr_t m_client_queue_list[QueueSize];
|
||||||
|
uintptr_t m_thread_queue_list[QueueSize];
|
||||||
|
UartLogMessage m_queue_list_msgs[QueueSize];
|
||||||
|
|
||||||
|
size_t m_cache_count;
|
||||||
|
size_t m_cache_pos;
|
||||||
|
UartLogMessage m_cache_list[CacheListSize];
|
||||||
|
u8 m_cache_buffer[CacheBufferSize];
|
||||||
|
|
||||||
|
static void ThreadEntry(void *arg) { static_cast<UartLogger *>(arg)->ThreadFunction(); }
|
||||||
|
void ThreadFunction();
|
||||||
|
|
||||||
|
void FlushCache();
|
||||||
|
void WriteCache(UartLogMessage *msg);
|
||||||
|
|
||||||
|
void WriteCmdLog(const char *path, const char *str, size_t *file_pos);
|
||||||
|
void WriteLog(FsFile *f, size_t *datalog_pos, const void* buffer, size_t size);
|
||||||
|
void WriteLogPacket(FsFile *f, size_t *datalog_pos, bool dir, const void* buffer, size_t size);
|
||||||
|
public:
|
||||||
|
UartLogger();
|
||||||
|
~UartLogger();
|
||||||
|
|
||||||
|
void WaitFinished();
|
||||||
|
|
||||||
|
void InitializeDataLog(FsFile *f, size_t *datalog_pos);
|
||||||
|
|
||||||
|
void SendLogData(FsFile *f, size_t *file_pos, bool dir, const void* buffer, size_t size);
|
||||||
|
void SendTextLogData(const char *path, size_t *file_pos, const char *str);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::shared_ptr<UartLogger> g_logger;
|
||||||
|
}
|
|
@ -15,10 +15,9 @@
|
||||||
*/
|
*/
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include "uart_mitm_service.hpp"
|
#include "uart_mitm_service.hpp"
|
||||||
|
#include "uart_mitm_logger.hpp"
|
||||||
#include "../amsmitm_fs_utils.hpp"
|
#include "../amsmitm_fs_utils.hpp"
|
||||||
|
|
||||||
/* TODO: This should really use async fs-writing, there's a slowdown with bluetooth communications with current fs-writing. */
|
|
||||||
|
|
||||||
namespace ams::mitm::uart {
|
namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Helper functions. */
|
/* Helper functions. */
|
||||||
|
@ -41,7 +40,7 @@ namespace ams::mitm::uart {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UartPortService::UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s) : client_info(cl), srv(std::move(s)) {
|
UartPortService::UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s) : m_client_info(cl), m_srv(std::move(s)) {
|
||||||
Result rc=0;
|
Result rc=0;
|
||||||
/* Get a timestamp. */
|
/* Get a timestamp. */
|
||||||
u64 timestamp0=0, timestamp1;
|
u64 timestamp0=0, timestamp1;
|
||||||
|
@ -49,122 +48,66 @@ namespace ams::mitm::uart {
|
||||||
timestamp1 = svcGetSystemTick();
|
timestamp1 = svcGetSystemTick();
|
||||||
|
|
||||||
/* Setup/create the logging directory. */
|
/* Setup/create the logging directory. */
|
||||||
std::snprintf(this->base_path, sizeof(this->base_path), "uart_logs/%011lu_%011lu_%016lx", timestamp0, timestamp1, static_cast<u64>(this->client_info.program_id));
|
std::snprintf(this->m_base_path, sizeof(this->m_base_path), "uart_logs/%011lu_%011lu_%016lx", timestamp0, timestamp1, static_cast<u64>(this->m_client_info.program_id));
|
||||||
ams::mitm::fs::CreateAtmosphereSdDirectory("uart_logs");
|
ams::mitm::fs::CreateAtmosphereSdDirectory("uart_logs");
|
||||||
ams::mitm::fs::CreateAtmosphereSdDirectory(this->base_path);
|
ams::mitm::fs::CreateAtmosphereSdDirectory(this->m_base_path);
|
||||||
|
|
||||||
/* Create/initialize the text cmd_log. */
|
/* Create/initialize the text cmd_log. */
|
||||||
char tmp_path[256];
|
char tmp_path[256];
|
||||||
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "cmd_log");
|
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->m_base_path, "cmd_log");
|
||||||
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
|
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
|
||||||
this->cmdlog_pos = 0;
|
this->m_cmdlog_pos = 0;
|
||||||
|
|
||||||
/* Initialize the Send cache-buffer. */
|
/* Initialize the Send cache-buffer. */
|
||||||
this->send_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
|
this->m_send_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
|
||||||
if (this->send_cache_buffer != nullptr) {
|
if (this->m_send_cache_buffer != nullptr) {
|
||||||
std::memset(this->send_cache_buffer, 0, this->CacheBufferSize);
|
std::memset(this->m_send_cache_buffer, 0, this->CacheBufferSize);
|
||||||
}
|
}
|
||||||
this->send_cache_pos = 0;
|
this->m_send_cache_pos = 0;
|
||||||
|
|
||||||
/* Initialize the Receive cache-buffer. */
|
/* Initialize the Receive cache-buffer. */
|
||||||
this->receive_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
|
this->m_receive_cache_buffer = static_cast<u8 *>(std::malloc(this->CacheBufferSize));
|
||||||
if (this->receive_cache_buffer != nullptr) {
|
if (this->m_receive_cache_buffer != nullptr) {
|
||||||
std::memset(this->receive_cache_buffer, 0, this->CacheBufferSize);
|
std::memset(this->m_receive_cache_buffer, 0, this->CacheBufferSize);
|
||||||
}
|
}
|
||||||
this->receive_cache_pos = 0;
|
this->m_receive_cache_pos = 0;
|
||||||
|
|
||||||
|
this->m_datalog_ready = false;
|
||||||
|
|
||||||
/* When the above is successful, initialize the datalog. */
|
/* When the above is successful, initialize the datalog. */
|
||||||
if (this->send_cache_buffer != nullptr && this->receive_cache_buffer != nullptr) {
|
if (this->m_send_cache_buffer != nullptr && this->m_receive_cache_buffer != nullptr) {
|
||||||
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "btsnoop_hci.log");
|
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->m_base_path, "btsnoop_hci.log");
|
||||||
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
|
ams::mitm::fs::CreateAtmosphereSdFile(tmp_path, 0, 0);
|
||||||
rc = ams::mitm::fs::OpenAtmosphereSdFile(&this->datalog_file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append);
|
rc = ams::mitm::fs::OpenAtmosphereSdFile(&this->m_datalog_file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append);
|
||||||
/* Set datalog_ready to whether initialization was successful. */
|
/* Set datalog_ready to whether initialization was successful. */
|
||||||
this->datalog_ready = R_SUCCEEDED(rc);
|
this->m_datalog_ready = R_SUCCEEDED(rc);
|
||||||
}
|
}
|
||||||
this->datalog_pos = 0;
|
|
||||||
|
|
||||||
/* Setup the btsnoop header. */
|
if (this->m_datalog_ready) {
|
||||||
|
std::shared_ptr<UartLogger> logger = mitm::uart::g_logger;
|
||||||
|
logger->InitializeDataLog(&this->m_datalog_file, &this->m_datalog_pos);
|
||||||
|
}
|
||||||
|
|
||||||
struct {
|
/* This will be enabled by WriteUartData once a certain command is detected. */
|
||||||
char id[8];
|
/* If you want to log all HCI traffic during system-boot initialization, you can change this field to true. */
|
||||||
u32 version;
|
/* When changed to true, qlaunch will hang at a black-screen during system-boot, due to the bluetooth slowdown. */
|
||||||
u32 datalink_type;
|
this->m_data_logging_enabled = false;
|
||||||
} btsnoop_header = { .id = "btsnoop" };
|
|
||||||
|
|
||||||
u32 version = 1;
|
|
||||||
u32 datalink_type = 1002; /* HCI UART (H4) */
|
|
||||||
ams::util::StoreBigEndian(&btsnoop_header.version, version);
|
|
||||||
ams::util::StoreBigEndian(&btsnoop_header.datalink_type, datalink_type);
|
|
||||||
|
|
||||||
/* Enable data-logging, required for WriteLog() to write anything. */
|
|
||||||
this->data_logging_enabled = true;
|
|
||||||
|
|
||||||
/* Write the btsnoop header to the datalog. */
|
|
||||||
this->WriteLog(&btsnoop_header, sizeof(btsnoop_header));
|
|
||||||
|
|
||||||
/* This will be re-enabled by WriteUartData once a certain command is detected. */
|
|
||||||
/* If you want to log all HCI traffic during system-boot initialization, you can comment out the below line, however there will be a slowdown. */
|
|
||||||
this->data_logging_enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append the specified string to the text cmd_log file. */
|
/* Append the specified string to the text cmd_log file. */
|
||||||
void UartPortService::WriteCmdLog(const char *str) {
|
void UartPortService::WriteCmdLog(const char *str) {
|
||||||
Result rc=0;
|
|
||||||
FsFile file={};
|
|
||||||
char tmp_path[256];
|
char tmp_path[256];
|
||||||
size_t len = strlen(str);
|
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->m_base_path, "cmd_log");
|
||||||
std::snprintf(tmp_path, sizeof(tmp_path), "%s/%s", this->base_path, "cmd_log");
|
std::shared_ptr<UartLogger> logger = mitm::uart::g_logger;
|
||||||
rc = ams::mitm::fs::OpenAtmosphereSdFile(&file, tmp_path, FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append);
|
logger->SendTextLogData(tmp_path, &this->m_cmdlog_pos, str);
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
rc = fsFileWrite(&file, this->cmdlog_pos, str, len, FsWriteOption_None);
|
|
||||||
}
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
|
||||||
this->cmdlog_pos += len;
|
|
||||||
}
|
|
||||||
fsFileClose(&file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append the specified data to the datalog file. */
|
|
||||||
void UartPortService::WriteLog(const void* buffer, size_t size) {
|
|
||||||
/* Only write to the file if data-logging is enabled and initialized. */
|
|
||||||
if (this->data_logging_enabled && this->datalog_ready) {
|
|
||||||
if (R_SUCCEEDED(fsFileWrite(&this->datalog_file, this->datalog_pos, buffer, size, FsWriteOption_None))) {
|
|
||||||
this->datalog_pos += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Append the specified packet to the datalog via WriteLog. */
|
|
||||||
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
|
||||||
void UartPortService::WriteLogPacket(bool dir, const void* buffer, size_t size) {
|
|
||||||
struct {
|
|
||||||
u32 original_length;
|
|
||||||
u32 included_length;
|
|
||||||
u32 packet_flags;
|
|
||||||
u32 cumulative_drops;
|
|
||||||
s64 timestamp_microseconds;
|
|
||||||
} pkt_hdr = {};
|
|
||||||
|
|
||||||
u32 flags = 0;
|
|
||||||
if (dir) {
|
|
||||||
flags |= BIT(0);
|
|
||||||
}
|
|
||||||
ams::util::StoreBigEndian(&pkt_hdr.original_length, static_cast<u32>(size));
|
|
||||||
ams::util::StoreBigEndian(&pkt_hdr.included_length, static_cast<u32>(size));
|
|
||||||
ams::util::StoreBigEndian(&pkt_hdr.packet_flags, flags);
|
|
||||||
|
|
||||||
/* Currently we leave the timestamp at value 0. */
|
|
||||||
|
|
||||||
this->WriteLog(&pkt_hdr, sizeof(pkt_hdr));
|
|
||||||
this->WriteLog(buffer, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log data from Send/Receive. */
|
/* Log data from Send/Receive. */
|
||||||
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
/* dir: false = Send (host->controller), true = Receive (controller->host). */
|
||||||
void UartPortService::WriteUartData(bool dir, const void* buffer, size_t size) {
|
void UartPortService::WriteUartData(bool dir, const void* buffer, size_t size) {
|
||||||
/* Select which cache buffer/pos to use via dir. */
|
/* Select which cache buffer/pos to use via dir. */
|
||||||
u8 *cache_buffer = !dir ? this->send_cache_buffer : this->receive_cache_buffer;
|
u8 *cache_buffer = !dir ? this->m_send_cache_buffer : this->m_receive_cache_buffer;
|
||||||
size_t *cache_pos = !dir ? &this->send_cache_pos : &this->receive_cache_pos;
|
size_t *cache_pos = !dir ? &this->m_send_cache_pos : &this->m_receive_cache_pos;
|
||||||
|
|
||||||
/* Verify that the input size is non-zero, and within cache buffer bounds. */
|
/* Verify that the input size is non-zero, and within cache buffer bounds. */
|
||||||
if (size && *cache_pos + size <= this->CacheBufferSize) {
|
if (size && *cache_pos + size <= this->CacheBufferSize) {
|
||||||
|
@ -217,8 +160,8 @@ namespace ams::mitm::uart {
|
||||||
/* Check for the first command used in the port which is opened last by bluetooth-sysmodule. */
|
/* Check for the first command used in the port which is opened last by bluetooth-sysmodule. */
|
||||||
/* This is a vendor command. */
|
/* This is a vendor command. */
|
||||||
/* Once detected, data-logging will be enabled. */
|
/* Once detected, data-logging will be enabled. */
|
||||||
if (!this->data_logging_enabled && hci_cmd->opcode[1] == 0xFC && hci_cmd->opcode[0] == 0x16) {
|
if (!this->m_data_logging_enabled && hci_cmd->opcode[1] == 0xFC && hci_cmd->opcode[0] == 0x16) {
|
||||||
this->data_logging_enabled = true;
|
this->m_data_logging_enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,7 +201,11 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* If a packet is available, log it and update the cache. */
|
/* If a packet is available, log it and update the cache. */
|
||||||
if (pkt_len>0x1) {
|
if (pkt_len>0x1) {
|
||||||
this->WriteLogPacket(dir, cache_buffer, pkt_len);
|
/* Only write to the file if data-logging is enabled and initialized. */
|
||||||
|
if (this->m_data_logging_enabled && this->m_datalog_ready) {
|
||||||
|
std::shared_ptr<UartLogger> logger = mitm::uart::g_logger;
|
||||||
|
logger->SendLogData(&this->m_datalog_file, &this->m_datalog_pos, dir, cache_buffer, pkt_len);
|
||||||
|
}
|
||||||
(*cache_pos)-= pkt_len;
|
(*cache_pos)-= pkt_len;
|
||||||
if (*cache_pos) {
|
if (*cache_pos) {
|
||||||
std::memmove(cache_buffer, &cache_buffer[pkt_len], *cache_pos);
|
std::memmove(cache_buffer, &cache_buffer[pkt_len], *cache_pos);
|
||||||
|
@ -272,7 +219,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward OpenPort and write to the cmd_log. */
|
/* Forward OpenPort and write to the cmd_log. */
|
||||||
Result UartPortService::OpenPort(sf::Out<bool> out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) {
|
Result UartPortService::OpenPort(sf::Out<bool> out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) {
|
||||||
Result rc = uartPortSessionOpenPortFwd(this->srv.get(), reinterpret_cast<bool *>(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length);
|
Result rc = uartPortSessionOpenPortFwd(this->m_srv.get(), reinterpret_cast<bool *>(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length);
|
||||||
svcCloseHandle(send_handle.GetValue());
|
svcCloseHandle(send_handle.GetValue());
|
||||||
svcCloseHandle(receive_handle.GetValue());
|
svcCloseHandle(receive_handle.GetValue());
|
||||||
|
|
||||||
|
@ -284,7 +231,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward OpenPortForDev and write to the cmd_log. */
|
/* Forward OpenPortForDev and write to the cmd_log. */
|
||||||
Result UartPortService::OpenPortForDev(sf::Out<bool> out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) {
|
Result UartPortService::OpenPortForDev(sf::Out<bool> out, u32 port, u32 baud_rate, UartFlowControlMode flow_control_mode, u32 device_variation, bool is_invert_tx, bool is_invert_rx, bool is_invert_rts, bool is_invert_cts, sf::CopyHandle send_handle, sf::CopyHandle receive_handle, u64 send_buffer_length, u64 receive_buffer_length) {
|
||||||
Result rc = uartPortSessionOpenPortForDevFwd(this->srv.get(), reinterpret_cast<bool *>(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length);
|
Result rc = uartPortSessionOpenPortForDevFwd(this->m_srv.get(), reinterpret_cast<bool *>(out.GetPointer()), port, baud_rate, flow_control_mode, device_variation, is_invert_tx, is_invert_rx, is_invert_rts, is_invert_cts, send_handle.GetValue(), receive_handle.GetValue(), send_buffer_length, receive_buffer_length);
|
||||||
svcCloseHandle(send_handle.GetValue());
|
svcCloseHandle(send_handle.GetValue());
|
||||||
svcCloseHandle(receive_handle.GetValue());
|
svcCloseHandle(receive_handle.GetValue());
|
||||||
|
|
||||||
|
@ -296,7 +243,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward GetWritableLength and write to the cmd_log. */
|
/* Forward GetWritableLength and write to the cmd_log. */
|
||||||
Result UartPortService::GetWritableLength(sf::Out<u64> out) {
|
Result UartPortService::GetWritableLength(sf::Out<u64> out) {
|
||||||
Result rc = uartPortSessionGetWritableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
|
Result rc = uartPortSessionGetWritableLength(this->m_srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
|
||||||
|
|
||||||
char str[256];
|
char str[256];
|
||||||
std::snprintf(str, sizeof(str), "GetWritableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue());
|
std::snprintf(str, sizeof(str), "GetWritableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue());
|
||||||
|
@ -307,7 +254,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward Send and log the data if the out_size is non-zero. */
|
/* Forward Send and log the data if the out_size is non-zero. */
|
||||||
Result UartPortService::Send(sf::Out<u64> out_size, const sf::InAutoSelectBuffer &data) {
|
Result UartPortService::Send(sf::Out<u64> out_size, const sf::InAutoSelectBuffer &data) {
|
||||||
Result rc = uartPortSessionSend(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
|
Result rc = uartPortSessionSend(this->m_srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && out_size.GetValue()) {
|
if (R_SUCCEEDED(rc) && out_size.GetValue()) {
|
||||||
this->WriteUartData(false, data.GetPointer(), out_size.GetValue());
|
this->WriteUartData(false, data.GetPointer(), out_size.GetValue());
|
||||||
|
@ -317,7 +264,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward GetReadableLength and write to the cmd_log. */
|
/* Forward GetReadableLength and write to the cmd_log. */
|
||||||
Result UartPortService::GetReadableLength(sf::Out<u64> out) {
|
Result UartPortService::GetReadableLength(sf::Out<u64> out) {
|
||||||
Result rc = uartPortSessionGetReadableLength(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
|
Result rc = uartPortSessionGetReadableLength(this->m_srv.get(), reinterpret_cast<u64 *>(out.GetPointer()));
|
||||||
|
|
||||||
char str[256];
|
char str[256];
|
||||||
std::snprintf(str, sizeof(str), "GetReadableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue());
|
std::snprintf(str, sizeof(str), "GetReadableLength(): rc = 0x%x, out = 0x%lx\n", rc.GetValue(), out.GetValue());
|
||||||
|
@ -328,7 +275,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward Receive and log the data if the out_size is non-zero. */
|
/* Forward Receive and log the data if the out_size is non-zero. */
|
||||||
Result UartPortService::Receive(sf::Out<u64> out_size, const sf::OutAutoSelectBuffer &data) {
|
Result UartPortService::Receive(sf::Out<u64> out_size, const sf::OutAutoSelectBuffer &data) {
|
||||||
Result rc = uartPortSessionReceive(this->srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
|
Result rc = uartPortSessionReceive(this->m_srv.get(), data.GetPointer(), data.GetSize(), reinterpret_cast<u64 *>(out_size.GetPointer()));
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc) && out_size.GetValue()) {
|
if (R_SUCCEEDED(rc) && out_size.GetValue()) {
|
||||||
this->WriteUartData(true, data.GetPointer(), out_size.GetValue());
|
this->WriteUartData(true, data.GetPointer(), out_size.GetValue());
|
||||||
|
@ -338,7 +285,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward BindPortEvent and write to the cmd_log. */
|
/* Forward BindPortEvent and write to the cmd_log. */
|
||||||
Result UartPortService::BindPortEvent(sf::Out<bool> out, sf::OutCopyHandle out_event_handle, UartPortEventType port_event_type, s64 threshold) {
|
Result UartPortService::BindPortEvent(sf::Out<bool> out, sf::OutCopyHandle out_event_handle, UartPortEventType port_event_type, s64 threshold) {
|
||||||
Result rc = uartPortSessionBindPortEventFwd(this->srv.get(), port_event_type, threshold, reinterpret_cast<bool *>(out.GetPointer()), out_event_handle.GetHandlePointer());
|
Result rc = uartPortSessionBindPortEventFwd(this->m_srv.get(), port_event_type, threshold, reinterpret_cast<bool *>(out.GetPointer()), out_event_handle.GetHandlePointer());
|
||||||
|
|
||||||
char str[256];
|
char str[256];
|
||||||
std::snprintf(str, sizeof(str), "BindPortEvent(port_event_type = 0x%x, threshold = 0x%lx): rc = 0x%x, out = %d\n", port_event_type, threshold, rc.GetValue(), out.GetValue());
|
std::snprintf(str, sizeof(str), "BindPortEvent(port_event_type = 0x%x, threshold = 0x%lx): rc = 0x%x, out = %d\n", port_event_type, threshold, rc.GetValue(), out.GetValue());
|
||||||
|
@ -348,7 +295,7 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
/* Forward UnbindPortEvent and write to the cmd_log. */
|
/* Forward UnbindPortEvent and write to the cmd_log. */
|
||||||
Result UartPortService::UnbindPortEvent(sf::Out<bool> out, UartPortEventType port_event_type) {
|
Result UartPortService::UnbindPortEvent(sf::Out<bool> out, UartPortEventType port_event_type) {
|
||||||
Result rc = uartPortSessionUnbindPortEvent(this->srv.get(), port_event_type, reinterpret_cast<bool *>(out.GetPointer()));
|
Result rc = uartPortSessionUnbindPortEvent(this->m_srv.get(), port_event_type, reinterpret_cast<bool *>(out.GetPointer()));
|
||||||
|
|
||||||
char str[256];
|
char str[256];
|
||||||
std::snprintf(str, sizeof(str), "UnbindPortEvent(port_event_type = 0x%x): rc = 0x%x, out = %d\n", port_event_type, rc.GetValue(), out.GetValue());
|
std::snprintf(str, sizeof(str), "UnbindPortEvent(port_event_type = 0x%x): rc = 0x%x, out = %d\n", port_event_type, rc.GetValue(), out.GetValue());
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
#include "uart_mitm_logger.hpp"
|
||||||
#include "uart_shim.h"
|
#include "uart_shim.h"
|
||||||
|
|
||||||
#define AMS_UART_IPORTSESSION_MITM_INTERFACE_INFO(C, H) \
|
#define AMS_UART_IPORTSESSION_MITM_INTERFACE_INFO(C, H) \
|
||||||
|
@ -39,39 +40,39 @@ namespace ams::mitm::uart {
|
||||||
|
|
||||||
class UartPortService {
|
class UartPortService {
|
||||||
private:
|
private:
|
||||||
sm::MitmProcessInfo client_info;
|
sm::MitmProcessInfo m_client_info;
|
||||||
std::unique_ptr<::UartPortSession> srv;
|
std::unique_ptr<::UartPortSession> m_srv;
|
||||||
|
|
||||||
static constexpr inline size_t CacheBufferSize = 0x1000;
|
static constexpr inline size_t CacheBufferSize = 0x1000;
|
||||||
|
|
||||||
char base_path[256];
|
char m_base_path[256];
|
||||||
|
|
||||||
size_t cmdlog_pos;
|
size_t m_cmdlog_pos;
|
||||||
size_t datalog_pos;
|
size_t m_datalog_pos;
|
||||||
|
|
||||||
bool datalog_ready;
|
bool m_datalog_ready;
|
||||||
bool data_logging_enabled;
|
bool m_data_logging_enabled;
|
||||||
|
|
||||||
FsFile datalog_file;
|
FsFile m_datalog_file;
|
||||||
|
|
||||||
u8 *send_cache_buffer;
|
u8 *m_send_cache_buffer;
|
||||||
u8 *receive_cache_buffer;
|
u8 *m_receive_cache_buffer;
|
||||||
size_t send_cache_pos;
|
size_t m_send_cache_pos;
|
||||||
size_t receive_cache_pos;
|
size_t m_receive_cache_pos;
|
||||||
|
|
||||||
bool TryGetCurrentTimestamp(u64 *out);
|
bool TryGetCurrentTimestamp(u64 *out);
|
||||||
void WriteCmdLog(const char *str);
|
void WriteCmdLog(const char *str);
|
||||||
void WriteLog(const void* buffer, size_t size);
|
|
||||||
void WriteLogPacket(bool dir, const void* buffer, size_t size);
|
|
||||||
void WriteUartData(bool dir, const void* buffer, size_t size);
|
void WriteUartData(bool dir, const void* buffer, size_t size);
|
||||||
public:
|
public:
|
||||||
UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s);
|
UartPortService(const sm::MitmProcessInfo &cl, std::unique_ptr<::UartPortSession> s);
|
||||||
|
|
||||||
virtual ~UartPortService() {
|
virtual ~UartPortService() {
|
||||||
uartPortSessionClose(this->srv.get());
|
std::shared_ptr<UartLogger> logger = mitm::uart::g_logger;
|
||||||
fsFileClose(&this->datalog_file);
|
logger->WaitFinished();
|
||||||
std::free(this->send_cache_buffer);
|
uartPortSessionClose(this->m_srv.get());
|
||||||
std::free(this->receive_cache_buffer);
|
fsFileClose(&this->m_datalog_file);
|
||||||
|
std::free(this->m_send_cache_buffer);
|
||||||
|
std::free(this->m_receive_cache_buffer);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
/* Actual command API. */
|
/* Actual command API. */
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "../amsmitm_initialization.hpp"
|
#include "../amsmitm_initialization.hpp"
|
||||||
#include "uartmitm_module.hpp"
|
#include "uartmitm_module.hpp"
|
||||||
#include "uart_mitm_service.hpp"
|
#include "uart_mitm_service.hpp"
|
||||||
|
#include "uart_mitm_logger.hpp"
|
||||||
|
|
||||||
namespace ams::mitm::uart {
|
namespace ams::mitm::uart {
|
||||||
|
|
||||||
|
@ -84,8 +85,12 @@ namespace ams::mitm::uart {
|
||||||
/* Create mitm servers. */
|
/* Create mitm servers. */
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<UartMitmService>(PortIndex_Mitm, UartMitmServiceName)));
|
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<UartMitmService>(PortIndex_Mitm, UartMitmServiceName)));
|
||||||
|
|
||||||
|
mitm::uart::g_logger = std::make_shared<UartLogger>();
|
||||||
|
|
||||||
/* Loop forever, servicing our services. */
|
/* Loop forever, servicing our services. */
|
||||||
g_server_manager.LoopProcess();
|
g_server_manager.LoopProcess();
|
||||||
|
|
||||||
|
mitm::uart::g_logger.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue