btdrv-mitm: refactor event handling code to make use of namespaces

This commit is contained in:
ndeadly 2020-06-13 19:15:59 +02:00
parent 417a7a6f85
commit aedca57a3e
16 changed files with 594 additions and 348 deletions

View file

@ -3,49 +3,73 @@
#include "../btdrv_mitm_logging.hpp" #include "../btdrv_mitm_logging.hpp"
ams::os::ThreadType g_bt_ble_event_task_thread; namespace ams::bluetooth::ble {
alignas(ams::os::ThreadStackAlignment) u8 g_bt_ble_event_task_stack[0x2000];
//u8 g_bt_ble_event_data_buffer[0x400];
//BluetoothEventType g_current_bt_ble_event_type;
ams::os::SystemEventType g_btBleSystemEvent; namespace {
ams::os::SystemEventType g_btBleSystemEventFwd;
ams::os::SystemEventType g_btBleSystemEventUser;
os::ThreadType g_eventHandlerThread;
alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
//u8 g_bt_ble_event_data_buffer[0x400];
//BluetoothEventType g_current_bt_ble_event_type;
void BluetoothBleEventThreadFunc(void *arg) { os::SystemEventType g_btBleSystemEvent;
while (true) { os::SystemEventType g_btBleSystemEventFwd;
// Wait for real bluetooth event os::SystemEventType g_btBleSystemEventUser;
ams::os::WaitSystemEvent(&g_btBleSystemEvent);
}
os::SystemEventType *GetSystemEvent(void) {
return &g_btBleSystemEvent;
}
os::SystemEventType *GetForwardEvent(void) {
return &g_btBleSystemEventFwd;
}
os::SystemEventType *GetUserForwardEvent(void) {
return &g_btBleSystemEventUser;
}
void HandleEvent(void) {
BTDRV_LOG_FMT("ble event fired"); BTDRV_LOG_FMT("ble event fired");
// Signal our forwarder events // Signal our forwarder events
if (!g_redirectEvents || g_preparingForSleep) if (!g_redirectEvents || g_preparingForSleep)
ams::os::SignalSystemEvent(&g_btBleSystemEventFwd); os::SignalSystemEvent(&g_btBleSystemEventFwd);
else else
ams::os::SignalSystemEvent(&g_btBleSystemEventUser); os::SignalSystemEvent(&g_btBleSystemEventUser);
} }
}
ams::Result InitializeBluetoothBleEvents(void) { void BluetoothBleEventThreadFunc(void *arg) {
R_TRY(ams::os::CreateSystemEvent(&g_btBleSystemEventFwd, ams::os::EventClearMode_AutoClear, true)); while (true) {
R_TRY(ams::os::CreateSystemEvent(&g_btBleSystemEventUser, ams::os::EventClearMode_AutoClear, true)); // Wait for real bluetooth event
os::WaitSystemEvent(&g_btBleSystemEvent);
return ams::ResultSuccess();
} HandleEvent();
}
ams::Result StartBluetoothBleEventThread(void) { }
R_TRY(ams::os::CreateThread(&g_bt_ble_event_task_thread,
BluetoothBleEventThreadFunc, Result InitializeEvents(void) {
nullptr, R_TRY(os::CreateSystemEvent(&g_btBleSystemEventFwd, os::EventClearMode_AutoClear, true));
g_bt_ble_event_task_stack, R_TRY(os::CreateSystemEvent(&g_btBleSystemEventUser, os::EventClearMode_AutoClear, true));
sizeof(g_bt_ble_event_task_stack),
9 return ams::ResultSuccess();
//38 // priority of btm sysmodule + 1 }
));
Result StartEventHandlerThread(void) {
ams::os::StartThread(&g_bt_ble_event_task_thread); R_TRY(os::CreateThread(&g_eventHandlerThread,
BluetoothBleEventThreadFunc,
return ams::ResultSuccess(); nullptr,
g_eventHandlerThreadStack,
sizeof(g_eventHandlerThreadStack),
9
//38 // priority of btm sysmodule + 1
));
os::StartThread(&g_eventHandlerThread);
return ams::ResultSuccess();
}
} }

View file

@ -2,10 +2,15 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
extern ams::os::SystemEventType g_btBleSystemEvent; namespace ams::bluetooth::ble {
extern ams::os::SystemEventType g_btBleSystemEventFwd;
extern ams::os::SystemEventType g_btBleSystemEventUser;
ams::Result InitializeBluetoothBleEvents(void); void HandleEvent(void);
ams::Result StartBluetoothBleEventThread(void);
os::SystemEventType *GetSystemEvent(void);
os::SystemEventType *GetForwardEvent(void);
os::SystemEventType *GetUserForwardEvent(void);
Result InitializeEvents(void);
Result StartEventHandlerThread(void);
}

View file

@ -3,49 +3,72 @@
#include "../btdrv_mitm_logging.hpp" #include "../btdrv_mitm_logging.hpp"
ams::os::ThreadType g_bt_event_task_thread; namespace ams::bluetooth::core {
alignas(ams::os::ThreadStackAlignment) u8 g_bt_event_task_stack[0x2000];
//u8 g_bt_event_data_buffer[0x400];
//BluetoothEventType g_current_bt_event_type;
ams::os::SystemEventType g_btSystemEvent; namespace {
ams::os::SystemEventType g_btSystemEventFwd;
ams::os::SystemEventType g_btSystemEventUser;
os::ThreadType g_eventHandlerThread;
alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
//u8 g_eventDataBuffer[0x400];
//BluetoothEventType g_currentEventType;
void BluetoothEventThreadFunc(void *arg) { os::SystemEventType g_btSystemEvent;
while (true) { os::SystemEventType g_btSystemEventFwd;
// Wait for real bluetooth event os::SystemEventType g_btSystemEventUser;
ams::os::WaitSystemEvent(&g_btSystemEvent);
}
os::SystemEventType *GetSystemEvent(void) {
return &g_btSystemEvent;
}
os::SystemEventType *GetForwardEvent(void) {
return &g_btSystemEventFwd;
}
os::SystemEventType *GetUserForwardEvent(void) {
return &g_btSystemEventUser;
}
void HandleEvent(void) {
BTDRV_LOG_FMT("bluetooth event fired"); BTDRV_LOG_FMT("bluetooth event fired");
// Signal our forwarder events // Signal our forwarder events
if (!g_redirectEvents || g_preparingForSleep) if (!g_redirectEvents || g_preparingForSleep)
ams::os::SignalSystemEvent(&g_btSystemEventFwd); os::SignalSystemEvent(&g_btSystemEventFwd);
else else
ams::os::SignalSystemEvent(&g_btSystemEventUser); os::SignalSystemEvent(&g_btSystemEventUser);
} }
}
void BluetoothEventThreadFunc(void *arg) {
ams::Result InitializeBluetoothCoreEvents(void) { while (true) {
R_TRY(ams::os::CreateSystemEvent(&g_btSystemEventFwd, ams::os::EventClearMode_AutoClear, true)); // Wait for real bluetooth event
R_TRY(ams::os::CreateSystemEvent(&g_btSystemEventUser, ams::os::EventClearMode_AutoClear, true)); os::WaitSystemEvent(&g_btSystemEvent);
return ams::ResultSuccess(); HandleEvent();
} }
}
ams::Result StartBluetoothCoreEventThread(void) {
R_TRY(ams::os::CreateThread(&g_bt_event_task_thread, Result InitializeEvents(void) {
BluetoothEventThreadFunc, R_TRY(os::CreateSystemEvent(&g_btSystemEventFwd, os::EventClearMode_AutoClear, true));
nullptr, R_TRY(os::CreateSystemEvent(&g_btSystemEventUser, os::EventClearMode_AutoClear, true));
g_bt_event_task_stack,
sizeof(g_bt_event_task_stack), return ams::ResultSuccess();
9 }
//37 // priority of btm sysmodule
)); Result StartEventHandlerThread(void) {
R_TRY(os::CreateThread(&g_eventHandlerThread,
ams::os::StartThread(&g_bt_event_task_thread); BluetoothEventThreadFunc,
nullptr,
return ams::ResultSuccess(); g_eventHandlerThreadStack,
sizeof(g_eventHandlerThreadStack),
9
//37 // priority of btm sysmodule
));
os::StartThread(&g_eventHandlerThread);
return ams::ResultSuccess();
}
} }

View file

@ -2,9 +2,15 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
extern ams::os::SystemEventType g_btSystemEvent; namespace ams::bluetooth::core {
extern ams::os::SystemEventType g_btSystemEventFwd;
extern ams::os::SystemEventType g_btSystemEventUser;
ams::Result InitializeBluetoothCoreEvents(void); void HandleEvent(void);
ams::Result StartBluetoothCoreEventThread(void);
os::SystemEventType *GetSystemEvent(void);
os::SystemEventType *GetForwardEvent(void);
os::SystemEventType *GetUserForwardEvent(void);
Result InitializeEvents(void);
Result StartEventHandlerThread(void);
}

View file

@ -0,0 +1,94 @@
#include <switch.h>
#include "bluetooth_events.hpp"
#include "../pscpm_module.hpp"
namespace ams::bluetooth::events {
namespace {
os::ThreadType g_eventHandlerThread;
alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
os::WaitableManagerType g_manager;
os::WaitableHolderType g_holderPscPm;
os::WaitableHolderType g_holderBtCore;
os::WaitableHolderType g_holderBtHid;
os::WaitableHolderType g_holderBtBle;
}
void EventHandlerThreadFunc(void *arg) {
while (true) {
auto signalled_holder = os::WaitAny(&g_manager);
switch (os::GetWaitableHolderUserData(signalled_holder)) {
case BtdrvEventType_PscPm:
mitm::btdrv::handlePscPmEvent();
break;
case BtdrvEventType_BluetoothCore:
core::HandleEvent();
break;
case BtdrvEventType_BluetoothHid:
hid::HandleEvent();
break;
case BtdrvEventType_BluetoothBle:
ble::HandleEvent();
break;
default:
break;
}
}
}
void AttachWaitHolder(BtdrvEventType type) {
switch(type) {
case BtdrvEventType_PscPm:
os::InitializeWaitableHolder(&g_holderPscPm, mitm::btdrv::GetPscPmModule()->GetEventPointer()->GetBase());
os::SetWaitableHolderUserData(&g_holderPscPm, BtdrvEventType_PscPm);
os::LinkWaitableHolder(&g_manager, &g_holderPscPm);
break;
case BtdrvEventType_BluetoothCore:
os::InitializeWaitableHolder(&g_holderBtCore, core::GetSystemEvent());
os::SetWaitableHolderUserData(&g_holderBtCore, BtdrvEventType_BluetoothCore);
os::LinkWaitableHolder(&g_manager, &g_holderBtCore);
break;
case BtdrvEventType_BluetoothHid:
os::InitializeWaitableHolder(&g_holderBtHid, hid::GetSystemEvent());
os::SetWaitableHolderUserData(&g_holderBtHid, BtdrvEventType_BluetoothHid);
os::LinkWaitableHolder(&g_manager, &g_holderBtHid);
break;
case BtdrvEventType_BluetoothBle:
os::InitializeWaitableHolder(&g_holderBtBle, ble::GetSystemEvent());
os::SetWaitableHolderUserData(&g_holderBtBle, BtdrvEventType_BluetoothBle);
os::LinkWaitableHolder(&g_manager, &g_holderBtBle);
break;
default:
return;
}
}
Result InitializeSystemEvents(void) {
//R_TRY(InitializePscPmModule());
R_TRY(core::InitializeEvents());
R_TRY(hid::InitializeEvents());
R_TRY(ble::InitializeEvents());
os::InitializeWaitableManager(&g_manager);
return ams::ResultSuccess();
}
Result StartEventHandlerThread(void) {
R_TRY(os::CreateThread(&g_eventHandlerThread,
EventHandlerThreadFunc,
nullptr,
g_eventHandlerThreadStack,
sizeof(g_eventHandlerThreadStack),
9
));
os::StartThread(&g_eventHandlerThread);
return ams::ResultSuccess();
}
}

View file

@ -1,6 +1,22 @@
#pragma once #pragma once
#include <stratosphere.hpp>
#include "bluetooth_core_events.hpp" #include "bluetooth_core_events.hpp"
#include "bluetooth_hid_events.hpp" #include "bluetooth_hid_events.hpp"
#include "bluetooth_hid_report_events.hpp" #include "bluetooth_hid_report_events.hpp"
#include "bluetooth_ble_events.hpp" #include "bluetooth_ble_events.hpp"
namespace ams::bluetooth::events {
enum BtdrvEventType {
BtdrvEventType_PscPm,
BtdrvEventType_BluetoothCore,
BtdrvEventType_BluetoothHid,
BtdrvEventType_BluetoothBle,
};
void AttachWaitHolder(BtdrvEventType type);
Result InitializeSystemEvents(void);
Result StartEventHandlerThread(void);
}

View file

@ -4,45 +4,57 @@
#include "../btdrv_mitm_logging.hpp" #include "../btdrv_mitm_logging.hpp"
ams::os::ThreadType g_bt_hid_event_task_thread; namespace ams::bluetooth::hid {
alignas(ams::os::ThreadStackAlignment) u8 g_bt_hid_event_task_stack[0x2000];
u8 g_bt_hid_event_data_buffer[0x480];
HidEventType g_current_bt_hid_event_type;
ams::os::SystemEventType g_btHidSystemEvent; namespace {
ams::os::SystemEventType g_btHidSystemEventFwd;
ams::os::SystemEventType g_btHidSystemEventUser;
os::ThreadType g_eventHandlerThread;
alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
u8 g_eventDataBuffer[0x480];
HidEventType g_currentEventType;
os::SystemEventType g_btHidSystemEvent;
os::SystemEventType g_btHidSystemEventFwd;
os::SystemEventType g_btHidSystemEventUser;
void handleConnectionStateEvent(HidEventData *eventData) {
switch (eventData->connectionState.state) {
case HidConnectionState_Connected:
ams::mitm::btdrv::attachDeviceHandler(&eventData->connectionState.address);
BTDRV_LOG_FMT("device connected");
break;
case HidConnectionState_Disconnected:
ams::mitm::btdrv::removeDeviceHandler(&eventData->connectionState.address);
BTDRV_LOG_FMT("device disconnected");
break;
default:
break;
} }
BTDRV_LOG_DATA(&eventData->connectionState.address, sizeof(BluetoothAddress));
}
os::SystemEventType *GetSystemEvent(void) {
return &g_btHidSystemEvent;
}
void BluetoothHidEventThreadFunc(void *arg) { os::SystemEventType *GetForwardEvent(void) {
HidEventData *eventData = reinterpret_cast<HidEventData *>(g_bt_hid_event_data_buffer); return &g_btHidSystemEventFwd;
}
while (true) { os::SystemEventType *GetUserForwardEvent(void) {
// Wait for real bluetooth event return &g_btHidSystemEventUser;
ams::os::WaitSystemEvent(&g_btHidSystemEvent); }
void handleConnectionStateEvent(HidEventData *eventData) {
switch (eventData->connectionState.state) {
case HidConnectionState_Connected:
ams::mitm::btdrv::attachDeviceHandler(&eventData->connectionState.address);
BTDRV_LOG_FMT("device connected");
break;
case HidConnectionState_Disconnected:
ams::mitm::btdrv::removeDeviceHandler(&eventData->connectionState.address);
BTDRV_LOG_FMT("device disconnected");
break;
default:
break;
}
BTDRV_LOG_DATA(&eventData->connectionState.address, sizeof(BluetoothAddress));
}
void HandleEvent(void) {
BTDRV_LOG_FMT("hid event fired"); BTDRV_LOG_FMT("hid event fired");
R_ABORT_UNLESS(btdrvGetHidEventInfo(&g_current_bt_hid_event_type, g_bt_hid_event_data_buffer, sizeof(g_bt_hid_event_data_buffer))); HidEventData *eventData = reinterpret_cast<HidEventData *>(g_eventDataBuffer);
switch (g_current_bt_hid_event_type) { R_ABORT_UNLESS(btdrvGetHidEventInfo(&g_currentEventType, g_eventDataBuffer, sizeof(g_eventDataBuffer)));
switch (g_currentEventType) {
case HidEvent_ConnectionState: case HidEvent_ConnectionState:
handleConnectionStateEvent(eventData); handleConnectionStateEvent(eventData);
break; break;
@ -54,32 +66,42 @@ void BluetoothHidEventThreadFunc(void *arg) {
//os::SignalSystemEvent(&g_btHidSystemEventFwd); //os::SignalSystemEvent(&g_btHidSystemEventFwd);
if (!g_redirectEvents || g_preparingForSleep) { if (!g_redirectEvents || g_preparingForSleep) {
ams::os::SignalSystemEvent(&g_btHidSystemEventFwd); os::SignalSystemEvent(&g_btHidSystemEventFwd);
} }
else { else {
ams::os::SignalSystemEvent(&g_btHidSystemEventUser); os::SignalSystemEvent(&g_btHidSystemEventUser);
} }
} }
}
void BluetoothHidEventThreadFunc(void *arg) {
ams::Result InitializeBluetoothHidEvents(void) { while (true) {
R_TRY(ams::os::CreateSystemEvent(&g_btHidSystemEventFwd, ams::os::EventClearMode_AutoClear, true)); // Wait for real bluetooth event
R_TRY(ams::os::CreateSystemEvent(&g_btHidSystemEventUser, ams::os::EventClearMode_AutoClear, true)); os::WaitSystemEvent(&g_btHidSystemEvent);
return ams::ResultSuccess(); HandleEvent();
} }
}
ams::Result StartBluetoothHidEventThread(void) {
R_TRY(ams::os::CreateThread(&g_bt_hid_event_task_thread, Result InitializeEvents(void) {
BluetoothHidEventThreadFunc, R_TRY(os::CreateSystemEvent(&g_btHidSystemEventFwd, os::EventClearMode_AutoClear, true));
nullptr, R_TRY(os::CreateSystemEvent(&g_btHidSystemEventUser, os::EventClearMode_AutoClear, true));
g_bt_hid_event_task_stack,
sizeof(g_bt_hid_event_task_stack), return ams::ResultSuccess();
9 }
//38 // priority of btm sysmodule + 1
)); Result StartEventHandlerThread(void) {
R_TRY(os::CreateThread(&g_eventHandlerThread,
ams::os::StartThread(&g_bt_hid_event_task_thread); BluetoothHidEventThreadFunc,
nullptr,
return ams::ResultSuccess(); g_eventHandlerThreadStack,
sizeof(g_eventHandlerThreadStack),
9
//38 // priority of btm sysmodule + 1
));
os::StartThread(&g_eventHandlerThread);
return ams::ResultSuccess();
}
} }

View file

@ -2,9 +2,15 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
extern ams::os::SystemEventType g_btHidSystemEvent; namespace ams::bluetooth::hid {
extern ams::os::SystemEventType g_btHidSystemEventFwd;
extern ams::os::SystemEventType g_btHidSystemEventUser;
ams::Result InitializeBluetoothHidEvents(void); void HandleEvent(void);
ams::Result StartBluetoothHidEventThread(void);
os::SystemEventType *GetSystemEvent(void);
os::SystemEventType *GetForwardEvent(void);
os::SystemEventType *GetUserForwardEvent(void);
Result InitializeEvents(void);
Result StartEventHandlerThread(void);
}

View file

@ -1,4 +1,5 @@
#include "bluetooth_hid_report_events.hpp" #include "bluetooth_hid_report_events.hpp"
#include "../circularbuffer.hpp"
#include "../btdrv_mitm_flags.hpp" #include "../btdrv_mitm_flags.hpp"
#include "../controllermanager.hpp" #include "../controllermanager.hpp"
#include "../controllers/bluetoothcontroller.hpp" #include "../controllers/bluetoothcontroller.hpp"
@ -6,191 +7,231 @@
#include "../btdrv_mitm_logging.hpp" #include "../btdrv_mitm_logging.hpp"
ams::os::ThreadType g_bt_hid_report_event_task_thread; namespace ams::bluetooth::hid::report {
alignas(ams::os::ThreadStackAlignment) u8 g_bt_hid_report_event_task_stack[0x2000];
SharedMemory g_realBtShmem; namespace {
SharedMemory g_fakeBtShmem;
ams::bluetooth::CircularBuffer *g_realCircBuff; os::ThreadType g_eventHandlerThread;
ams::bluetooth::CircularBuffer *g_fakeCircBuff; alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
ams::os::SystemEventType g_btHidReportSystemEvent; SharedMemory g_realBtShmem;
ams::os::SystemEventType g_btHidReportSystemEventFwd; SharedMemory g_fakeBtShmem;
ams::os::SystemEventType g_btHidReportSystemEventUser;
u8 g_fakeReportBuffer[0x42] = {}; bluetooth::CircularBuffer *g_realCircBuff;
HidReportData *g_fakeReportData = reinterpret_cast<HidReportData *>(g_fakeReportBuffer); bluetooth::CircularBuffer *g_fakeCircBuff;
ams::Result ProcessHidReportPackets(ams::bluetooth::CircularBuffer *realBuffer, ams::bluetooth::CircularBuffer *fakeBuffer) { os::SystemEventType g_btHidReportSystemEvent;
controller::BluetoothController *controller; os::SystemEventType g_btHidReportSystemEventFwd;
ams::bluetooth::CircularBufferPacket *realPacket; os::SystemEventType g_btHidReportSystemEventUser;
/* u8 g_fakeReportBuffer[0x42] = {};
BTDRV_LOG_FMT("realBuffer: name: %s, roffs: %d, woffs: %d, capacity: %d, _unk3: %d, id: %d", HidReportData *g_fakeReportData = reinterpret_cast<HidReportData *>(g_fakeReportBuffer);
realBuffer->name,
realBuffer->readOffset,
realBuffer->writeOffset,
realBuffer->size,
realBuffer->_unk3,
realBuffer->id);
BTDRV_LOG_FMT("fakeBuffer: name: %s, roffs: %d, woffs: %d, capacity: %d, _unk3: %d, id: %d",
fakeBuffer->name,
fakeBuffer->readOffset,
fakeBuffer->writeOffset,
fakeBuffer->size,
fakeBuffer->_unk3,
fakeBuffer->id);
*/
// Take snapshot of current write offset }
u32 writeOffset = realBuffer->writeOffset;
while (true) { SharedMemory *GetRealSharedMemory(void) {
if (realBuffer->readOffset == writeOffset) return &g_realBtShmem;
break; }
// Get packet from real buffer SharedMemory *GetFakeSharedMemory(void) {
//realPacket = reinterpret_cast<bluetooth::CircularBufferPacket *>(realBuffer->_read()); return &g_fakeBtShmem;
realPacket = reinterpret_cast<ams::bluetooth::CircularBufferPacket *>(&realBuffer->data[realBuffer->readOffset]); }
if (!realPacket)
break;
// Move read pointer past current packet (I think this is what Free does) os::SystemEventType *GetSystemEvent(void) {
if (realBuffer->readOffset != writeOffset) { return &g_btHidReportSystemEvent;
u32 newOffset = realBuffer->readOffset + realPacket->header.size + sizeof(ams::bluetooth::CircularBufferPacketHeader); }
if (newOffset >= BLUETOOTH_CIRCBUFFER_SIZE)
newOffset = 0;
realBuffer->_setReadOffset(newOffset); os::SystemEventType *GetForwardEvent(void) {
} return &g_btHidReportSystemEventFwd;
}
os::SystemEventType *GetUserForwardEvent(void) {
return &g_btHidReportSystemEventUser;
}
Result MapRemoteSharedMemory(Handle handle) {
shmemLoadRemote(&g_realBtShmem, handle, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw);
R_TRY(shmemMap(&g_realBtShmem));
g_realCircBuff = reinterpret_cast<bluetooth::CircularBuffer *>(shmemGetAddr(&g_realBtShmem));
BTDRV_LOG_FMT("Real shmem @ 0x%p", (void *)g_realCircBuff);
return ams::ResultSuccess();
}
Result InitializeFakeSharedMemory(void) {
R_TRY(shmemCreate(&g_fakeBtShmem, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw, Perm_Rw));
R_TRY(shmemMap(&g_fakeBtShmem));
g_fakeCircBuff = reinterpret_cast<CircularBuffer *>(shmemGetAddr(&g_fakeBtShmem));
BTDRV_LOG_FMT("Fake shmem @ 0x%p", (void *)g_fakeCircBuff);
// Initialise fake hid report buffer
g_fakeCircBuff->Initialize("HID Report");
g_fakeCircBuff->id = 1;
g_fakeCircBuff->_unk3 = 1;
return ams::ResultSuccess();
}
Result ProcessHidReportPackets(CircularBuffer *realBuffer, CircularBuffer *fakeBuffer) {
controller::BluetoothController *controller;
CircularBufferPacket *realPacket;
/*
BTDRV_LOG_FMT("realBuffer: name: %s, roffs: %d, woffs: %d, capacity: %d, _unk3: %d, id: %d",
realBuffer->name,
realBuffer->readOffset,
realBuffer->writeOffset,
realBuffer->size,
realBuffer->_unk3,
realBuffer->id);
BTDRV_LOG_FMT("fakeBuffer: name: %s, roffs: %d, woffs: %d, capacity: %d, _unk3: %d, id: %d",
fakeBuffer->name,
fakeBuffer->readOffset,
fakeBuffer->writeOffset,
fakeBuffer->size,
fakeBuffer->_unk3,
fakeBuffer->id);
*/
//BTDRV_LOG_DATA(&realPacket->data, realPacket->header.size);
//BTDRV_LOG_DATA(realPacket, realPacket->header.size + sizeof(bluetooth::CircularBufferPacketHeader));
//BTDRV_LOG_FMT("fakeBuffer: [%d] writing %d bytes to data[%d]", realPacket->header.type, realPacket->header.size + sizeof(bluetooth::CircularBufferPacketHeader), fakeBuffer->writeOffset);
switch (realPacket->header.type) { // Take snapshot of current write offset
case 0xff: u32 writeOffset = realBuffer->writeOffset;
// Skip over packet type 0xff. This packet indicates the buffer should wrap around on next read.
// Since our buffer read and write offsets can differ from the real buffer we want to write this ourselves while (true) {
// when appropriate via CircularBuffer::Write() if (realBuffer->readOffset == writeOffset)
continue; break;
case 4: // Get packet from real buffer
{ //realPacket = reinterpret_cast<bluetooth::CircularBufferPacket *>(realBuffer->_read());
// Locate the controller that sent the report realPacket = reinterpret_cast<CircularBufferPacket *>(&realBuffer->data[realBuffer->readOffset]);
controller = ams::mitm::btdrv::locateController(ams::hos::GetVersion() < ams::hos::Version_9_0_0 ? &realPacket->data.address : &realPacket->data.v2.address); if (!realPacket)
if (!controller) { break;
continue;
} // Move read pointer past current packet (I think this is what Free does)
if (realBuffer->readOffset != writeOffset) {
u32 newOffset = realBuffer->readOffset + realPacket->header.size + sizeof(CircularBufferPacketHeader);
if (newOffset >= BLUETOOTH_CIRCBUFFER_SIZE)
newOffset = 0;
realBuffer->_setReadOffset(newOffset);
}
//BTDRV_LOG_DATA(&realPacket->data, realPacket->header.size);
//BTDRV_LOG_DATA(realPacket, realPacket->header.size + sizeof(bluetooth::CircularBufferPacketHeader));
//BTDRV_LOG_FMT("fakeBuffer: [%d] writing %d bytes to data[%d]", realPacket->header.type, realPacket->header.size + sizeof(bluetooth::CircularBufferPacketHeader), fakeBuffer->writeOffset);
switch (realPacket->header.type) {
case 0xff:
// Skip over packet type 0xff. This packet indicates the buffer should wrap around on next read.
// Since our buffer read and write offsets can differ from the real buffer we want to write this ourselves
// when appropriate via CircularBuffer::Write()
continue;
if (controller->isSwitchController()) { case 4:
// Write unmodified packet directly to fake buffer (_write call will add new timestamp) {
fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size); // Locate the controller that sent the report
} controller = ams::mitm::btdrv::locateController(hos::GetVersion() < hos::Version_9_0_0 ? &realPacket->data.address : &realPacket->data.v2.address);
else { if (!controller) {
const HidReport *inReport; continue;
HidReport *outReport; }
// copy address and stuff over
if (ams::hos::GetVersion() < ams::hos::Version_10_0_0) { if (controller->isSwitchController()) {
g_fakeReportData->size = 0; // Todo: calculate size of report data // Write unmodified packet directly to fake buffer (_write call will add new timestamp)
std::memcpy(&g_fakeReportData->address, &realPacket->data.address, sizeof(BluetoothAddress)); fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size);
inReport = &realPacket->data.report;
outReport = &g_fakeReportData->report;
} }
else { else {
std::memcpy(&g_fakeReportData->v2.address, &realPacket->data.v2.address, sizeof(BluetoothAddress)); const HidReport *inReport;
inReport = &realPacket->data.v2.report; HidReport *outReport;
outReport = &g_fakeReportData->v2.report; // copy address and stuff over
if (hos::GetVersion() < hos::Version_10_0_0) {
g_fakeReportData->size = 0; // Todo: calculate size of report data
std::memcpy(&g_fakeReportData->address, &realPacket->data.address, sizeof(BluetoothAddress));
inReport = &realPacket->data.report;
outReport = &g_fakeReportData->report;
}
else {
std::memcpy(&g_fakeReportData->v2.address, &realPacket->data.v2.address, sizeof(BluetoothAddress));
inReport = &realPacket->data.v2.report;
outReport = &g_fakeReportData->v2.report;
}
auto switchData = reinterpret_cast<controller::SwitchReportData *>(&outReport->data);
switchData->report0x30.timer = os::ConvertToTimeSpan(realPacket->header.timestamp).GetMilliSeconds() & 0xff;
// Translate packet to switch pro format
controller->convertReportFormat(inReport, outReport);
//BTDRV_LOG_DATA(g_fakeReportData, sizeof(g_fakeReportBuffer));
// Write the converted report to our fake buffer
fakeBuffer->Write(4, g_fakeReportData, sizeof(g_fakeReportBuffer));
} }
auto switchData = reinterpret_cast<controller::SwitchReportData *>(&outReport->data);
switchData->report0x30.timer = ams::os::ConvertToTimeSpan(realPacket->header.timestamp).GetMilliSeconds() & 0xff;
// Translate packet to switch pro format
controller->convertReportFormat(inReport, outReport);
//BTDRV_LOG_DATA(g_fakeReportData, sizeof(g_fakeReportBuffer));
// Write the converted report to our fake buffer
fakeBuffer->Write(4, g_fakeReportData, sizeof(g_fakeReportBuffer));
} }
} break;
break;
default: default:
BTDRV_LOG_FMT("unknown packet received: %d", realPacket->header.type); BTDRV_LOG_FMT("unknown packet received: %d", realPacket->header.type);
fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size); fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size);
break; break;
} }
} }
return ams::ResultSuccess(); return ams::ResultSuccess();
} }
void BluetoothHidReportEventThreadFunc(void *arg) {
/*
R_ABORT_UNLESS(hiddbgInitialize());
// Todo: move these to some class constuctor or something?
if (hos::GetVersion() >= hos::Version_7_0_0)
R_ABORT_UNLESS(hiddbgAttachHdlsWorkBuffer());
*/
while (true) {
// Wait for real bluetooth event
ams::os::WaitSystemEvent(&g_btHidReportSystemEvent);
void HandleEvent(void) {
ProcessHidReportPackets(g_realCircBuff, g_fakeCircBuff); ProcessHidReportPackets(g_realCircBuff, g_fakeCircBuff);
// Signal our forwarder events // Signal our forwarder events
//os::SignalSystemEvent(&btHidReportSystemEventUser); //os::SignalSystemEvent(&btHidReportSystemEventUser);
ams::os::SignalSystemEvent(&g_btHidReportSystemEventFwd); os::SignalSystemEvent(&g_btHidReportSystemEventFwd);
}
//BTDRV_LOG_FMT("wrote hid report packets");
void BluetoothHidReportEventThreadFunc(void *arg) {
/*
R_ABORT_UNLESS(hiddbgInitialize());
// Todo: move these to some class constuctor or something?
if (hos::GetVersion() >= hos::Version_7_0_0)
R_ABORT_UNLESS(hiddbgAttachHdlsWorkBuffer());
*/
while (true) {
// Wait for real bluetooth event
os::WaitSystemEvent(&g_btHidReportSystemEvent);
HandleEvent();
}
/*
if (hos::GetVersion() >= hos::Version_7_0_0)
R_ABORT_UNLESS(hiddbgReleaseHdlsWorkBuffer());
hiddbgExit();
*/
}
ams::Result InitializeEvents(void) {
R_TRY(os::CreateSystemEvent(&g_btHidReportSystemEventFwd, os::EventClearMode_AutoClear, true));
R_TRY(os::CreateSystemEvent(&g_btHidReportSystemEventUser, os::EventClearMode_AutoClear, true));
return ams::ResultSuccess();
}
ams::Result StartEventHandlerThread(void) {
R_TRY(os::CreateThread(&g_eventHandlerThread,
BluetoothHidReportEventThreadFunc,
nullptr,
g_eventHandlerThreadStack,
sizeof(g_eventHandlerThreadStack),
-10
//18 // priority of hid sysmodule
));
os::StartThread(&g_eventHandlerThread);
return ams::ResultSuccess();
} }
/*
if (hos::GetVersion() >= hos::Version_7_0_0)
R_ABORT_UNLESS(hiddbgReleaseHdlsWorkBuffer());
hiddbgExit();
*/
}
ams::Result InitializeBluetoothHidReportEvents(void) {
R_TRY(ams::os::CreateSystemEvent(&g_btHidReportSystemEventFwd, ams::os::EventClearMode_AutoClear, true));
R_TRY(ams::os::CreateSystemEvent(&g_btHidReportSystemEventUser, ams::os::EventClearMode_AutoClear, true));
return ams::ResultSuccess();
}
ams::Result InitializeBluetoothHidReportFakeSharedMemory(void) {
R_TRY(shmemCreate(&g_fakeBtShmem, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw, Perm_Rw));
R_TRY(shmemMap(&g_fakeBtShmem));
g_fakeCircBuff = reinterpret_cast<ams::bluetooth::CircularBuffer *>(shmemGetAddr(&g_fakeBtShmem));
BTDRV_LOG_FMT("Fake shmem @ 0x%p", (void *)g_fakeCircBuff);
// Initialise fake hid report buffer
g_fakeCircBuff->Initialize("HID Report");
g_fakeCircBuff->id = 1;
g_fakeCircBuff->_unk3 = 1;
return ams::ResultSuccess();
}
ams::Result StartBluetoothHidReportEventThread(void) {
R_TRY(ams::os::CreateThread(&g_bt_hid_report_event_task_thread,
BluetoothHidReportEventThreadFunc,
nullptr,
g_bt_hid_report_event_task_stack,
sizeof(g_bt_hid_report_event_task_stack),
-10
//18 // priority of hid sysmodule
));
ams::os::StartThread(&g_bt_hid_report_event_task_thread);
return ams::ResultSuccess();
} }

