2020-06-13 19:27:07 +00:00
|
|
|
#include "bluetooth_hid_report.hpp"
|
2020-06-14 22:18:46 +00:00
|
|
|
|
|
|
|
#include <atomic>
|
2020-06-22 21:14:54 +00:00
|
|
|
#include <mutex>
|
|
|
|
#include <cstring>
|
2020-06-13 22:41:14 +00:00
|
|
|
#include "bluetooth_circularbuffer.hpp"
|
2020-06-13 00:08:43 +00:00
|
|
|
#include "../btdrv_mitm_flags.hpp"
|
|
|
|
#include "../controllermanager.hpp"
|
|
|
|
#include "../controllers/bluetoothcontroller.hpp"
|
|
|
|
#include "../controllers/switchcontroller.hpp"
|
|
|
|
|
|
|
|
#include "../btdrv_mitm_logging.hpp"
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
namespace ams::bluetooth::hid::report {
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
namespace {
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-14 22:18:46 +00:00
|
|
|
std::atomic<bool> g_isInitialized(false);
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
os::ThreadType g_eventHandlerThread;
|
|
|
|
alignas(os::ThreadStackAlignment) u8 g_eventHandlerThreadStack[0x2000];
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-14 22:18:46 +00:00
|
|
|
// This is only required on fw < 7.0.0
|
|
|
|
os::Mutex g_eventDataLock(false);
|
|
|
|
u8 g_eventDataBuffer[0x480];
|
|
|
|
HidEventType g_currentEventType;
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
SharedMemory g_realBtShmem;
|
|
|
|
SharedMemory g_fakeBtShmem;
|
|
|
|
|
2020-06-14 11:10:09 +00:00
|
|
|
bluetooth::CircularBuffer *g_realBuffer;
|
|
|
|
bluetooth::CircularBuffer *g_fakeBuffer;
|
2020-06-13 17:15:59 +00:00
|
|
|
|
|
|
|
os::SystemEventType g_btHidReportSystemEvent;
|
|
|
|
os::SystemEventType g_btHidReportSystemEventFwd;
|
|
|
|
os::SystemEventType g_btHidReportSystemEventUser;
|
|
|
|
|
|
|
|
u8 g_fakeReportBuffer[0x42] = {};
|
|
|
|
HidReportData *g_fakeReportData = reinterpret_cast<HidReportData *>(g_fakeReportBuffer);
|
|
|
|
|
2020-07-09 21:31:39 +00:00
|
|
|
// Buffer for hid report responses. Might be able to replace the above
|
|
|
|
HidReport g_hidReport = {};
|
|
|
|
|
|
|
|
|
2020-06-14 22:18:46 +00:00
|
|
|
void EventThreadFunc(void *arg) {
|
|
|
|
while (true) {
|
|
|
|
os::WaitSystemEvent(&g_btHidReportSystemEvent);
|
|
|
|
HandleEvent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInitialized(void) {
|
|
|
|
return g_isInitialized;
|
2020-06-13 17:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SharedMemory *GetRealSharedMemory(void) {
|
|
|
|
return &g_realBtShmem;
|
|
|
|
}
|
|
|
|
|
|
|
|
SharedMemory *GetFakeSharedMemory(void) {
|
|
|
|
return &g_fakeBtShmem;
|
|
|
|
}
|
|
|
|
|
|
|
|
os::SystemEventType *GetSystemEvent(void) {
|
|
|
|
return &g_btHidReportSystemEvent;
|
|
|
|
}
|
|
|
|
|
|
|
|
os::SystemEventType *GetForwardEvent(void) {
|
|
|
|
return &g_btHidReportSystemEventFwd;
|
|
|
|
}
|
|
|
|
|
|
|
|
os::SystemEventType *GetUserForwardEvent(void) {
|
|
|
|
return &g_btHidReportSystemEventUser;
|
|
|
|
}
|
|
|
|
|
2020-06-14 22:18:46 +00:00
|
|
|
Result Initialize(Handle eventHandle) {
|
|
|
|
os::AttachReadableHandleToSystemEvent(&g_btHidReportSystemEvent, eventHandle, false, os::EventClearMode_AutoClear);
|
|
|
|
|
|
|
|
R_TRY(os::CreateSystemEvent(&g_btHidReportSystemEventFwd, os::EventClearMode_AutoClear, true));
|
|
|
|
R_TRY(os::CreateSystemEvent(&g_btHidReportSystemEventUser, os::EventClearMode_AutoClear, true));
|
|
|
|
|
|
|
|
R_TRY(os::CreateThread(&g_eventHandlerThread,
|
|
|
|
EventThreadFunc,
|
|
|
|
nullptr,
|
|
|
|
g_eventHandlerThreadStack,
|
|
|
|
sizeof(g_eventHandlerThreadStack),
|
|
|
|
-10
|
|
|
|
));
|
|
|
|
|
|
|
|
os::StartThread(&g_eventHandlerThread);
|
|
|
|
|
|
|
|
g_isInitialized = true;
|
|
|
|
|
|
|
|
return ams::ResultSuccess();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Finalize(void) {
|
|
|
|
os::DestroyThread(&g_eventHandlerThread);
|
|
|
|
|
2020-07-09 17:44:12 +00:00
|
|
|
//if (hos::GetVersion() < hos::Version_7_0_0)
|
|
|
|
//delete g_fakeBuffer;
|
|
|
|
|
2020-06-14 22:18:46 +00:00
|
|
|
os::DestroySystemEvent(&g_btHidReportSystemEventUser);
|
|
|
|
os::DestroySystemEvent(&g_btHidReportSystemEventFwd);
|
|
|
|
|
|
|
|
g_isInitialized = false;
|
|
|
|
}
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
Result MapRemoteSharedMemory(Handle handle) {
|
|
|
|
shmemLoadRemote(&g_realBtShmem, handle, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw);
|
|
|
|
R_TRY(shmemMap(&g_realBtShmem));
|
2020-06-14 11:10:09 +00:00
|
|
|
g_realBuffer = reinterpret_cast<bluetooth::CircularBuffer *>(shmemGetAddr(&g_realBtShmem));
|
|
|
|
BTDRV_LOG_FMT("Real shmem @ 0x%p", (void *)g_realBuffer);
|
2020-06-13 17:15:59 +00:00
|
|
|
|
|
|
|
return ams::ResultSuccess();
|
|
|
|
}
|
|
|
|
|
2020-07-09 17:44:12 +00:00
|
|
|
Result InitializeReportBuffer(void) {
|
|
|
|
BTDRV_LOG_FMT("btdrv-mitm: InitializeReportBuffer");
|
|
|
|
|
|
|
|
// Todo: maybe just create shared memory for all fw?
|
|
|
|
if (hos::GetVersion() < hos::Version_7_0_0) {
|
|
|
|
g_fakeBuffer = new CircularBuffer();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
R_TRY(shmemCreate(&g_fakeBtShmem, BLUETOOTH_SHAREDMEM_SIZE, Perm_Rw, Perm_Rw));
|
|
|
|
R_TRY(shmemMap(&g_fakeBtShmem));
|
|
|
|
g_fakeBuffer = reinterpret_cast<CircularBuffer *>(shmemGetAddr(&g_fakeBtShmem));
|
|
|
|
}
|
|
|
|
|
|
|
|
g_fakeBuffer->Initialize("HID Report");
|
|
|
|
g_fakeBuffer->type = CircularBufferType_HidReport;
|
|
|
|
g_fakeBuffer->_unk3 = 1;
|
|
|
|
|
|
|
|
return ams::ResultSuccess();
|
|
|
|
}
|
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
/* Write a fake report into the circular buffer */
|
2020-07-01 13:34:07 +00:00
|
|
|
Result WriteFakeHidData(const Address *address, const HidData *data) {
|
2020-06-30 20:23:16 +00:00
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
BTDRV_LOG_DATA_MSG((void*)data, data->length + sizeof(data->length), "btdrv-mitm: WriteFakeHidData");
|
2020-06-30 20:23:16 +00:00
|
|
|
|
|
|
|
u16 bufferSize = data->length + 0x11;
|
|
|
|
u8 buffer[bufferSize] = {};
|
|
|
|
auto fakeReportData = reinterpret_cast<HidReportData *>(buffer);
|
|
|
|
|
|
|
|
if (hos::GetVersion() < hos::Version_9_0_0) {
|
|
|
|
fakeReportData->size = bufferSize;
|
2020-07-01 13:34:07 +00:00
|
|
|
std::memcpy(&fakeReportData->address, address, sizeof(Address));
|
2020-07-01 08:41:23 +00:00
|
|
|
std::memcpy(&fakeReportData->report, data, data->length + sizeof(data->length));
|
2020-06-30 20:23:16 +00:00
|
|
|
}
|
|
|
|
else {
|
2020-07-01 13:34:07 +00:00
|
|
|
std::memcpy(&fakeReportData->v2.address, address, sizeof(Address));
|
2020-07-01 08:41:23 +00:00
|
|
|
std::memcpy(&fakeReportData->v2.report, data, data->length + sizeof(data->length));
|
2020-06-30 20:23:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_fakeBuffer->Write(4, fakeReportData, bufferSize);
|
|
|
|
os::SignalSystemEvent(&g_btHidReportSystemEventFwd);
|
|
|
|
|
|
|
|
return ams::ResultSuccess();
|
|
|
|
}
|
|
|
|
|
2020-07-09 21:31:39 +00:00
|
|
|
/* Write a fake subcommand response into buffer */
|
|
|
|
Result FakeSubCmdResponse(const bluetooth::Address *address, u8 response[], size_t size) {
|
|
|
|
auto report = &g_hidReport;
|
|
|
|
report->type = 0x31; // This is actually size, need to rename
|
|
|
|
report->id = 0x21;
|
|
|
|
|
|
|
|
auto reportData = reinterpret_cast<controller::SwitchReport0x21 *>(&report->data);
|
|
|
|
reportData->conn_info = 0;
|
|
|
|
reportData->battery = 8;
|
|
|
|
reportData->buttons = {0x00, 0x00, 0x00};
|
|
|
|
reportData->left_stick = {0x0b, 0xb8, 0x78};
|
|
|
|
reportData->right_stick = {0xd9, 0xd7, 0x81};
|
|
|
|
reportData->vibrator = 0;
|
|
|
|
std::memcpy(&reportData->subcmd, response, size);
|
|
|
|
|
|
|
|
reportData->timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff;
|
|
|
|
|
|
|
|
// Todo: change types so we don't have to cast
|
|
|
|
return bluetooth::hid::report::WriteFakeHidData(address, reinterpret_cast<bluetooth::HidData *>(report));
|
|
|
|
}
|
|
|
|
|
2020-06-22 21:14:54 +00:00
|
|
|
/* Only used for < 7.0.0. newer firmwares read straight from shared memory */
|
|
|
|
Result GetEventInfo(HidEventType *type, u8* buffer, size_t size) {
|
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
/*
|
|
|
|
auto packet = reinterpret_cast<CircularBufferPacket *>(g_fakeBuffer->Read());
|
|
|
|
if (!packet)
|
|
|
|
return -1;
|
|
|
|
*/
|
2020-06-28 15:22:37 +00:00
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
//BTDRV_LOG_FMT("!!! GetEventInfo Called");
|
2020-06-22 21:14:54 +00:00
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
CircularBufferPacket *packet;
|
2020-06-22 21:14:54 +00:00
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
while (true) {
|
|
|
|
if (g_fakeBuffer->readOffset == g_fakeBuffer->writeOffset)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Get packet from real buffer
|
|
|
|
packet = reinterpret_cast<CircularBufferPacket *>(&g_fakeBuffer->data[g_fakeBuffer->readOffset]);
|
|
|
|
if (!packet)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Move read pointer past current packet (I think this is what Free does)
|
|
|
|
if (g_fakeBuffer->readOffset != g_fakeBuffer->writeOffset) {
|
|
|
|
u32 newOffset = g_fakeBuffer->readOffset + packet->header.size + sizeof(CircularBufferPacketHeader);
|
|
|
|
if (newOffset >= BLUETOOTH_CIRCBUFFER_SIZE)
|
|
|
|
newOffset = 0;
|
|
|
|
|
|
|
|
g_fakeBuffer->_setReadOffset(newOffset);
|
2020-06-22 21:14:54 +00:00
|
|
|
}
|
2020-07-09 19:26:22 +00:00
|
|
|
|
|
|
|
if (packet->header.type == 0xff)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
break;
|
2020-06-28 15:22:37 +00:00
|
|
|
}
|
2020-07-09 19:26:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto eventData = reinterpret_cast<HidEventData *>(buffer);
|
|
|
|
|
|
|
|
*type = static_cast<HidEventType>(packet->header.type);
|
|
|
|
std::memcpy(&eventData->getReport.address, &packet->data.address, sizeof(Address));
|
|
|
|
eventData->getReport.status = HidStatus_Ok;
|
|
|
|
eventData->getReport.report_length = packet->header.size;
|
|
|
|
|
|
|
|
std::memcpy(&eventData->getReport.report_data, &packet->data, packet->header.size);
|
|
|
|
|
|
|
|
//BTDRV_LOG_DATA_MSG(&packet->data, packet->header.size, "btdrv-mitm: hid::report::GetEventInfo -> Read");
|
|
|
|
//g_fakeBuffer->Free();
|
2020-06-22 21:14:54 +00:00
|
|
|
|
|
|
|
return ams::ResultSuccess();
|
|
|
|
}
|
|
|
|
|
2020-07-09 19:26:22 +00:00
|
|
|
void _HandleEvent() {
|
2020-06-13 17:15:59 +00:00
|
|
|
controller::BluetoothController *controller;
|
2020-06-28 15:22:37 +00:00
|
|
|
CircularBufferPacket *realPacket;
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
// Take snapshot of current write offset
|
2020-06-14 11:10:09 +00:00
|
|
|
u32 writeOffset = g_realBuffer->writeOffset;
|
2020-06-13 17:15:59 +00:00
|
|
|
|
|
|
|
while (true) {
|
2020-06-14 11:10:09 +00:00
|
|
|
if (g_realBuffer->readOffset == writeOffset)
|
2020-06-13 00:08:43 +00:00
|
|
|
break;
|
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
// Get packet from real buffer
|
2020-06-14 11:10:09 +00:00
|
|
|
//realPacket = reinterpret_cast<bluetooth::CircularBufferPacket *>(g_realBuffer->_read());
|
|
|
|
realPacket = reinterpret_cast<CircularBufferPacket *>(&g_realBuffer->data[g_realBuffer->readOffset]);
|
2020-06-13 17:15:59 +00:00
|
|
|
if (!realPacket)
|
|
|
|
break;
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
// Move read pointer past current packet (I think this is what Free does)
|
2020-06-14 11:10:09 +00:00
|
|
|
if (g_realBuffer->readOffset != writeOffset) {
|
|
|
|
u32 newOffset = g_realBuffer->readOffset + realPacket->header.size + sizeof(CircularBufferPacketHeader);
|
2020-06-13 17:15:59 +00:00
|
|
|
if (newOffset >= BLUETOOTH_CIRCBUFFER_SIZE)
|
|
|
|
newOffset = 0;
|
|
|
|
|
2020-06-14 11:10:09 +00:00
|
|
|
g_realBuffer->_setReadOffset(newOffset);
|
2020-06-13 17:15:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//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;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
if (!controller) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller->isSwitchController()) {
|
|
|
|
// Write unmodified packet directly to fake buffer (_write call will add new timestamp)
|
2020-06-14 11:10:09 +00:00
|
|
|
g_fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size);
|
2020-06-13 17:15:59 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
const HidReport *inReport;
|
|
|
|
HidReport *outReport;
|
|
|
|
// copy address and stuff over
|
2020-06-14 23:52:31 +00:00
|
|
|
if (hos::GetVersion() < hos::Version_9_0_0) {
|
2020-07-09 19:26:22 +00:00
|
|
|
g_fakeReportData->size = 0x42;
|
2020-07-01 13:34:07 +00:00
|
|
|
std::memcpy(&g_fakeReportData->address, &realPacket->data.address, sizeof(Address));
|
2020-06-13 17:15:59 +00:00
|
|
|
inReport = &realPacket->data.report;
|
|
|
|
outReport = &g_fakeReportData->report;
|
|
|
|
}
|
|
|
|
else {
|
2020-07-01 13:34:07 +00:00
|
|
|
std::memcpy(&g_fakeReportData->v2.address, &realPacket->data.v2.address, sizeof(Address));
|
2020-06-13 17:15:59 +00:00
|
|
|
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
|
2020-06-25 21:50:43 +00:00
|
|
|
g_fakeBuffer->Write(4, g_fakeReportData, sizeof(g_fakeReportBuffer));
|
2020-06-13 17:15:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
default:
|
2020-06-28 15:22:37 +00:00
|
|
|
|
|
|
|
BTDRV_LOG_FMT("unknown packet received: %d", realPacket->header.type);
|
|
|
|
//g_fakeBuffer->Write(realPacket->header.type, &realPacket->data, realPacket->header.size);
|
2020-06-13 17:15:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-06-13 17:15:59 +00:00
|
|
|
}
|
2020-07-09 19:26:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void _HandleEventDeprecated(void) {
|
|
|
|
|
|
|
|
std::scoped_lock lk(g_eventDataLock);
|
|
|
|
R_ABORT_UNLESS(btdrvGetHidReportEventInfo(&g_currentEventType, g_eventDataBuffer, sizeof(g_eventDataBuffer)));
|
|
|
|
|
|
|
|
auto eventData = reinterpret_cast<HidEventData *>(g_eventDataBuffer);
|
|
|
|
|
|
|
|
//BTDRV_LOG_FMT("hid report event [%02d]", g_currentEventType);
|
|
|
|
|
|
|
|
switch (g_currentEventType) {
|
|
|
|
|
|
|
|
case HidEvent_GetReport:
|
|
|
|
{
|
|
|
|
// Locate the controller that sent the report
|
|
|
|
auto controller = ams::mitm::btdrv::locateController(&eventData->getReport.address);
|
|
|
|
if (!controller) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (controller->isSwitchController()) {
|
|
|
|
//BTDRV_LOG_DATA_MSG(&eventData->getReport.report_data, eventData->getReport.report_length, "Switch controller -> Write");
|
2020-07-09 21:31:39 +00:00
|
|
|
g_fakeBuffer->Write(g_currentEventType, &eventData->getReport.report_data, eventData->getReport.report_length);
|
2020-07-09 19:26:22 +00:00
|
|
|
//BTDRV_LOG_FMT("Write result: %d", rc);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const HidReport *inReport;
|
|
|
|
HidReport *outReport;
|
|
|
|
|
|
|
|
//BTDRV_LOG_FMT("Non-Switch controller");
|
|
|
|
|
|
|
|
g_fakeReportData->size = 0x42; // Todo: check size is correct for report 0x30
|
|
|
|
std::memcpy(&g_fakeReportData->address, &eventData->getReport.address, sizeof(Address));
|
|
|
|
inReport = &eventData->getReport.report_data.report;
|
|
|
|
outReport = &g_fakeReportData->report;
|
|
|
|
|
|
|
|
auto switchData = reinterpret_cast<controller::SwitchReportData *>(&outReport->data);
|
|
|
|
switchData->report0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).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
|
|
|
|
g_fakeBuffer->Write(4, g_fakeReportData, sizeof(g_fakeReportBuffer));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
BTDRV_LOG_FMT("unknown packet received: %d", g_currentEventType);
|
|
|
|
//g_fakeBuffer->Write(g_currentEventType, &eventData->getReport.report_data, &eventData->getReport.report_length);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HandleEvent(void) {
|
|
|
|
|
|
|
|
if (hos::GetVersion() < hos::Version_7_0_0) {
|
|
|
|
_HandleEventDeprecated();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_HandleEvent();
|
|
|
|
}
|
2020-06-13 00:08:43 +00:00
|
|
|
|
2020-07-09 17:38:53 +00:00
|
|
|
if (!g_redirectHidReportEvents) {
|
|
|
|
os::SignalSystemEvent(&g_btHidReportSystemEventFwd);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
os::SignalSystemEvent(&g_btHidReportSystemEventUser);
|
|
|
|
}
|
|
|
|
|
2020-06-13 00:08:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|