From 0a7725f430cfef86763fb72fd3d8b691ccf088d8 Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 12 Sep 2020 15:09:33 +0200 Subject: [PATCH 1/2] bluetooth-mitm: add skeleton handler for steelseries controller --- .../controllers/controller_management.cpp | 11 ++++- .../controllers/controller_management.hpp | 2 + .../controllers/steelseries_controller.cpp | 44 +++++++++++++++++++ .../controllers/steelseries_controller.hpp | 42 ++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 bluetooth-mitm/source/controllers/steelseries_controller.cpp create mode 100644 bluetooth-mitm/source/controllers/steelseries_controller.hpp diff --git a/bluetooth-mitm/source/controllers/controller_management.cpp b/bluetooth-mitm/source/controllers/controller_management.cpp index 2a4171fa..0083115d 100644 --- a/bluetooth-mitm/source/controllers/controller_management.cpp +++ b/bluetooth-mitm/source/controllers/controller_management.cpp @@ -90,7 +90,13 @@ namespace ams::controller { return ControllerType_Xiaomi; } } - + + for (auto hwId : SteelseriesController::hardware_ids) { + if ( (device->vid == hwId.vid) && (device->pid == hwId.pid) ) { + return ControllerType_Steelseries; + } + } + return ControllerType_Unknown; } @@ -144,6 +150,9 @@ namespace ams::controller { case ControllerType_Xiaomi: g_controllers.push_back(std::make_unique(address)); break; + case ControllerType_Steelseries: + g_controllers.push_back(std::make_unique(address)); + break; default: g_controllers.push_back(std::make_unique(address)); break; diff --git a/bluetooth-mitm/source/controllers/controller_management.hpp b/bluetooth-mitm/source/controllers/controller_management.hpp index 17a796b6..b37a023d 100644 --- a/bluetooth-mitm/source/controllers/controller_management.hpp +++ b/bluetooth-mitm/source/controllers/controller_management.hpp @@ -26,6 +26,7 @@ #include "gembox_controller.hpp" #include "ipega_controller.hpp" #include "xiaomi_controller.hpp" +#include "steelseries_controller.hpp" namespace ams::controller { @@ -42,6 +43,7 @@ namespace ams::controller { ControllerType_Gembox, ControllerType_Ipega, ControllerType_Xiaomi, + ControllerType_Steelseries, ControllerType_Unknown, }; diff --git a/bluetooth-mitm/source/controllers/steelseries_controller.cpp b/bluetooth-mitm/source/controllers/steelseries_controller.cpp new file mode 100644 index 00000000..bb59b664 --- /dev/null +++ b/bluetooth-mitm/source/controllers/steelseries_controller.cpp @@ -0,0 +1,44 @@ +/* + * 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 "steelseries_controller.hpp" +#include + +namespace ams::controller { + + namespace { + + + } + + void SteelseriesController::ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report) { + auto steelseries_report = reinterpret_cast(&in_report->data); + auto switch_report = reinterpret_cast(&out_report->data); + + switch(steelseries_report->id) { + 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; + } + +} diff --git a/bluetooth-mitm/source/controllers/steelseries_controller.hpp b/bluetooth-mitm/source/controllers/steelseries_controller.hpp new file mode 100644 index 00000000..18cd5ca9 --- /dev/null +++ b/bluetooth-mitm/source/controllers/steelseries_controller.hpp @@ -0,0 +1,42 @@ +/* + * 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 { + + struct SteelseriesReportData { + uint8_t id; + } __attribute__((packed)); + + class SteelseriesController : public EmulatedSwitchController { + + public: + static constexpr const HardwareID hardware_ids[] = { + {0x1038, 0x1412} + }; + + SteelseriesController(const bluetooth::Address *address) + : EmulatedSwitchController(address) { }; + + void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); + + private: + + }; + +} From c1fa8229f81bad07306b125e4db655a7628d385d Mon Sep 17 00:00:00 2001 From: ndeadly <24677491+ndeadly@users.noreply.github.com> Date: Sat, 12 Sep 2020 17:56:18 +0200 Subject: [PATCH 2/2] bluetooth-mitm: add button mappings for steelseries controller --- .../controllers/steelseries_controller.cpp | 49 +++++++++++++++++++ .../controllers/steelseries_controller.hpp | 46 ++++++++++++++++- 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/bluetooth-mitm/source/controllers/steelseries_controller.cpp b/bluetooth-mitm/source/controllers/steelseries_controller.cpp index bb59b664..0a8abe31 100644 --- a/bluetooth-mitm/source/controllers/steelseries_controller.cpp +++ b/bluetooth-mitm/source/controllers/steelseries_controller.cpp @@ -21,6 +21,7 @@ namespace ams::controller { namespace { + const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX; } @@ -29,6 +30,9 @@ namespace ams::controller { auto switch_report = reinterpret_cast(&out_report->data); switch(steelseries_report->id) { + case 0x01: + this->HandleInputReport0x01(steelseries_report, switch_report); + break; default: break; } @@ -41,4 +45,49 @@ namespace ams::controller { switch_report->input0x30.timer = os::ConvertToTimeSpan(os::GetSystemTick()).GetMilliSeconds() & 0xff; } + void SteelseriesController::HandleInputReport0x01(const SteelseriesReportData *src, SwitchReportData *dst) { + this->PackStickData(&dst->input0x30.left_stick, + static_cast(stick_scale_factor * -static_cast(~src->input0x01.left_stick.x + 1) + 0x7ff) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX + static_cast(~src->input0x01.left_stick.y + 1)) + 0x7ff) & 0xfff + ); + this->PackStickData(&dst->input0x30.right_stick, + static_cast(stick_scale_factor * -static_cast(~src->input0x01.right_stick.x + 1) + 0x7ff) & 0xfff, + static_cast(stick_scale_factor * (UINT8_MAX + static_cast(~src->input0x01.right_stick.y + 1)) + 0x7ff) & 0xfff + ); + + dst->input0x30.buttons.dpad_down = (src->input0x01.dpad == SteelseriesDPad_S) || + (src->input0x01.dpad == SteelseriesDPad_SE) || + (src->input0x01.dpad == SteelseriesDPad_SW); + dst->input0x30.buttons.dpad_up = (src->input0x01.dpad == SteelseriesDPad_N) || + (src->input0x01.dpad == SteelseriesDPad_NE) || + (src->input0x01.dpad == SteelseriesDPad_NW); + dst->input0x30.buttons.dpad_right = (src->input0x01.dpad == SteelseriesDPad_E) || + (src->input0x01.dpad == SteelseriesDPad_NE) || + (src->input0x01.dpad == SteelseriesDPad_SE); + dst->input0x30.buttons.dpad_left = (src->input0x01.dpad == SteelseriesDPad_W) || + (src->input0x01.dpad == SteelseriesDPad_NW) || + (src->input0x01.dpad == SteelseriesDPad_SW); + + dst->input0x30.buttons.A = src->input0x01.buttons.B; + dst->input0x30.buttons.B = src->input0x01.buttons.A; + dst->input0x30.buttons.X = src->input0x01.buttons.Y; + dst->input0x30.buttons.Y = src->input0x01.buttons.X; + + dst->input0x30.buttons.R = src->input0x01.buttons.R; + dst->input0x30.buttons.L = src->input0x01.buttons.L; + + dst->input0x30.buttons.minus = src->input0x01.buttons.select; + dst->input0x30.buttons.plus = src->input0x01.buttons.start; + + dst->input0x30.buttons.capture = 0; + + // Home button combo + dst->input0x30.buttons.home = dst->input0x30.buttons.dpad_down & dst->input0x30.buttons.minus; + if (dst->input0x30.buttons.home){ + dst->input0x30.buttons.dpad_down = 0; + dst->input0x30.buttons.minus = 0; + } + + } + } diff --git a/bluetooth-mitm/source/controllers/steelseries_controller.hpp b/bluetooth-mitm/source/controllers/steelseries_controller.hpp index 18cd5ca9..77b7c16f 100644 --- a/bluetooth-mitm/source/controllers/steelseries_controller.hpp +++ b/bluetooth-mitm/source/controllers/steelseries_controller.hpp @@ -19,8 +19,51 @@ namespace ams::controller { - struct SteelseriesReportData { + enum SteelseriesDPadDirection { + SteelseriesDPad_N, + SteelseriesDPad_NE, + SteelseriesDPad_E, + SteelseriesDPad_SE, + SteelseriesDPad_S, + SteelseriesDPad_SW, + SteelseriesDPad_W, + SteelseriesDPad_NW, + SteelseriesDPad_Released = 0x0f + }; + + struct SteelseriesStickData { + uint8_t x; + uint8_t y; + } __attribute__ ((__packed__)); + + struct SteelseriesButtonData { + 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 : 3; + uint8_t start : 1; + uint8_t select : 1; + uint8_t : 0; + } __attribute__ ((__packed__)); + + struct SteelseriesInputReport0x01 { + uint8_t dpad; + SteelseriesStickData left_stick; + SteelseriesStickData right_stick; + SteelseriesButtonData buttons; + } __attribute__((packed)); + + struct SteelseriesReportData { uint8_t id; + union { + SteelseriesInputReport0x01 input0x01; + }; } __attribute__((packed)); class SteelseriesController : public EmulatedSwitchController { @@ -36,6 +79,7 @@ namespace ams::controller { void ConvertReportFormat(const bluetooth::HidReport *in_report, bluetooth::HidReport *out_report); private: + void HandleInputReport0x01(const SteelseriesReportData *src, SwitchReportData *dst); };