View file

@ -2,18 +2,19 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "../circularbuffer.hpp" namespace ams::bluetooth::hid::report {
extern SharedMemory g_realBtShmem; SharedMemory *GetRealSharedMemory(void);
extern SharedMemory g_fakeBtShmem; SharedMemory *GetFakeSharedMemory(void);
extern ams::bluetooth::CircularBuffer *g_realCircBuff; os::SystemEventType *GetSystemEvent(void);
extern ams::bluetooth::CircularBuffer *g_fakeCircBuff; os::SystemEventType *GetForwardEvent(void);
os::SystemEventType *GetUserForwardEvent(void);
extern ams::os::SystemEventType g_btHidReportSystemEvent; Result MapRemoteSharedMemory(Handle handle);
extern ams::os::SystemEventType g_btHidReportSystemEventFwd; Result InitializeFakeSharedMemory(void);
extern ams::os::SystemEventType g_btHidReportSystemEventUser;
ams::Result InitializeBluetoothHidReportEvents(void); Result InitializeEvents(void);
ams::Result InitializeBluetoothHidReportFakeSharedMemory(void); Result StartEventHandlerThread(void);
ams::Result StartBluetoothHidReportEventThread(void);
}

View file

@ -1,7 +1,3 @@
#include <algorithm>
#include <atomic>
#include <memory>
#include <vector>
#include <cstring> #include <cstring>
#include <switch.h> #include <switch.h>
@ -12,7 +8,6 @@
#include "bluetooth/bluetooth_events.hpp" #include "bluetooth/bluetooth_events.hpp"
#include "controllermanager.hpp" #include "controllermanager.hpp"
namespace ams::mitm::btdrv { namespace ams::mitm::btdrv {
namespace { namespace {
@ -34,27 +29,35 @@ namespace ams::mitm::btdrv {
Handle handle = INVALID_HANDLE; Handle handle = INVALID_HANDLE;
// Forward to the real bluetooth module with our event handle instead // Forward to the real bluetooth module with our event handle instead
R_ABORT_UNLESS(btdrvInitializeBluetoothFwd(this->forward_service.get(), &handle)); R_TRY(btdrvInitializeBluetoothFwd(this->forward_service.get(), &handle));
// Attach the handle to our real system event // Attach the handle to our real system event
os::AttachReadableHandleToSystemEvent(&g_btSystemEvent, handle, false, os::EventClearMode_AutoClear); os::AttachReadableHandleToSystemEvent(bluetooth::core::GetSystemEvent(),
handle,
false,
os::EventClearMode_AutoClear
);
// Create forwarder events // Create forwarder eventsg
R_ABORT_UNLESS(InitializeBluetoothCoreEvents()); //R_ABORT_UNLESS(bluetooth::core::InitializeEvents());
R_TRY(bluetooth::core::InitializeEvents());
//bluetooth::events::AttachWaitHolder(BtdrvEventType_BluetoothCore);
// Set callers handle to that of our forwarder event // Set callers handle to that of our forwarder event
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btSystemEventFwd)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::core::GetForwardEvent()));
// Create and map fake bluetooth hid report shared memory // Create and map fake bluetooth hid report shared memory
R_ABORT_UNLESS(InitializeBluetoothHidReportFakeSharedMemory()); R_TRY(bluetooth::hid::report::InitializeFakeSharedMemory());
// Create thread for forwarding events // Create thread for forwarding events
R_ABORT_UNLESS(StartBluetoothCoreEventThread()); R_ABORT_UNLESS(bluetooth::core::StartEventHandlerThread());
//R_TRY(StartEventHandlerThread());
g_bluetoothInitialized = true; g_bluetoothInitialized = true;
} else { } else {
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btSystemEventUser)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::core::GetUserForwardEvent()));
} }
return ams::ResultSuccess(); return ams::ResultSuccess();
@ -143,20 +146,25 @@ namespace ams::mitm::btdrv {
R_ABORT_UNLESS(btdrvInitializeHidFwd(this->forward_service.get(), &handle, version)); R_ABORT_UNLESS(btdrvInitializeHidFwd(this->forward_service.get(), &handle, version));
// Attach the handle to our real system event // Attach the handle to our real system event
os::AttachReadableHandleToSystemEvent(&g_btHidSystemEvent, handle, false, os::EventClearMode_AutoClear); os::AttachReadableHandleToSystemEvent(bluetooth::hid::GetSystemEvent(),
handle,
false,
os::EventClearMode_AutoClear
);
// Create forwarder events // Create forwarder events
R_ABORT_UNLESS(InitializeBluetoothHidEvents()); R_ABORT_UNLESS(bluetooth::hid::InitializeEvents());
//bluetooth::events::AttachWaitHolder(BtdrvEventType_BluetoothHid);
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btHidSystemEventFwd)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::hid::GetForwardEvent()));
// Create thread for forwarding events // Create thread for forwarding events
R_ABORT_UNLESS(StartBluetoothHidEventThread()); R_ABORT_UNLESS(bluetooth::hid::StartEventHandlerThread());
g_hidInitialized = true; g_hidInitialized = true;
} }
else { else {
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btHidSystemEventUser)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::hid::GetUserForwardEvent()));
} }
return ams::ResultSuccess(); return ams::ResultSuccess();
@ -229,21 +237,25 @@ namespace ams::mitm::btdrv {
R_ABORT_UNLESS(btdrvRegisterHidReportEventFwd(this->forward_service.get(), &handle)); R_ABORT_UNLESS(btdrvRegisterHidReportEventFwd(this->forward_service.get(), &handle));
// Attach the handle to our real system event // Attach the handle to our real system event
os::AttachReadableHandleToSystemEvent(&g_btHidReportSystemEvent, handle, false, os::EventClearMode_AutoClear); os::AttachReadableHandleToSystemEvent(bluetooth::hid::report::GetSystemEvent(),
handle,
false,
os::EventClearMode_AutoClear
);
// Create forwarder events // Create forwarder events
R_ABORT_UNLESS(InitializeBluetoothHidReportEvents()); R_ABORT_UNLESS(bluetooth::hid::report::InitializeEvents());
// Set callers handle to that of our forwarder event // Set callers handle to that of our forwarder event
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btHidReportSystemEventFwd)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::hid::report::GetForwardEvent()));
// Create thread for forwarding events // Create thread for forwarding events
R_ABORT_UNLESS(StartBluetoothHidReportEventThread()); R_ABORT_UNLESS(bluetooth::hid::report::StartEventHandlerThread());
g_hidReportInitialized = true; g_hidReportInitialized = true;
} }
else { else {
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btHidReportSystemEventUser)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::hid::report::GetUserForwardEvent()));
} }
return ams::ResultSuccess(); return ams::ResultSuccess();
@ -295,13 +307,10 @@ namespace ams::mitm::btdrv {
R_ABORT_UNLESS(btdrvGetHidReportEventInfoFwd(this->forward_service.get(), &handle)); R_ABORT_UNLESS(btdrvGetHidReportEventInfoFwd(this->forward_service.get(), &handle));
// Load and map the real bluetooth shared memory // Load and map the real bluetooth shared memory
shmemLoadRemote(&g_realBtShmem, handle, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw); R_TRY(bluetooth::hid::report::MapRemoteSharedMemory(handle));
R_ABORT_UNLESS(shmemMap(&g_realBtShmem));
g_realCircBuff = reinterpret_cast<bluetooth::CircularBuffer *>(shmemGetAddr(&g_realBtShmem));
BTDRV_LOG_FMT("Real shmem @ 0x%p", (void *)g_realCircBuff);
// Return the handle of our fake shared memory to the caller instead // Return the handle of our fake shared memory to the caller instead
out_handle.SetValue(g_fakeBtShmem.handle); out_handle.SetValue(bluetooth::hid::report::GetFakeSharedMemory()->handle);
return ams::ResultSuccess(); return ams::ResultSuccess();
} }
@ -317,20 +326,19 @@ namespace ams::mitm::btdrv {
R_ABORT_UNLESS(btdrvInitializeBleFwd(this->forward_service.get(), &handle)); R_ABORT_UNLESS(btdrvInitializeBleFwd(this->forward_service.get(), &handle));
// Attach the handle to our real system event // Attach the handle to our real system event
os::AttachReadableHandleToSystemEvent(&g_btBleSystemEvent, handle, false, os::EventClearMode_AutoClear); os::AttachReadableHandleToSystemEvent(bluetooth::ble::GetSystemEvent(), handle, false, os::EventClearMode_AutoClear);
// Create forwarder events R_ABORT_UNLESS(bluetooth::ble::InitializeEvents());
R_ABORT_UNLESS(InitializeBluetoothBleEvents()); //bluetooth::events::AttachWaitHolder(BtdrvEventType_BluetoothBle);
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btBleSystemEventFwd)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::ble::GetForwardEvent()));
// Create thread for forwarding events R_ABORT_UNLESS(bluetooth::ble::StartEventHandlerThread());
R_ABORT_UNLESS(StartBluetoothBleEventThread());
g_bleInitialized = true; g_bleInitialized = true;
} }
else { else {
out_handle.SetValue(os::GetReadableHandleOfSystemEvent(&g_btBleSystemEventUser)); out_handle.SetValue(os::GetReadableHandleOfSystemEvent(bluetooth::ble::GetUserForwardEvent()));
} }
return ams::ResultSuccess(); return ams::ResultSuccess();

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "btdrv_mitm_logging.hpp"
#include "btdrv_mitm_logging.hpp"
namespace ams::mitm::btdrv { namespace ams::mitm::btdrv {

View file

@ -1,7 +1,6 @@
#include "btdrv_shim.h" #include "btdrv_shim.h"
#include <stratosphere/sf/sf_mitm_dispatch.h> #include <stratosphere/sf/sf_mitm_dispatch.h>
Result btdrvInitializeBluetoothFwd(Service* s, Handle *out_handle) { Result btdrvInitializeBluetoothFwd(Service* s, Handle *out_handle) {
return serviceMitmDispatch(s, 1, return serviceMitmDispatch(s, 1,
.out_handle_attrs = { SfOutHandleAttr_HipcCopy }, .out_handle_attrs = { SfOutHandleAttr_HipcCopy },

View file

@ -13,7 +13,6 @@
#include "btdrv_mitm_logging.hpp" #include "btdrv_mitm_logging.hpp"
namespace ams::mitm::btdrv { namespace ams::mitm::btdrv {
namespace { namespace {

View file

@ -2,7 +2,6 @@
#include <switch.h> #include <switch.h>
#include "controllers/bluetoothcontroller.hpp" #include "controllers/bluetoothcontroller.hpp"
namespace ams::mitm::btdrv { namespace ams::mitm::btdrv {
controller::ControllerType identifyController(uint16_t vid, uint16_t pid); controller::ControllerType identifyController(uint16_t vid, uint16_t pid);

View file

@ -56,6 +56,7 @@ void __appInit(void) {
sm::DoWithSession([&]() { sm::DoWithSession([&]() {
R_ABORT_UNLESS(fsInitialize()); R_ABORT_UNLESS(fsInitialize());
R_ABORT_UNLESS(pscmInitialize());
R_ABORT_UNLESS(pmdmntInitialize()); R_ABORT_UNLESS(pmdmntInitialize());
R_ABORT_UNLESS(pminfoInitialize()); R_ABORT_UNLESS(pminfoInitialize());
R_ABORT_UNLESS(btdrvInitialize()); R_ABORT_UNLESS(btdrvInitialize());
@ -68,11 +69,13 @@ void __appInit(void) {
} }
void __appExit(void) { void __appExit(void) {
fsdevUnmountAll();
//hiddbgExit(); //hiddbgExit();
btdrvExit(); btdrvExit();
pminfoExit(); pminfoExit();
pmdmntExit(); pmdmntExit();
pscmExit();
fsdevUnmountAll();
fsExit(); fsExit();
} }