mirror of
https://github.com/ndeadly/MissionControl
synced 2024-11-26 14:20:21 +00:00
bluetooth-mitm: extended report, battery, and player LEDs for DualSense (#180)
This commit is contained in:
parent
3d635cc468
commit
d1ec785a08
2 changed files with 135 additions and 6 deletions
|
@ -22,6 +22,51 @@ namespace ams::controller {
|
|||
|
||||
const constexpr float stick_scale_factor = float(UINT12_MAX) / UINT8_MAX;
|
||||
|
||||
const uint8_t player_led_flags[] = {
|
||||
// Mimic the Switch's player LEDs
|
||||
0x01,
|
||||
0x03,
|
||||
0x0B,
|
||||
0x1B,
|
||||
0x11,
|
||||
0x09,
|
||||
0x19,
|
||||
0x0A
|
||||
};
|
||||
|
||||
const RGBColour player_led_colours[] = {
|
||||
// Same colours used by PS4
|
||||
{0x00, 0x00, 0x40}, // blue
|
||||
{0x40, 0x00, 0x00}, // red
|
||||
{0x00, 0x40, 0x00}, // green
|
||||
{0x20, 0x00, 0x20}, // pink
|
||||
// New colours for controllers 5-8
|
||||
{0x00, 0x20, 0x20}, // cyan
|
||||
{0x30, 0x10, 0x00}, // orange
|
||||
{0x20, 0x20, 0x00}, // yellow
|
||||
{0x10, 0x00, 0x30} // purple
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Result DualsenseController::Initialize(void) {
|
||||
R_TRY(EmulatedSwitchController::Initialize());
|
||||
R_TRY(this->PushRumbleLedState());
|
||||
|
||||
return ams::ResultSuccess();
|
||||
}
|
||||
|
||||
Result DualsenseController::SetPlayerLed(uint8_t led_mask) {
|
||||
uint8_t player_number;
|
||||
R_TRY(LedsMaskToPlayerNumber(led_mask, &player_number));
|
||||
m_led_flags = player_led_flags[player_number];
|
||||
RGBColour colour = player_led_colours[player_number];
|
||||
return this->SetLightbarColour(colour);
|
||||
}
|
||||
|
||||
Result DualsenseController::SetLightbarColour(RGBColour colour) {
|
||||
m_led_colour = colour;
|
||||
return this->PushRumbleLedState();
|
||||
}
|
||||
|
||||
void DualsenseController::UpdateControllerState(const bluetooth::HidReport *report) {
|
||||
|
@ -31,12 +76,15 @@ namespace ams::controller {
|
|||
case 0x01:
|
||||
this->HandleInputReport0x01(dualsense_report);
|
||||
break;
|
||||
case 0x31:
|
||||
this->HandleInputReport0x31(dualsense_report);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DualsenseController::HandleInputReport0x01(const DualsenseReportData *src) {
|
||||
void DualsenseController::HandleInputReport0x01(const DualsenseReportData *src) {
|
||||
m_left_stick = this->PackStickData(
|
||||
static_cast<uint16_t>(stick_scale_factor * src->input0x01.left_stick.x) & 0xfff,
|
||||
static_cast<uint16_t>(stick_scale_factor * (UINT8_MAX - src->input0x01.left_stick.y)) & 0xfff
|
||||
|
@ -49,6 +97,32 @@ namespace ams::controller {
|
|||
this->MapButtons(&src->input0x01.buttons);
|
||||
}
|
||||
|
||||
void DualsenseController::HandleInputReport0x31(const DualsenseReportData *src) {
|
||||
if (!src->input0x31.usb || src->input0x31.full)
|
||||
m_charging = false;
|
||||
else
|
||||
m_charging = true;
|
||||
|
||||
uint8_t battery_level = src->input0x31.battery_level;
|
||||
if (!src->input0x31.usb)
|
||||
battery_level++;
|
||||
if (battery_level > 10)
|
||||
battery_level = 10;
|
||||
|
||||
m_battery = static_cast<uint8_t>(8 * (battery_level + 1) / 10) & 0x0e;
|
||||
|
||||
m_left_stick = this->PackStickData(
|
||||
static_cast<uint16_t>(stick_scale_factor * src->input0x31.left_stick.x) & 0xfff,
|
||||
static_cast<uint16_t>(stick_scale_factor * (UINT8_MAX - src->input0x31.left_stick.y)) & 0xfff
|
||||
);
|
||||
m_right_stick = this->PackStickData(
|
||||
static_cast<uint16_t>(stick_scale_factor * src->input0x31.right_stick.x) & 0xfff,
|
||||
static_cast<uint16_t>(stick_scale_factor * (UINT8_MAX - src->input0x31.right_stick.y)) & 0xfff
|
||||
);
|
||||
|
||||
this->MapButtons(&src->input0x31.buttons);
|
||||
}
|
||||
|
||||
void DualsenseController::MapButtons(const DualsenseButtonData *buttons) {
|
||||
m_buttons.dpad_down = (buttons->dpad == DualsenseDPad_S) ||
|
||||
(buttons->dpad == DualsenseDPad_SE) ||
|
||||
|
@ -83,4 +157,20 @@ namespace ams::controller {
|
|||
m_buttons.home = buttons->ps;
|
||||
}
|
||||
|
||||
Result DualsenseController::PushRumbleLedState(void) {
|
||||
DualsenseOutputReport0x31 report = {0xa2, 0x31, 0x02, 0x00, 0x14};
|
||||
report.data[41] = 0x02;
|
||||
report.data[44] = 0x02;
|
||||
report.data[46] = m_led_flags;
|
||||
report.data[47] = m_led_colour.r;
|
||||
report.data[48] = m_led_colour.g;
|
||||
report.data[49] = m_led_colour.b;
|
||||
report.crc = crc32Calculate(report.data, sizeof(report.data));
|
||||
|
||||
s_output_report.size = sizeof(report) - 1;
|
||||
std::memcpy(s_output_report.data, &report.data[1], s_output_report.size);
|
||||
|
||||
return bluetooth::hid::report::SendHidReport(&m_address, &s_output_report);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,18 +56,49 @@ namespace ams::controller {
|
|||
uint8_t counter : 6;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct DualsenseOutputReport0x31 {
|
||||
struct {
|
||||
uint8_t data[75];
|
||||
};
|
||||
uint32_t crc;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct DualsenseInputReport0x01 {
|
||||
DualsenseStickData left_stick;
|
||||
DualsenseStickData right_stick;
|
||||
DualsenseButtonData buttons;
|
||||
DualsenseStickData left_stick;
|
||||
DualsenseStickData right_stick;
|
||||
DualsenseButtonData buttons;
|
||||
uint8_t left_trigger;
|
||||
uint8_t right_trigger;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct DualsenseInputReport0x31 {
|
||||
uint8_t _unk0;
|
||||
DualsenseStickData left_stick;
|
||||
DualsenseStickData right_stick;
|
||||
uint8_t left_trigger;
|
||||
uint8_t right_trigger;
|
||||
uint8_t counter;
|
||||
DualsenseButtonData buttons;
|
||||
uint8_t _unk1[5];
|
||||
uint16_t vel_x;
|
||||
uint16_t vel_y;
|
||||
uint16_t vel_z;
|
||||
uint16_t acc_x;
|
||||
uint16_t acc_y;
|
||||
uint16_t acc_z;
|
||||
uint8_t _unk2[25];
|
||||
|
||||
uint8_t battery_level : 4;
|
||||
uint8_t usb : 1;
|
||||
uint8_t full : 1;
|
||||
uint8_t : 0;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct DualsenseReportData {
|
||||
uint8_t id;
|
||||
union {
|
||||
DualsenseInputReport0x01 input0x01;
|
||||
DualsenseInputReport0x31 input0x31;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -79,15 +110,23 @@ namespace ams::controller {
|
|||
};
|
||||
|
||||
DualsenseController(const bluetooth::Address *address)
|
||||
: EmulatedSwitchController(address) { };
|
||||
: EmulatedSwitchController(address), m_led_flags(0), m_led_colour({0, 0, 0}) { };
|
||||
|
||||
//Result Initialize(void);
|
||||
Result Initialize(void);
|
||||
Result SetPlayerLed(uint8_t led_mask);
|
||||
Result SetLightbarColour(RGBColour colour);
|
||||
|
||||
void UpdateControllerState(const bluetooth::HidReport *report);
|
||||
|
||||
private:
|
||||
void HandleInputReport0x01(const DualsenseReportData *src);
|
||||
void HandleInputReport0x31(const DualsenseReportData *src);
|
||||
|
||||
void MapButtons(const DualsenseButtonData *buttons);
|
||||
|
||||
Result PushRumbleLedState(void);
|
||||
|
||||
uint8_t m_led_flags;
|
||||
RGBColour m_led_colour;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue