diff --git a/bluetooth-mitm/source/controllers/8bitdo_controller.cpp b/bluetooth-mitm/source/controllers/8bitdo_controller.cpp
new file mode 100644
index 0000000..103f155
--- /dev/null
+++ b/bluetooth-mitm/source/controllers/8bitdo_controller.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2020 ndeadly
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ */
+#include "8bitdo_controller.hpp"
+#include
+
+namespace ams::controller {
+
+ void EightBitDoController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) {
+ auto eightbitdo_report = reinterpret_cast(&in_report->data);
+ auto switch_report = reinterpret_cast(&out_report->data);
+
+ switch(eightbitdo_report->id) {
+ case 0x01:
+ this->HandleInputReport0x01(eightbitdo_report, switch_report);
+ break;
+ case 0x03:
+ this->HandleInputReport0x03(eightbitdo_report, switch_report);
+ break;
+ default:
+ break;
+ }
+
+ out_report->size = sizeof(SwitchInputReport0x30) + 1;
+ switch_report->id = 0x30;
+ switch_report->input0x30.conn_info = 0x0;
+ switch_report->input0x30.battery = m_battery | m_charging;
+ std::memset(switch_report->input0x30.motion, 0, sizeof(switch_report->input0x30.motion));
+ switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff;
+ }
+
+ void EightBitDoController::HandleInputReport0x01(const EightBitDoReportData *src, SwitchReportData *dst) {
+ dst->input0x30.buttons.dpad_down = (src->input0x01.dpad == EightBitDoDPad_S) ||
+ (src->input0x01.dpad == EightBitDoDPad_SE) ||
+ (src->input0x01.dpad == EightBitDoDPad_SW);
+ dst->input0x30.buttons.dpad_up = (src->input0x01.dpad == EightBitDoDPad_N) ||
+ (src->input0x01.dpad == EightBitDoDPad_NE) ||
+ (src->input0x01.dpad == EightBitDoDPad_NW);
+ dst->input0x30.buttons.dpad_right = (src->input0x01.dpad == EightBitDoDPad_E) ||
+ (src->input0x01.dpad == EightBitDoDPad_NE) ||
+ (src->input0x01.dpad == EightBitDoDPad_SE);
+ dst->input0x30.buttons.dpad_left = (src->input0x01.dpad == EightBitDoDPad_W) ||
+ (src->input0x01.dpad == EightBitDoDPad_NW) ||
+ (src->input0x01.dpad == EightBitDoDPad_SW);
+
+ }
+
+ void EightBitDoController::HandleInputReport0x03(const EightBitDoReportData *src, SwitchReportData *dst) {
+ dst->input0x30.buttons.A = src->input0x03.buttons.B;
+ dst->input0x30.buttons.B = src->input0x03.buttons.A;
+ dst->input0x30.buttons.X = src->input0x03.buttons.Y;
+ dst->input0x30.buttons.Y = src->input0x03.buttons.X;
+
+ dst->input0x30.buttons.R = src->input0x03.buttons.R;
+ dst->input0x30.buttons.L = src->input0x03.buttons.L;
+
+ dst->input0x30.buttons.minus = src->input0x03.buttons.select;
+ dst->input0x30.buttons.plus = src->input0x03.buttons.start;
+
+ // Home combo
+ dst->input0x30.buttons.home = dst->input0x30.buttons.minus && dst->input0x30.buttons.dpad_down;
+ if (dst->input0x30.buttons.home) {
+ dst->input0x30.buttons.minus = 0;
+ dst->input0x30.buttons.dpad_down = 0;
+ }
+ }
+
+}
diff --git a/bluetooth-mitm/source/controllers/8bitdo_controller.hpp b/bluetooth-mitm/source/controllers/8bitdo_controller.hpp
new file mode 100644
index 0000000..af37b55
--- /dev/null
+++ b/bluetooth-mitm/source/controllers/8bitdo_controller.hpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2020 ndeadly
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 .
+ */
+#pragma once
+#include "emulated_switch_controller.hpp"
+
+namespace ams::controller {
+
+ enum EightBitDoDPadDirection : uint16_t {
+ EightBitDoDPad_Released = 0x0000,
+ EightBitDoDPad_N = 0x0052,
+ EightBitDoDPad_NE = 0x524f,
+ EightBitDoDPad_E = 0x004f,
+ EightBitDoDPad_SE = 0x4f51,
+ EightBitDoDPad_S = 0x0051,
+ EightBitDoDPad_SW = 0x5150,
+ EightBitDoDPad_W = 0x0050,
+ EightBitDoDPad_NW = 0x5250,
+ };
+
+ struct EightBitDoStickData {
+ uint8_t x;
+ uint8_t y;
+ } __attribute__((packed));
+
+ struct EightBitDoButtonData {
+ uint8_t A : 1;
+ uint8_t B : 1;
+ uint8_t : 1;
+ uint8_t X : 1;
+ uint8_t Y : 1;
+ uint8_t : 1;
+ uint8_t L : 1;
+ uint8_t R : 1;
+
+ uint8_t : 2;
+ uint8_t select : 1;
+ uint8_t start : 1;
+ uint8_t : 0;
+ }__attribute__((packed));
+
+ struct EightBitDoInputReport0x01 {
+ uint8_t _unk0[2];
+ uint16_t dpad;
+ uint8_t _unk1[4];
+ } __attribute__((packed));
+
+ struct EightBitDoInputReport0x03 {
+ uint8_t dpad;
+ EightBitDoStickData left_stick;
+ EightBitDoStickData right_stick;
+ uint8_t _unk[3];
+ EightBitDoButtonData buttons;
+ } __attribute__((packed));
+
+ struct EightBitDoReportData{
+ uint8_t id;
+ union {
+ EightBitDoInputReport0x01 input0x01;
+ EightBitDoInputReport0x03 input0x03;
+ };
+ } __attribute__((packed));
+
+ class EightBitDoController : public EmulatedSwitchController {
+
+ public:
+ static constexpr const HardwareID hardware_ids[] = {
+ {0x05a0, 0x3232} // 8BitDo Zero
+ };
+
+ EightBitDoController(const bluetooth::Address *address)
+ : EmulatedSwitchController(address) { };
+
+ void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report);
+
+ private:
+ void HandleInputReport0x01(const EightBitDoReportData *src, SwitchReportData *dst);
+ void HandleInputReport0x03(const EightBitDoReportData *src, SwitchReportData *dst);
+
+ };
+
+
+}
diff --git a/bluetooth-mitm/source/controllers/controller_management.cpp b/bluetooth-mitm/source/controllers/controller_management.cpp
index fa6f3af..788588a 100644
--- a/bluetooth-mitm/source/controllers/controller_management.cpp
+++ b/bluetooth-mitm/source/controllers/controller_management.cpp
@@ -106,6 +106,12 @@ namespace ams::controller {
for (auto hwId : NvidiaShieldController::hardware_ids) {
if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) {
return ControllerType_NvidiaShield;
+ }
+ }
+
+ for (auto hwId : EightBitDoController::hardware_ids) {
+ if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) {
+ return ControllerType_8BitDo;
}
}
@@ -170,6 +176,9 @@ namespace ams::controller {
break;
case ControllerType_NvidiaShield:
g_controllers.push_back(std::make_unique(address));
+ break;
+ case ControllerType_8BitDo:
+ g_controllers.push_back(std::make_unique(address));
break;
default:
g_controllers.push_back(std::make_unique(address));
diff --git a/bluetooth-mitm/source/controllers/controller_management.hpp b/bluetooth-mitm/source/controllers/controller_management.hpp
index ea50919..e5a5f30 100644
--- a/bluetooth-mitm/source/controllers/controller_management.hpp
+++ b/bluetooth-mitm/source/controllers/controller_management.hpp
@@ -29,6 +29,7 @@
#include "gamesir_controller.hpp"
#include "steelseries_controller.hpp"
#include "nvidia_shield_controller.hpp"
+#include "8bitdo_controller.hpp"
namespace ams::controller {
@@ -48,6 +49,7 @@ namespace ams::controller {
ControllerType_Gamesir,
ControllerType_Steelseries,
ControllerType_NvidiaShield,
+ ControllerType_8BitDo,
ControllerType_Unknown,
};