mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-30 07:20:13 +00:00
Dualsense/DS4: Replace buffers with human readable structs
Also don't turn off the lights when the game closes.
This commit is contained in:
parent
2647a09790
commit
645621b243
@ -6,39 +6,6 @@
|
||||
|
||||
LOG_CHANNEL(ds3_log, "DS3");
|
||||
|
||||
struct ds3_rumble
|
||||
{
|
||||
u8 padding = 0x00;
|
||||
u8 small_motor_duration = 0xFF; // 0xff means forever
|
||||
u8 small_motor_on = 0x00; // 0 or 1 (off/on)
|
||||
u8 large_motor_duration = 0xFF; // 0xff means forever
|
||||
u8 large_motor_force = 0x00; // 0 to 255
|
||||
};
|
||||
|
||||
struct ds3_led
|
||||
{
|
||||
u8 duration = 0xFF; // total duration, 0xff means forever
|
||||
u8 interval_duration = 0xFF; // interval duration in deciseconds
|
||||
u8 enabled = 0x10;
|
||||
u8 interval_portion_off = 0x00; // in percent (100% = 0xFF)
|
||||
u8 interval_portion_on = 0xFF; // in percent (100% = 0xFF)
|
||||
};
|
||||
|
||||
struct ds3_output_report
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u8 report_id = 0x00;
|
||||
u8 idk_what_this_is[3] = {0x02, 0x00, 0x00};
|
||||
#else
|
||||
u8 report_id = 0x01;
|
||||
#endif
|
||||
ds3_rumble rumble;
|
||||
u8 padding[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
u8 led_enabled = 0x00; // LED 1 = 0x02, LED 2 = 0x04, etc.
|
||||
ds3_led led[4];
|
||||
ds3_led led_5; // reserved for another LED
|
||||
};
|
||||
|
||||
constexpr std::array<u8, 6> battery_capacity = {0, 1, 25, 50, 75, 100};
|
||||
|
||||
constexpr id_pair SONY_DS3_ID_0 = {0x054C, 0x0268};
|
||||
@ -144,7 +111,7 @@ int ds3_pad_handler::send_output_report(ds3_device* ds3dev)
|
||||
if (!ds3dev || !ds3dev->hidDevice || !ds3dev->config)
|
||||
return -2;
|
||||
|
||||
ds3_output_report output_report;
|
||||
ds3_output_report output_report{};
|
||||
output_report.rumble.small_motor_on = ds3dev->small_motor;
|
||||
output_report.rumble.large_motor_force = ds3dev->large_motor;
|
||||
|
||||
@ -186,7 +153,7 @@ int ds3_pad_handler::send_output_report(ds3_device* ds3dev)
|
||||
output_report.led[3].interval_portion_off = ds3dev->led_delay_off;
|
||||
}
|
||||
|
||||
return hid_write(ds3dev->hidDevice, &output_report.report_id, sizeof(output_report));
|
||||
return hid_write(ds3dev->hidDevice, &output_report.report_id, sizeof(ds3_output_report));
|
||||
}
|
||||
|
||||
void ds3_pad_handler::init_config(cfg_pad* cfg)
|
||||
@ -328,15 +295,15 @@ ds3_pad_handler::DataStatus ds3_pad_handler::get_data(ds3_device* ds3dev)
|
||||
return DataStatus::ReadError;
|
||||
|
||||
#ifdef _WIN32
|
||||
ds3dev->padData[0] = ds3dev->report_id;
|
||||
const int result = hid_get_feature_report(ds3dev->hidDevice, ds3dev->padData.data(), ds3dev->padData.size());
|
||||
ds3dev->report.data[0] = ds3dev->report_id;
|
||||
const int result = hid_get_feature_report(ds3dev->hidDevice, ds3dev->report.data.data(), ds3dev->report.data.size());
|
||||
if (result < 0)
|
||||
{
|
||||
ds3_log.error("get_data: hid_get_feature_report 0x%02x failed! result=%d, buf[0]=0x%x, error=%s", ds3dev->report_id, result, ds3dev->padData[0], hid_error(ds3dev->hidDevice));
|
||||
ds3_log.error("get_data: hid_get_feature_report 0x%02x failed! result=%d, buf[0]=0x%x, error=%s", ds3dev->report_id, result, ds3dev->report.data[0], hid_error(ds3dev->hidDevice));
|
||||
return DataStatus::ReadError;
|
||||
}
|
||||
#else
|
||||
const int result = hid_read(ds3dev->hidDevice, ds3dev->padData.data(), ds3dev->padData.size());
|
||||
const int result = hid_read(ds3dev->hidDevice, ds3dev->report.data.data(), ds3dev->report.data.size());
|
||||
if (result < 0)
|
||||
{
|
||||
ds3_log.error("get_data: hid_read failed! result=%d, error=%s", result, hid_error(ds3dev->hidDevice));
|
||||
@ -347,12 +314,12 @@ ds3_pad_handler::DataStatus ds3_pad_handler::get_data(ds3_device* ds3dev)
|
||||
if (result > 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (ds3dev->padData[0] == ds3dev->report_id)
|
||||
if (ds3dev->report.data[0] == ds3dev->report_id)
|
||||
#else
|
||||
if (ds3dev->padData[0] == 0x01 && ds3dev->padData[1] != 0xFF)
|
||||
if (ds3dev->report.data[0] == 0x01 && ds3dev->report.data[1] != 0xFF)
|
||||
#endif
|
||||
{
|
||||
const u8 battery_status = ds3dev->padData[30 + DS3_HID_OFFSET];
|
||||
const u8 battery_status = ds3dev->report.data[30 + DS3_HID_OFFSET];
|
||||
|
||||
if (battery_status >= 0xEE)
|
||||
{
|
||||
@ -369,7 +336,7 @@ ds3_pad_handler::DataStatus ds3_pad_handler::get_data(ds3_device* ds3dev)
|
||||
return DataStatus::NewData;
|
||||
}
|
||||
|
||||
ds3_log.warning("get_data: Unknown packet received: 0x%02x", ds3dev->padData[0]);
|
||||
ds3_log.warning("get_data: Unknown packet received: 0x%02x", ds3dev->report.data[0]);
|
||||
}
|
||||
|
||||
return DataStatus::NoNewData;
|
||||
@ -382,7 +349,7 @@ std::unordered_map<u64, u16> ds3_pad_handler::get_button_values(const std::share
|
||||
if (!dev)
|
||||
return key_buf;
|
||||
|
||||
auto& dbuf = dev->padData;
|
||||
auto& dbuf = dev->report.data;
|
||||
|
||||
const u8 lsx = dbuf[6 + DS3_HID_OFFSET];
|
||||
const u8 lsy = dbuf[7 + DS3_HID_OFFSET];
|
||||
@ -457,14 +424,14 @@ void ds3_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
|
||||
#ifdef _WIN32
|
||||
// Official Sony Windows DS3 driver seems to do the same modification of this value as the ps3
|
||||
pad->m_sensors[0].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 41 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[0].m_value = read_from_ptr<le_t<u16>>(ds3dev->report.data, 41 + DS3_HID_OFFSET);
|
||||
#else
|
||||
// When getting raw values from the device this adjustement is needed
|
||||
pad->m_sensors[0].m_value = 512 - (read_from_ptr<le_t<u16>>(ds3dev->padData, 41 + DS3_HID_OFFSET) - 512);
|
||||
pad->m_sensors[0].m_value = 512 - (read_from_ptr<le_t<u16>>(ds3dev->report.data, 41 + DS3_HID_OFFSET) - 512);
|
||||
#endif
|
||||
pad->m_sensors[1].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 45 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[2].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 43 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[3].m_value = read_from_ptr<le_t<u16>>(ds3dev->padData, 47 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[1].m_value = read_from_ptr<le_t<u16>>(ds3dev->report.data, 45 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[2].m_value = read_from_ptr<le_t<u16>>(ds3dev->report.data, 43 + DS3_HID_OFFSET);
|
||||
pad->m_sensors[3].m_value = read_from_ptr<le_t<u16>>(ds3dev->report.data, 47 + DS3_HID_OFFSET);
|
||||
|
||||
// Those are formulas used to adjust sensor values in sys_hid code but I couldn't find all the vars.
|
||||
//auto polish_value = [](s32 value, s32 dword_0x0, s32 dword_0x4, s32 dword_0x8, s32 dword_0xC, s32 dword_0x18, s32 dword_0x1C) -> u16
|
||||
|
@ -4,12 +4,54 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct ds3_rumble
|
||||
{
|
||||
u8 padding = 0x00;
|
||||
u8 small_motor_duration = 0xFF; // 0xff means forever
|
||||
u8 small_motor_on = 0x00; // 0 or 1 (off/on)
|
||||
u8 large_motor_duration = 0xFF; // 0xff means forever
|
||||
u8 large_motor_force = 0x00; // 0 to 255
|
||||
};
|
||||
|
||||
struct ds3_led
|
||||
{
|
||||
u8 duration = 0xFF; // total duration, 0xff means forever
|
||||
u8 interval_duration = 0xFF; // interval duration in deciseconds
|
||||
u8 enabled = 0x10;
|
||||
u8 interval_portion_off = 0x00; // in percent (100% = 0xFF)
|
||||
u8 interval_portion_on = 0xFF; // in percent (100% = 0xFF)
|
||||
};
|
||||
|
||||
struct ds3_output_report
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u8 report_id = 0x00;
|
||||
u8 idk_what_this_is[3] = {0x02, 0x00, 0x00};
|
||||
#else
|
||||
u8 report_id = 0x01;
|
||||
#endif
|
||||
ds3_rumble rumble;
|
||||
u8 padding[4] = {0x00, 0x00, 0x00, 0x00};
|
||||
u8 led_enabled = 0x00; // LED 1 = 0x02, LED 2 = 0x04, etc.
|
||||
ds3_led led[4];
|
||||
ds3_led led_5; // reserved for another LED
|
||||
};
|
||||
|
||||
struct ds3_input_report
|
||||
{
|
||||
std::array<u8, 64> data;
|
||||
};
|
||||
}
|
||||
|
||||
class ds3_device : public HidDevice
|
||||
{
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
u8 report_id = 0;
|
||||
#endif
|
||||
ds3_input_report report{};
|
||||
};
|
||||
|
||||
class ds3_pad_handler final : public hid_pad_handler<ds3_device>
|
||||
|
@ -12,19 +12,6 @@ constexpr id_pair ZEROPLUS_ID_0 = {0x0C12, 0x0E20};
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr u32 DS4_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DS4_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
constexpr u32 DS4_FEATURE_REPORT_0x02_SIZE = 37;
|
||||
constexpr u32 DS4_FEATURE_REPORT_0x05_SIZE = 41;
|
||||
//constexpr u32 DS4_FEATURE_REPORT_0x12_SIZE = 16;
|
||||
//constexpr u32 DS4_FEATURE_REPORT_0x81_SIZE = 7;
|
||||
constexpr u32 DS4_FEATURE_REPORT_0xA3_SIZE = 49;
|
||||
constexpr u32 DS4_INPUT_REPORT_0x11_SIZE = 78;
|
||||
constexpr u32 DS4_OUTPUT_REPORT_0x05_SIZE = 32;
|
||||
constexpr u32 DS4_OUTPUT_REPORT_0x11_SIZE = 78;
|
||||
constexpr u32 DS4_INPUT_REPORT_GYRO_X_OFFSET = 13;
|
||||
constexpr u32 DS4_INPUT_REPORT_BATTERY_OFFSET = 30;
|
||||
|
||||
// This tries to convert axis to give us the max even in the corners,
|
||||
// this actually might work 'too' well, we end up actually getting diagonals of actual max/min, we need the corners still a bit rounded to match ds3
|
||||
// im leaving it here for now, and future reference as it probably can be used later
|
||||
@ -237,26 +224,26 @@ std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::share
|
||||
if (!ds4_dev)
|
||||
return keyBuffer;
|
||||
|
||||
auto buf = ds4_dev->padData;
|
||||
const ds4_input_report_common& input = ds4_dev->bt_controller ? ds4_dev->report_bt.common : ds4_dev->report_usb.common;
|
||||
|
||||
// Left Stick X Axis
|
||||
keyBuffer[DS4KeyCodes::LSXNeg] = Clamp0To255((127.5f - buf[1]) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSXPos] = Clamp0To255((buf[1] - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSXPos] = Clamp0To255((input.x - 127.5f) * 2.0f);
|
||||
|
||||
// Left Stick Y Axis (Up is the negative for some reason)
|
||||
keyBuffer[DS4KeyCodes::LSYNeg] = Clamp0To255((buf[2] - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSYPos] = Clamp0To255((127.5f - buf[2]) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSYNeg] = Clamp0To255((input.y - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::LSYPos] = Clamp0To255((127.5f - input.y) * 2.0f);
|
||||
|
||||
// Right Stick X Axis
|
||||
keyBuffer[DS4KeyCodes::RSXNeg] = Clamp0To255((127.5f - buf[3]) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSXPos] = Clamp0To255((buf[3] - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSXNeg] = Clamp0To255((127.5f - input.rx) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSXPos] = Clamp0To255((input.rx - 127.5f) * 2.0f);
|
||||
|
||||
// Right Stick Y Axis (Up is the negative for some reason)
|
||||
keyBuffer[DS4KeyCodes::RSYNeg] = Clamp0To255((buf[4] - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSYPos] = Clamp0To255((127.5f - buf[4]) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSYNeg] = Clamp0To255((input.ry - 127.5f) * 2.0f);
|
||||
keyBuffer[DS4KeyCodes::RSYPos] = Clamp0To255((127.5f - input.ry) * 2.0f);
|
||||
|
||||
// bleh, dpad in buffer is stored in a different state
|
||||
const u8 dpadState = buf[5] & 0xf;
|
||||
const u8 dpadState = input.buttons[0] & 0xf;
|
||||
switch (dpadState)
|
||||
{
|
||||
case 0x08: // none pressed
|
||||
@ -318,28 +305,28 @@ std::unordered_map<u64, u16> ds4_pad_handler::get_button_values(const std::share
|
||||
}
|
||||
|
||||
// square, cross, circle, triangle
|
||||
keyBuffer[DS4KeyCodes::Square] = ((buf[5] & (1 << 4)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Cross] = ((buf[5] & (1 << 5)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Circle] = ((buf[5] & (1 << 6)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Triangle] = ((buf[5] & (1 << 7)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Square] = ((input.buttons[0] & (1 << 4)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Cross] = ((input.buttons[0] & (1 << 5)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Circle] = ((input.buttons[0] & (1 << 6)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Triangle] = ((input.buttons[0] & (1 << 7)) != 0) ? 255 : 0;
|
||||
|
||||
// L1, R1, L2, L3, select, start, L3, L3
|
||||
keyBuffer[DS4KeyCodes::L1] = ((buf[6] & (1 << 0)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::R1] = ((buf[6] & (1 << 1)) != 0) ? 255 : 0;
|
||||
//keyBuffer[DS4KeyCodes::L2But] = ((buf[6] & (1 << 2)) != 0) ? 255 : 0;
|
||||
//keyBuffer[DS4KeyCodes::R2But] = ((buf[6] & (1 << 3)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Share] = ((buf[6] & (1 << 4)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Options] = ((buf[6] & (1 << 5)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::L3] = ((buf[6] & (1 << 6)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::R3] = ((buf[6] & (1 << 7)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::L1] = ((input.buttons[1] & (1 << 0)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::R1] = ((input.buttons[1] & (1 << 1)) != 0) ? 255 : 0;
|
||||
//keyBuffer[DS4KeyCodes::L2But] = ((input.buttons[1] & (1 << 2)) != 0) ? 255 : 0;
|
||||
//keyBuffer[DS4KeyCodes::R2But] = ((input.buttons[1] & (1 << 3)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Share] = ((input.buttons[1] & (1 << 4)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::Options] = ((input.buttons[1] & (1 << 5)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::L3] = ((input.buttons[1] & (1 << 6)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::R3] = ((input.buttons[1] & (1 << 7)) != 0) ? 255 : 0;
|
||||
|
||||
// PS Button, Touch Button
|
||||
keyBuffer[DS4KeyCodes::PSButton] = ((buf[7] & (1 << 0)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::TouchPad] = ((buf[7] & (1 << 1)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::PSButton] = ((input.buttons[2] & (1 << 0)) != 0) ? 255 : 0;
|
||||
keyBuffer[DS4KeyCodes::TouchPad] = ((input.buttons[2] & (1 << 1)) != 0) ? 255 : 0;
|
||||
|
||||
// L2, R2
|
||||
keyBuffer[DS4KeyCodes::L2] = buf[8];
|
||||
keyBuffer[DS4KeyCodes::R2] = buf[9];
|
||||
keyBuffer[DS4KeyCodes::L2] = input.z;
|
||||
keyBuffer[DS4KeyCodes::R2] = input.rz;
|
||||
|
||||
return keyBuffer;
|
||||
}
|
||||
@ -371,9 +358,9 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const
|
||||
for (int tries = 0; tries < 3; ++tries)
|
||||
{
|
||||
buf = {};
|
||||
buf[0] = 0x05;
|
||||
buf[0] = 0x05; // Calibration feature report id
|
||||
|
||||
if (int res = hid_get_feature_report(ds4Dev->hidDevice, buf.data(), DS4_FEATURE_REPORT_0x05_SIZE); res != DS4_FEATURE_REPORT_0x05_SIZE || buf[0] != 0x05)
|
||||
if (int res = hid_get_feature_report(ds4Dev->hidDevice, buf.data(), DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE); res != DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE || buf[0] != 0x05)
|
||||
{
|
||||
ds4_log.error("GetCalibrationData: hid_get_feature_report 0x05 for bluetooth controller failed! result=%d, error=%s", res, hid_error(ds4Dev->hidDevice));
|
||||
return false;
|
||||
@ -381,8 +368,8 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const
|
||||
|
||||
const u8 btHdr = 0xA3;
|
||||
const u32 crcHdr = CRCPP::CRC::Calculate(&btHdr, 1, crcTable);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), (DS4_FEATURE_REPORT_0x05_SIZE - 4), crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[DS4_FEATURE_REPORT_0x05_SIZE - 4]);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE - 4, crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE - 4]);
|
||||
|
||||
if (crcCalc == crcReported)
|
||||
break;
|
||||
@ -399,7 +386,7 @@ bool ds4_pad_handler::GetCalibrationData(DS4Device* ds4Dev) const
|
||||
else
|
||||
{
|
||||
buf[0] = 0x02;
|
||||
if (int res = hid_get_feature_report(ds4Dev->hidDevice, buf.data(), DS4_FEATURE_REPORT_0x02_SIZE); res != DS4_FEATURE_REPORT_0x02_SIZE || buf[0] != 0x02)
|
||||
if (int res = hid_get_feature_report(ds4Dev->hidDevice, buf.data(), DS4_FEATURE_REPORT_USB_CALIBRATION_SIZE); res != DS4_FEATURE_REPORT_USB_CALIBRATION_SIZE || buf[0] != 0x02)
|
||||
{
|
||||
ds4_log.error("GetCalibrationData: hid_get_feature_report 0x02 for wired controller failed! result=%d, error=%s", res, hid_error(ds4Dev->hidDevice));
|
||||
return false;
|
||||
@ -544,8 +531,8 @@ void ds4_pad_handler::check_add_device(hid_device* hidDevice, std::string_view p
|
||||
std::array<u8, 64> buf{};
|
||||
buf[0] = 0xA3;
|
||||
|
||||
int res = hid_get_feature_report(hidDevice, buf.data(), DS4_FEATURE_REPORT_0xA3_SIZE);
|
||||
if (res != DS4_FEATURE_REPORT_0xA3_SIZE || buf[0] != 0xA3)
|
||||
int res = hid_get_feature_report(hidDevice, buf.data(), DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE);
|
||||
if (res != DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE || buf[0] != 0xA3)
|
||||
{
|
||||
ds4_log.error("check_add_device: hid_get_feature_report 0xA3 failed! Could not retrieve firmware version! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(hidDevice));
|
||||
}
|
||||
@ -600,50 +587,44 @@ int ds4_pad_handler::send_output_report(DS4Device* device)
|
||||
if (config == nullptr)
|
||||
return -2; // hid_write and hid_write_control return -1 on error
|
||||
|
||||
std::array<u8, 78> outputBuf{0};
|
||||
// write rumble state
|
||||
ds4_output_report_common common{};
|
||||
common.valid_flag0 = 0x07;
|
||||
common.motor_right = device->small_motor;
|
||||
common.motor_left = device->large_motor;
|
||||
|
||||
// write LED color
|
||||
common.lightbar_red = config->colorR;
|
||||
common.lightbar_green = config->colorG;
|
||||
common.lightbar_blue = config->colorB;
|
||||
|
||||
// alternating blink states with values 0-255: only setting both to zero disables blinking
|
||||
// 255 is roughly 2 seconds, so setting both values to 255 results in a 4 second interval
|
||||
// using something like (0,10) will heavily blink, while using (0, 255) will be slow. you catch the drift
|
||||
common.lightbar_blink_on = device->led_delay_on;
|
||||
common.lightbar_blink_off = device->led_delay_off;
|
||||
|
||||
if (device->bt_controller)
|
||||
{
|
||||
outputBuf[0] = 0x11;
|
||||
outputBuf[1] = 0xC4;
|
||||
outputBuf[3] = 0x07;
|
||||
outputBuf[6] = device->small_motor;
|
||||
outputBuf[7] = device->large_motor;
|
||||
outputBuf[8] = config->colorR; // red
|
||||
outputBuf[9] = config->colorG; // green
|
||||
outputBuf[10] = config->colorB; // blue
|
||||
|
||||
// alternating blink states with values 0-255: only setting both to zero disables blinking
|
||||
// 255 is roughly 2 seconds, so setting both values to 255 results in a 4 second interval
|
||||
// using something like (0,10) will heavily blink, while using (0, 255) will be slow. you catch the drift
|
||||
outputBuf[11] = device->led_delay_on;
|
||||
outputBuf[12] = device->led_delay_off;
|
||||
ds4_output_report_bt output{};
|
||||
output.report_id = 0x11;
|
||||
output.hw_control = 0xC4;
|
||||
output.common = std::move(common);
|
||||
|
||||
const u8 btHdr = 0xA2;
|
||||
const u32 crcHdr = CRCPP::CRC::Calculate(&btHdr, 1, crcTable);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(outputBuf.data(), (DS4_OUTPUT_REPORT_0x11_SIZE - 4), crcTable, crcHdr);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(&output.report_id, offsetof(ds4_output_report_bt, crc32), crcTable, crcHdr);
|
||||
|
||||
outputBuf[74] = (crcCalc >> 0) & 0xFF;
|
||||
outputBuf[75] = (crcCalc >> 8) & 0xFF;
|
||||
outputBuf[76] = (crcCalc >> 16) & 0xFF;
|
||||
outputBuf[77] = (crcCalc >> 24) & 0xFF;
|
||||
write_to_ptr(output.crc32, crcCalc);
|
||||
|
||||
return hid_write_control(device->hidDevice, outputBuf.data(), DS4_OUTPUT_REPORT_0x11_SIZE);
|
||||
return hid_write_control(device->hidDevice, &output.report_id, sizeof(ds4_output_report_bt));
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuf[0] = 0x05;
|
||||
outputBuf[1] = 0x07;
|
||||
outputBuf[4] = device->small_motor;
|
||||
outputBuf[5] = device->large_motor;
|
||||
outputBuf[6] = config->colorR; // red
|
||||
outputBuf[7] = config->colorG; // green
|
||||
outputBuf[8] = config->colorB; // blue
|
||||
outputBuf[9] = device->led_delay_on;
|
||||
outputBuf[10] = device->led_delay_off;
|
||||
|
||||
return hid_write(device->hidDevice, outputBuf.data(), DS4_OUTPUT_REPORT_0x05_SIZE);
|
||||
}
|
||||
ds4_output_report_usb output{};
|
||||
output.report_id = 0x05;
|
||||
output.common = std::move(common);
|
||||
|
||||
return hid_write(device->hidDevice, &output.report_id, sizeof(ds4_output_report_usb));
|
||||
}
|
||||
|
||||
ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device)
|
||||
@ -651,9 +632,9 @@ ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device)
|
||||
if (!device || !device->hidDevice)
|
||||
return DataStatus::ReadError;
|
||||
|
||||
std::array<u8, 78> buf{};
|
||||
std::array<u8, std::max(sizeof(ds4_input_report_bt), sizeof(ds4_input_report_usb))> buf{};
|
||||
|
||||
const int res = hid_read(device->hidDevice, buf.data(), device->bt_controller ? DS4_INPUT_REPORT_0x11_SIZE : 64);
|
||||
const int res = hid_read(device->hidDevice, buf.data(), device->bt_controller ? sizeof(ds4_input_report_bt) : sizeof(ds4_input_report_usb));
|
||||
if (res == -1)
|
||||
{
|
||||
// looks like controller disconnected or read error
|
||||
@ -677,41 +658,42 @@ ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device)
|
||||
return DataStatus::NoNewData;
|
||||
}
|
||||
|
||||
int offset;
|
||||
int offset = 0;
|
||||
|
||||
// check report and set offset
|
||||
if (device->bt_controller && buf[0] == 0x11 && res == DS4_INPUT_REPORT_0x11_SIZE)
|
||||
if (device->bt_controller && buf[0] == 0x11 && res == sizeof(ds4_input_report_bt))
|
||||
{
|
||||
offset = 2;
|
||||
offset = offsetof(ds4_input_report_bt, common);
|
||||
|
||||
const u8 btHdr = 0xA1;
|
||||
const u32 crcHdr = CRCPP::CRC::Calculate(&btHdr, 1, crcTable);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), (DS4_INPUT_REPORT_0x11_SIZE - 4), crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[DS4_INPUT_REPORT_0x11_SIZE - 4]);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), offsetof(ds4_input_report_bt, crc32), crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[offsetof(ds4_input_report_bt, crc32)]);
|
||||
if (crcCalc != crcReported)
|
||||
{
|
||||
ds4_log.warning("Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x", crcReported, crcCalc);
|
||||
return DataStatus::NoNewData;
|
||||
}
|
||||
}
|
||||
else if (!device->bt_controller && buf[0] == 0x01 && res == 64)
|
||||
else if (!device->bt_controller && buf[0] == 0x01 && res == sizeof(ds4_input_report_usb))
|
||||
{
|
||||
// Ds4 Dongle uses this bit to actually report whether a controller is connected
|
||||
const bool connected = (buf[31] & 0x04) ? false : true;
|
||||
const bool connected = !(buf[31] & 0x04);
|
||||
if (connected && !device->has_calib_data)
|
||||
device->has_calib_data = GetCalibrationData(device);
|
||||
|
||||
offset = 0;
|
||||
offset = offsetof(ds4_input_report_usb, common);
|
||||
}
|
||||
else
|
||||
return DataStatus::NoNewData;
|
||||
|
||||
const int battery_offset = offset + DS4_INPUT_REPORT_BATTERY_OFFSET;
|
||||
const int battery_offset = offset + offsetof(ds4_input_report_common, status);
|
||||
device->cable_state = (buf[battery_offset] >> 4) & 0x01;
|
||||
device->battery_level = buf[battery_offset] & 0x0F; // 0 - 9 while unplugged, 0 - 10 while plugged in, 11 charge complete
|
||||
|
||||
if (device->has_calib_data)
|
||||
{
|
||||
int calibOffset = offset + DS4_INPUT_REPORT_GYRO_X_OFFSET;
|
||||
int calibOffset = offset + offsetof(ds4_input_report_common, gyro);
|
||||
for (int i = 0; i < CalibIndex::COUNT; ++i)
|
||||
{
|
||||
const s16 rawValue = read_s16(&buf[calibOffset]);
|
||||
@ -720,7 +702,15 @@ ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device)
|
||||
buf[calibOffset++] = (static_cast<u16>(calValue) >> 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
memcpy(device->padData.data(), &buf[offset], 64);
|
||||
|
||||
if (device->bt_controller)
|
||||
{
|
||||
std::memcpy(&device->report_bt, buf.data(), sizeof(ds4_input_report_bt));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(&device->report_usb, buf.data(), sizeof(ds4_input_report_usb));
|
||||
}
|
||||
|
||||
return DataStatus::NewData;
|
||||
}
|
||||
@ -811,7 +801,7 @@ void ds4_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
if (!ds4_device || !pad)
|
||||
return;
|
||||
|
||||
auto buf = ds4_device->padData;
|
||||
const ds4_input_report_common& input = ds4_device->bt_controller ? ds4_device->report_bt.common : ds4_device->report_usb.common;
|
||||
|
||||
pad->m_battery_level = ds4_device->battery_level;
|
||||
pad->m_cable_state = ds4_device->cable_state;
|
||||
@ -819,9 +809,9 @@ void ds4_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
// these values come already calibrated, all we need to do is convert to ds3 range
|
||||
|
||||
// accel
|
||||
f32 accelX = static_cast<s16>((buf[20] << 8) | buf[19]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
f32 accelY = static_cast<s16>((buf[22] << 8) | buf[21]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
f32 accelZ = static_cast<s16>((buf[24] << 8) | buf[23]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
f32 accelX = static_cast<s16>(input.accel[0]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
f32 accelY = static_cast<s16>(input.accel[1]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
f32 accelZ = static_cast<s16>(input.accel[2]) / static_cast<f32>(DS4_ACC_RES_PER_G) * -1;
|
||||
|
||||
// now just use formula from ds3
|
||||
accelX = accelX * 113 + 512;
|
||||
@ -833,9 +823,9 @@ void ds4_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
pad->m_sensors[2].m_value = Clamp0To1023(accelZ);
|
||||
|
||||
// gyroY is yaw, which is all that we need
|
||||
//f32 gyroX = static_cast<s16>((u16)(buf[14] << 8) | buf[13]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
f32 gyroY = static_cast<s16>((buf[16] << 8) | buf[15]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
//f32 gyroZ = static_cast<s16>((u16)(buf[18] << 8) | buf[17]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
//f32 gyroX = static_cast<s16>(input.gyro[0]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
f32 gyroY = static_cast<s16>(input.gyro[1]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
//f32 gyroZ = static_cast<s16>(input.gyro[2]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
|
||||
|
||||
// Convert to ds3. The ds3 resolution is 123/90°/sec.
|
||||
gyroY = gyroY * (123.f / 90.f) + 512;
|
||||
|
@ -4,12 +4,123 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr u32 DS4_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DS4_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
constexpr u32 DS4_FEATURE_REPORT_USB_CALIBRATION_SIZE = 37;
|
||||
constexpr u32 DS4_FEATURE_REPORT_BLUETOOTH_CALIBRATION_SIZE = 41;
|
||||
//constexpr u32 DS4_FEATURE_REPORT_PAIRING_INFO_SIZE = 16;
|
||||
//constexpr u32 DS4_FEATURE_REPORT_0x81_SIZE = 7;
|
||||
constexpr u32 DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE = 49;
|
||||
constexpr u32 DS4_INPUT_REPORT_USB_SIZE = 64;
|
||||
constexpr u32 DS4_INPUT_REPORT_BLUETOOTH_SIZE = 78;
|
||||
constexpr u32 DS4_OUTPUT_REPORT_USB_SIZE = 32;
|
||||
constexpr u32 DS4_OUTPUT_REPORT_BLUETOOTH_SIZE = 78;
|
||||
constexpr u32 DS4_TOUCHPAD_WIDTH = 1920;
|
||||
constexpr u32 DS4_TOUCHPAD_HEIGHT = 942;
|
||||
|
||||
struct ds4_touch_point
|
||||
{
|
||||
u8 contact;
|
||||
u8 x_lo;
|
||||
u8 x_hi : 4;
|
||||
u8 y_lo : 4;
|
||||
u8 y_hi;
|
||||
};
|
||||
static_assert(sizeof(ds4_touch_point) == 4);
|
||||
|
||||
struct ds4_touch_report
|
||||
{
|
||||
u8 timestamp;
|
||||
ds4_touch_point points[2];
|
||||
};
|
||||
static_assert(sizeof(ds4_touch_report) == 9);
|
||||
|
||||
struct ds4_input_report_common
|
||||
{
|
||||
u8 x;
|
||||
u8 y;
|
||||
u8 rx;
|
||||
u8 ry;
|
||||
u8 buttons[3];
|
||||
u8 z;
|
||||
u8 rz;
|
||||
le_t<u16, 1> sensor_timestamp;
|
||||
u8 sensor_temperature;
|
||||
le_t<u16, 1> gyro[3];
|
||||
le_t<u16, 1> accel[3];
|
||||
u8 reserved2[5];
|
||||
u8 status[2];
|
||||
u8 reserved3;
|
||||
};
|
||||
static_assert(sizeof(ds4_input_report_common) == 32);
|
||||
|
||||
struct ds4_input_report_usb
|
||||
{
|
||||
u8 report_id;
|
||||
ds4_input_report_common common;
|
||||
u8 num_touch_reports;
|
||||
ds4_touch_report touch_reports[3];
|
||||
u8 reserved[3];
|
||||
};
|
||||
static_assert(sizeof(ds4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
|
||||
|
||||
struct ds4_input_report_bt
|
||||
{
|
||||
u8 report_id;
|
||||
u8 reserved[2];
|
||||
ds4_input_report_common common;
|
||||
u8 num_touch_reports;
|
||||
ds4_touch_report touch_reports[4];
|
||||
u8 reserved2[2];
|
||||
u8 crc32[4];
|
||||
};
|
||||
static_assert(sizeof(ds4_input_report_bt) == DS4_INPUT_REPORT_BLUETOOTH_SIZE);
|
||||
|
||||
struct ds4_output_report_common
|
||||
{
|
||||
u8 valid_flag0;
|
||||
u8 valid_flag1;
|
||||
u8 reserved;
|
||||
u8 motor_right;
|
||||
u8 motor_left;
|
||||
u8 lightbar_red;
|
||||
u8 lightbar_green;
|
||||
u8 lightbar_blue;
|
||||
u8 lightbar_blink_on;
|
||||
u8 lightbar_blink_off;
|
||||
};
|
||||
static_assert(sizeof(ds4_output_report_common) == 10);
|
||||
|
||||
struct ds4_output_report_usb
|
||||
{
|
||||
u8 report_id;
|
||||
ds4_output_report_common common;
|
||||
u8 reserved[21];
|
||||
};
|
||||
static_assert(sizeof(ds4_output_report_usb) == DS4_OUTPUT_REPORT_USB_SIZE);
|
||||
|
||||
struct ds4_output_report_bt
|
||||
{
|
||||
u8 report_id;
|
||||
u8 hw_control;
|
||||
u8 audio_control;
|
||||
ds4_output_report_common common;
|
||||
u8 reserved[61];
|
||||
u8 crc32[4];
|
||||
};
|
||||
static_assert(sizeof(ds4_output_report_bt) == DS4_OUTPUT_REPORT_BLUETOOTH_SIZE);
|
||||
}
|
||||
|
||||
class DS4Device : public HidDevice
|
||||
{
|
||||
public:
|
||||
bool bt_controller{false};
|
||||
bool has_calib_data{false};
|
||||
std::array<CalibData, CalibIndex::COUNT> calib_data{};
|
||||
ds4_input_report_usb report_usb{};
|
||||
ds4_input_report_bt report_bt{};
|
||||
};
|
||||
|
||||
class ds4_pad_handler final : public hid_pad_handler<DS4Device>
|
||||
|
@ -21,79 +21,8 @@ void fmt_class_string<DualSenseDevice::DualSenseDataMode>::format(std::string& o
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
constexpr u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41;
|
||||
constexpr u32 DUALSENSE_VERSION_REPORT_SIZE = 64;
|
||||
constexpr u32 DUALSENSE_BLUETOOTH_REPORT_SIZE = 78;
|
||||
constexpr u32 DUALSENSE_USB_REPORT_SIZE = 63;
|
||||
constexpr u32 DUALSENSE_COMMON_REPORT_SIZE = 47;
|
||||
constexpr u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15;
|
||||
|
||||
constexpr id_pair SONY_DUALSENSE_ID_0 = {0x054C, 0x0CE6}; // DualSense
|
||||
constexpr id_pair SONY_DUALSENSE_ID_1 = {0x054C, 0x0DF2}; // DualSense Edge
|
||||
|
||||
enum
|
||||
{
|
||||
VALID_FLAG_0_COMPATIBLE_VIBRATION = 0x01,
|
||||
VALID_FLAG_0_HAPTICS_SELECT = 0x02,
|
||||
VALID_FLAG_1_MIC_MUTE_LED_CONTROL_ENABLE = 0x01,
|
||||
VALID_FLAG_1_POWER_SAVE_CONTROL_ENABLE = 0x02,
|
||||
VALID_FLAG_1_LIGHTBAR_CONTROL_ENABLE = 0x04,
|
||||
VALID_FLAG_1_RELEASE_LEDS = 0x08,
|
||||
VALID_FLAG_1_PLAYER_INDICATOR_CONTROL_ENABLE = 0x10,
|
||||
VALID_FLAG_2_LIGHTBAR_SETUP_CONTROL_ENABLE = 0x02,
|
||||
VALID_FLAG_2_IMPROVED_RUMBLE_EMULATION = 0x04,
|
||||
POWER_SAVE_CONTROL_MIC_MUTE = 0x10,
|
||||
LIGHTBAR_SETUP_LIGHT_ON = 0x01,
|
||||
LIGHTBAR_SETUP_LIGHT_OUT = 0x02,
|
||||
};
|
||||
|
||||
struct output_report_common
|
||||
{
|
||||
u8 valid_flag_0;
|
||||
u8 valid_flag_1;
|
||||
u8 motor_right;
|
||||
u8 motor_left;
|
||||
u8 headphone_volume;
|
||||
u8 speaker_volume;
|
||||
u8 microphone_volume;
|
||||
u8 audio_enable_bits;
|
||||
u8 mute_button_led;
|
||||
u8 power_save_control;
|
||||
u8 right_trigger_effect[11];
|
||||
u8 left_trigger_effect[11];
|
||||
u8 reserved[6];
|
||||
u8 valid_flag_2;
|
||||
u8 reserved_3[2];
|
||||
u8 lightbar_setup;
|
||||
u8 led_brightness;
|
||||
u8 player_leds;
|
||||
u8 lightbar_r;
|
||||
u8 lightbar_g;
|
||||
u8 lightbar_b;
|
||||
};
|
||||
|
||||
struct output_report_bt
|
||||
{
|
||||
u8 report_id; // 0x31
|
||||
u8 seq_tag;
|
||||
u8 tag;
|
||||
output_report_common common;
|
||||
u8 reserved[24];
|
||||
u8 crc32[4];
|
||||
};
|
||||
|
||||
struct output_report_usb
|
||||
{
|
||||
u8 report_id; // 0x02
|
||||
output_report_common common;
|
||||
u8 reserved[15];
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct output_report_common) == DUALSENSE_COMMON_REPORT_SIZE);
|
||||
static_assert(sizeof(struct output_report_bt) == DUALSENSE_BLUETOOTH_REPORT_SIZE);
|
||||
static_assert(sizeof(struct output_report_usb) == DUALSENSE_USB_REPORT_SIZE);
|
||||
}
|
||||
|
||||
dualsense_pad_handler::dualsense_pad_handler(bool emulation)
|
||||
@ -185,7 +114,7 @@ void dualsense_pad_handler::check_add_device(hid_device* hidDevice, std::string_
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<u8, 64> buf{};
|
||||
std::array<u8, std::max(DUALSENSE_FIRMWARE_REPORT_SIZE, DUALSENSE_PAIRING_REPORT_SIZE)> buf{};
|
||||
buf[0] = 0x09;
|
||||
|
||||
// This will give us the bluetooth mac address of the device, regardless if we are on wired or bluetooth.
|
||||
@ -234,8 +163,8 @@ void dualsense_pad_handler::check_add_device(hid_device* hidDevice, std::string_
|
||||
buf = {};
|
||||
buf[0] = 0x20;
|
||||
|
||||
res = hid_get_feature_report(hidDevice, buf.data(), DUALSENSE_VERSION_REPORT_SIZE);
|
||||
if (res != DUALSENSE_VERSION_REPORT_SIZE || buf[0] != 0x20) // Old versions return 65, newer versions return 64
|
||||
res = hid_get_feature_report(hidDevice, buf.data(), DUALSENSE_FIRMWARE_REPORT_SIZE);
|
||||
if (res != DUALSENSE_FIRMWARE_REPORT_SIZE || buf[0] != 0x20) // Old versions return 65, newer versions return 64
|
||||
{
|
||||
dualsense_log.error("check_add_device: hid_get_feature_report 0x20 failed! Could not retrieve firmware version! result=%d, buf[0]=0x%x, error=%s", res, buf[0], hid_error(hidDevice));
|
||||
}
|
||||
@ -359,34 +288,36 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
|
||||
return DataStatus::NoNewData;
|
||||
|
||||
u8 offset = 0;
|
||||
|
||||
switch (buf[0])
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
if (res == DUALSENSE_BLUETOOTH_REPORT_SIZE)
|
||||
if (res == sizeof(dualsense_input_report_bt))
|
||||
{
|
||||
device->data_mode = DualSenseDevice::DualSenseDataMode::Simple;
|
||||
device->bt_controller = true;
|
||||
offset = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
device->data_mode = DualSenseDevice::DualSenseDataMode::Enhanced;
|
||||
device->bt_controller = false;
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
offset = offsetof(dualsense_input_report_usb, common);
|
||||
break;
|
||||
}
|
||||
case 0x31:
|
||||
{
|
||||
device->data_mode = DualSenseDevice::DualSenseDataMode::Enhanced;
|
||||
device->bt_controller = true;
|
||||
offset = 2;
|
||||
|
||||
offset = offsetof(dualsense_input_report_bt, common);
|
||||
|
||||
const u8 btHdr = 0xA1;
|
||||
const u32 crcHdr = CRCPP::CRC::Calculate(&btHdr, 1, crcTable);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), (DUALSENSE_BLUETOOTH_REPORT_SIZE - 4), crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[DUALSENSE_BLUETOOTH_REPORT_SIZE - 4]);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(buf.data(), offsetof(dualsense_input_report_bt, crc32), crcTable, crcHdr);
|
||||
const u32 crcReported = read_u32(&buf[offsetof(dualsense_input_report_bt, crc32)]);
|
||||
if (crcCalc != crcReported)
|
||||
{
|
||||
dualsense_log.warning("Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x", crcReported, crcCalc);
|
||||
@ -400,7 +331,7 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
|
||||
|
||||
if (device->has_calib_data)
|
||||
{
|
||||
int calib_offset = offset + DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET;
|
||||
int calib_offset = offset + offsetof(dualsense_input_report_common, gyro);
|
||||
for (int i = 0; i < CalibIndex::COUNT; ++i)
|
||||
{
|
||||
const s16 raw_value = read_s16(&buf[calib_offset]);
|
||||
@ -410,10 +341,12 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
|
||||
}
|
||||
}
|
||||
|
||||
std::memcpy(&device->report, &buf[offset], sizeof(dualsense_input_report_common));
|
||||
|
||||
// For now let's only get battery info in enhanced mode
|
||||
if (device->data_mode == DualSenseDevice::DualSenseDataMode::Enhanced)
|
||||
{
|
||||
const u8 battery_state = buf[offset + 52];
|
||||
const u8 battery_state = device->report.status;
|
||||
const u8 battery_value = battery_state & 0x0F; // 10% per unit, starting with 0-9%. So 100% equals unit 10
|
||||
const u8 charge_info = (battery_state & 0xF0) >> 4;
|
||||
|
||||
@ -439,7 +372,6 @@ dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevic
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(device->padData.data(), &buf[offset], device->padData.size());
|
||||
return DataStatus::NewData;
|
||||
}
|
||||
|
||||
@ -670,19 +602,19 @@ void dualsense_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
pad->m_battery_level = dualsense_device->battery_level;
|
||||
pad->m_cable_state = dualsense_device->cable_state;
|
||||
|
||||
const std::array<u8, 64>& buf = dualsense_device->padData;
|
||||
const dualsense_input_report_common& input = dualsense_device->report;
|
||||
|
||||
// these values come already calibrated, all we need to do is convert to ds3 range
|
||||
|
||||
// gyroY is yaw, which is all that we need
|
||||
//f32 gyroX = static_cast<s16>((buf[16] << 8) | buf[15]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
f32 gyroY = static_cast<s16>((buf[18] << 8) | buf[17]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
//f32 gyroZ = static_cast<s16>((buf[20] << 8) | buf[19]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
//f32 gyroX = static_cast<s16>(input.gyro[0]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
f32 gyroY = static_cast<s16>(input.gyro[1]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
//f32 gyroZ = static_cast<s16>(input.gyro[2]) / static_cast<f32>(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f;
|
||||
|
||||
// accel
|
||||
f32 accelX = static_cast<s16>((buf[22] << 8) | buf[21]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
f32 accelY = static_cast<s16>((buf[24] << 8) | buf[23]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
f32 accelZ = static_cast<s16>((buf[26] << 8) | buf[25]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
f32 accelX = static_cast<s16>(input.accel[0]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
f32 accelY = static_cast<s16>(input.accel[1]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
f32 accelZ = static_cast<s16>(input.accel[2]) / static_cast<f32>(DUALSENSE_ACC_RES_PER_G) * -1;
|
||||
|
||||
// now just use formula from ds3
|
||||
accelX = accelX * 113 + 512;
|
||||
@ -705,30 +637,30 @@ std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std:
|
||||
if (!dualsense_dev)
|
||||
return keyBuffer;
|
||||
|
||||
const std::array<u8, 64>& buf = dualsense_dev->padData;
|
||||
const dualsense_input_report_common& input = dualsense_dev->report;
|
||||
|
||||
const bool is_simple_mode = dualsense_dev->data_mode == DualSenseDevice::DualSenseDataMode::Simple;
|
||||
|
||||
// Left Stick X Axis
|
||||
keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - buf[0]) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSXPos] = Clamp0To255((buf[0] - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - input.x) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSXPos] = Clamp0To255((input.x - 127.5f) * 2.0f);
|
||||
|
||||
// Left Stick Y Axis (Up is the negative for some reason)
|
||||
keyBuffer[DualSenseKeyCodes::LSYNeg] = Clamp0To255((buf[1] - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSYPos] = Clamp0To255((127.5f - buf[1]) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSYNeg] = Clamp0To255((input.y - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::LSYPos] = Clamp0To255((127.5f - input.y) * 2.0f);
|
||||
|
||||
// Right Stick X Axis
|
||||
keyBuffer[DualSenseKeyCodes::RSXNeg] = Clamp0To255((127.5f - buf[2]) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSXPos] = Clamp0To255((buf[2] - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSXNeg] = Clamp0To255((127.5f - input.rx) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSXPos] = Clamp0To255((input.rx - 127.5f) * 2.0f);
|
||||
|
||||
// Right Stick Y Axis (Up is the negative for some reason)
|
||||
keyBuffer[DualSenseKeyCodes::RSYNeg] = Clamp0To255((buf[3] - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSYPos] = Clamp0To255((127.5f - buf[3]) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSYNeg] = Clamp0To255((input.ry - 127.5f) * 2.0f);
|
||||
keyBuffer[DualSenseKeyCodes::RSYPos] = Clamp0To255((127.5f - input.ry) * 2.0f);
|
||||
|
||||
keyBuffer[DualSenseKeyCodes::L2] = buf[is_simple_mode ? 7 : 4];
|
||||
keyBuffer[DualSenseKeyCodes::R2] = buf[is_simple_mode ? 8 : 5];
|
||||
keyBuffer[DualSenseKeyCodes::L2] = is_simple_mode ? input.buttons[0] : input.z;
|
||||
keyBuffer[DualSenseKeyCodes::R2] = is_simple_mode ? input.buttons[1] : input.rz;
|
||||
|
||||
u8 data = buf[is_simple_mode ? 4 : 7] & 0xf;
|
||||
u8 data = (is_simple_mode ? input.z : input.buttons[0]) & 0xf;
|
||||
switch (data)
|
||||
{
|
||||
case 0x08: // none pressed
|
||||
@ -789,13 +721,13 @@ std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std:
|
||||
fmt::throw_exception("dualsense dpad state encountered unexpected input");
|
||||
}
|
||||
|
||||
data = buf[is_simple_mode ? 4 : 7] >> 4;
|
||||
data = (is_simple_mode ? input.z : input.buttons[0]) >> 4;
|
||||
keyBuffer[DualSenseKeyCodes::Square] = ((data & 0x01) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::Cross] = ((data & 0x02) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::Circle] = ((data & 0x04) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::Triangle] = ((data & 0x08) != 0) ? 255 : 0;
|
||||
|
||||
data = buf[is_simple_mode ? 5 : 8];
|
||||
data = (is_simple_mode ? input.rz : input.buttons[1]);
|
||||
keyBuffer[DualSenseKeyCodes::L1] = ((data & 0x01) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::R1] = ((data & 0x02) != 0) ? 255 : 0;
|
||||
//keyBuffer[DualSenseKeyCodes::L2] = ((data & 0x04) != 0) ? 255 : 0; // active when L2 is pressed
|
||||
@ -805,7 +737,7 @@ std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std:
|
||||
keyBuffer[DualSenseKeyCodes::L3] = ((data & 0x40) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::R3] = ((data & 0x80) != 0) ? 255 : 0;
|
||||
|
||||
data = buf[is_simple_mode ? 6 : 9];
|
||||
data = (is_simple_mode ? input.seq_number : input.buttons[2]);
|
||||
keyBuffer[DualSenseKeyCodes::PSButton] = ((data & 0x01) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::TouchPad] = ((data & 0x02) != 0) ? 255 : 0;
|
||||
keyBuffer[DualSenseKeyCodes::Mic] = ((data & 0x04) != 0) ? 255 : 0;
|
||||
@ -842,7 +774,10 @@ dualsense_pad_handler::~dualsense_pad_handler()
|
||||
// Disable vibration
|
||||
controller.second->small_motor = 0;
|
||||
controller.second->large_motor = 0;
|
||||
controller.second->release_leds = true;
|
||||
|
||||
// Turns off the lights (disabled due to user complaints)
|
||||
//controller.second->release_leds = true;
|
||||
|
||||
send_output_report(controller.second.get());
|
||||
}
|
||||
}
|
||||
@ -857,7 +792,7 @@ int dualsense_pad_handler::send_output_report(DualSenseDevice* device)
|
||||
if (config == nullptr)
|
||||
return -2; // hid_write returns -1 on error
|
||||
|
||||
output_report_common common{};
|
||||
dualsense_output_report_common common{};
|
||||
|
||||
// Only initialize lightbar in the first output report. The controller didn't seem to update the player LEDs correctly otherwise. (Might be placebo)
|
||||
if (device->init_lightbar)
|
||||
@ -867,7 +802,7 @@ int dualsense_pad_handler::send_output_report(DualSenseDevice* device)
|
||||
device->lightbar_on_old = true;
|
||||
|
||||
common.valid_flag_2 |= VALID_FLAG_2_LIGHTBAR_SETUP_CONTROL_ENABLE;
|
||||
common.lightbar_setup = LIGHTBAR_SETUP_LIGHT_OUT; // Fade light out.
|
||||
common.lightbar_setup = LIGHTBAR_SETUP_LIGHT_OFF; // Fade light out.
|
||||
}
|
||||
else if (device->release_leds)
|
||||
{
|
||||
@ -941,27 +876,24 @@ int dualsense_pad_handler::send_output_report(DualSenseDevice* device)
|
||||
const u8 seq_tag = (device->bt_sequence << 4) | 0x0;
|
||||
if (++device->bt_sequence >= 16) device->bt_sequence = 0;
|
||||
|
||||
output_report_bt report{};
|
||||
dualsense_output_report_bt report{};
|
||||
report.report_id = 0x31; // report id for bluetooth
|
||||
report.seq_tag = seq_tag;
|
||||
report.tag = 0x10; // magic number
|
||||
report.common = common;
|
||||
report.common = std::move(common);
|
||||
|
||||
const u8 btHdr = 0xA2;
|
||||
const u32 crcHdr = CRCPP::CRC::Calculate(&btHdr, 1, crcTable);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(&report.report_id, (DUALSENSE_BLUETOOTH_REPORT_SIZE - 4), crcTable, crcHdr);
|
||||
const u32 crcCalc = CRCPP::CRC::Calculate(&report.report_id, (sizeof(dualsense_output_report_bt) - 4), crcTable, crcHdr);
|
||||
|
||||
report.crc32[0] = (crcCalc >> 0) & 0xFF;
|
||||
report.crc32[1] = (crcCalc >> 8) & 0xFF;
|
||||
report.crc32[2] = (crcCalc >> 16) & 0xFF;
|
||||
report.crc32[3] = (crcCalc >> 24) & 0xFF;
|
||||
write_to_ptr(report.crc32, crcCalc);
|
||||
|
||||
return hid_write(device->hidDevice, &report.report_id, DUALSENSE_BLUETOOTH_REPORT_SIZE);
|
||||
return hid_write(device->hidDevice, &report.report_id, sizeof(dualsense_output_report_bt));
|
||||
}
|
||||
|
||||
output_report_usb report{};
|
||||
dualsense_output_report_usb report{};
|
||||
report.report_id = 0x02; // report id for usb
|
||||
report.common = common;
|
||||
report.common = std::move(common);
|
||||
|
||||
return hid_write(device->hidDevice, &report.report_id, DUALSENSE_USB_REPORT_SIZE);
|
||||
}
|
||||
|
@ -4,6 +4,155 @@
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192;
|
||||
constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 86; // technically this could be 1024, but keeping it at 86 keeps us within 16 bits of precision
|
||||
constexpr u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41;
|
||||
constexpr u32 DUALSENSE_FIRMWARE_REPORT_SIZE = 64;
|
||||
constexpr u32 DUALSENSE_PAIRING_REPORT_SIZE = 20;
|
||||
constexpr u32 DUALSENSE_BLUETOOTH_REPORT_SIZE = 78;
|
||||
constexpr u32 DUALSENSE_USB_REPORT_SIZE = 63; // 64 in hid, because of the report ID being added
|
||||
constexpr u32 DUALSENSE_COMMON_REPORT_SIZE = 47;
|
||||
constexpr u32 DUALSENSE_USB_INPUT_REPORT_SIZE = 64;
|
||||
constexpr u32 DUALSENSE_BLUETOOTH_INPUT_REPORT_SIZE = 78;
|
||||
constexpr u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15;
|
||||
constexpr u32 DUALSENSE_TOUCHPAD_WIDTH = 1920;
|
||||
constexpr u32 DUALSENSE_TOUCHPAD_HEIGHT = 1080;
|
||||
|
||||
enum
|
||||
{
|
||||
VALID_FLAG_0_COMPATIBLE_VIBRATION = 0x01,
|
||||
VALID_FLAG_0_HAPTICS_SELECT = 0x02,
|
||||
VALID_FLAG_0_SET_LEFT_TRIGGER_MOTOR = 0x04,
|
||||
VALID_FLAG_0_SET_RIGHT_TRIGGER_MOTOR = 0x08,
|
||||
VALID_FLAG_0_SET_AUDIO_VOLUME = 0x10,
|
||||
VALID_FLAG_0_TOGGLE_AUDIO = 0x20,
|
||||
VALID_FLAG_0_SET_MICROPHONE_VOLUME = 0x40,
|
||||
VALID_FLAG_0_TOGGLE_MICROPHONE = 0x80,
|
||||
|
||||
VALID_FLAG_1_TOGGLE_MIC_BUTTON_LED = 0x01,
|
||||
VALID_FLAG_1_POWER_SAVE_CONTROL_ENABLE = 0x02,
|
||||
VALID_FLAG_1_LIGHTBAR_CONTROL_ENABLE = 0x04,
|
||||
VALID_FLAG_1_RELEASE_LEDS = 0x08,
|
||||
VALID_FLAG_1_PLAYER_INDICATOR_CONTROL_ENABLE = 0x10,
|
||||
VALID_FLAG_1_EFFECT_POWER = 0x40,
|
||||
|
||||
VALID_FLAG_2_SET_PLAYER_LED_BRIGHTNESS = 0x01,
|
||||
VALID_FLAG_2_LIGHTBAR_SETUP_CONTROL_ENABLE = 0x02,
|
||||
VALID_FLAG_2_IMPROVED_RUMBLE_EMULATION = 0x04,
|
||||
|
||||
AUDIO_BIT_FORCE_INTERNAL_MIC = 0x01,
|
||||
AUDIO_BIT_FORCE_EXTERNAL_MIC = 0x02,
|
||||
AUDIO_BIT_PAD_EXTERNAL_MIC = 0x04,
|
||||
AUDIO_BIT_PAD_INTERNAL_MIC = 0x08,
|
||||
AUDIO_BIT_DISABLE_EXTERNAL_SPEAKERS = 0x10,
|
||||
AUDIO_BIT_ENABLE_INTERNAL_SPEAKERS = 0x20,
|
||||
|
||||
POWER_SAVE_CONTROL_MIC_MUTE = 0x10,
|
||||
POWER_SAVE_CONTROL_AUDIO_MUTE = 0x40,
|
||||
LIGHTBAR_SETUP_LIGHT_ON = 0x01,
|
||||
LIGHTBAR_SETUP_LIGHT_OFF = 0x02,
|
||||
MIC_BUTTON_LED_ON = 0x01,
|
||||
MIC_BUTTON_LED_PULSE = 0x02,
|
||||
};
|
||||
|
||||
struct dualsense_touch_point
|
||||
{
|
||||
u8 contact;
|
||||
u8 x_lo;
|
||||
u8 x_hi : 4;
|
||||
u8 y_lo : 4;
|
||||
u8 y_hi;
|
||||
};
|
||||
static_assert(sizeof(dualsense_touch_point) == 4);
|
||||
|
||||
struct dualsense_input_report_common
|
||||
{
|
||||
u8 x;
|
||||
u8 y;
|
||||
u8 rx;
|
||||
u8 ry;
|
||||
u8 z;
|
||||
u8 rz;
|
||||
u8 seq_number;
|
||||
u8 buttons[4];
|
||||
u8 reserved[4];
|
||||
le_t<u16, 1> gyro[3];
|
||||
le_t<u16, 1> accel[3];
|
||||
le_t<u32, 1> sensor_timestamp;
|
||||
u8 reserved2;
|
||||
dualsense_touch_point points[2];
|
||||
u8 reserved3[12];
|
||||
u8 status;
|
||||
u8 reserved4[10];
|
||||
};
|
||||
|
||||
struct dualsense_input_report_usb
|
||||
{
|
||||
u8 report_id;
|
||||
dualsense_input_report_common common;
|
||||
};
|
||||
static_assert(sizeof(dualsense_input_report_usb) == DUALSENSE_USB_INPUT_REPORT_SIZE);
|
||||
|
||||
struct dualsense_input_report_bt
|
||||
{
|
||||
u8 report_id;
|
||||
u8 something;
|
||||
dualsense_input_report_common common;
|
||||
u8 reserved[9];
|
||||
u8 crc32[4];
|
||||
};
|
||||
static_assert(sizeof(dualsense_input_report_bt) == DUALSENSE_BLUETOOTH_INPUT_REPORT_SIZE);
|
||||
|
||||
struct dualsense_output_report_common
|
||||
{
|
||||
u8 valid_flag_0;
|
||||
u8 valid_flag_1;
|
||||
u8 motor_right;
|
||||
u8 motor_left;
|
||||
u8 headphone_volume;
|
||||
u8 speaker_volume;
|
||||
u8 microphone_volume;
|
||||
u8 audio_enable_bits;
|
||||
u8 mute_button_led;
|
||||
u8 power_save_control;
|
||||
u8 right_trigger_effect[11];
|
||||
u8 left_trigger_effect[11];
|
||||
u8 reserved[6];
|
||||
u8 valid_flag_2;
|
||||
u8 effect_strength_1 : 4; // 0-7 (one for motors, the other for trigger motors, not sure which is which)
|
||||
u8 effect_strength_2 : 4; // 0-7 (one for motors, the other for trigger motors, not sure which is which)
|
||||
u8 reserved2;
|
||||
u8 lightbar_setup;
|
||||
u8 led_brightness;
|
||||
u8 player_leds;
|
||||
u8 lightbar_r;
|
||||
u8 lightbar_g;
|
||||
u8 lightbar_b;
|
||||
};
|
||||
static_assert(sizeof(dualsense_output_report_common) == DUALSENSE_COMMON_REPORT_SIZE);
|
||||
|
||||
struct dualsense_output_report_bt
|
||||
{
|
||||
u8 report_id; // 0x31
|
||||
u8 seq_tag;
|
||||
u8 tag;
|
||||
dualsense_output_report_common common;
|
||||
u8 reserved[24];
|
||||
u8 crc32[4];
|
||||
};
|
||||
static_assert(sizeof(dualsense_output_report_bt) == DUALSENSE_BLUETOOTH_REPORT_SIZE);
|
||||
|
||||
struct dualsense_output_report_usb
|
||||
{
|
||||
u8 report_id; // 0x02
|
||||
dualsense_output_report_common common;
|
||||
u8 reserved[15];
|
||||
};
|
||||
static_assert(sizeof(dualsense_output_report_usb) == DUALSENSE_USB_REPORT_SIZE);
|
||||
}
|
||||
|
||||
class DualSenseDevice : public HidDevice
|
||||
{
|
||||
public:
|
||||
@ -23,6 +172,7 @@ public:
|
||||
u8 bt_sequence{0};
|
||||
bool has_calib_data{false};
|
||||
std::array<CalibData, CalibIndex::COUNT> calib_data{};
|
||||
dualsense_input_report_common report{}; // No need to have separate reports for usb and bluetooth
|
||||
DualSenseDataMode data_mode{DualSenseDataMode::Simple};
|
||||
DualSenseFeatureSet feature_set{DualSenseFeatureSet::Normal};
|
||||
bool init_lightbar{true};
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
#include "hidapi.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
struct CalibData
|
||||
{
|
||||
s16 bias;
|
||||
@ -34,7 +32,6 @@ class HidDevice : public PadDevice
|
||||
public:
|
||||
hid_device* hidDevice{nullptr};
|
||||
std::string path;
|
||||
std::array<u8, 64> padData{};
|
||||
bool new_output_data{true};
|
||||
bool enable_player_leds{false};
|
||||
u8 led_delay_on{0};
|
||||
|
@ -209,11 +209,11 @@ skateboard_pad_handler::DataStatus skateboard_pad_handler::get_data(skateboard_d
|
||||
if (res != static_cast<int>(sizeof(skateboard_input_report)))
|
||||
return DataStatus::NoNewData;
|
||||
|
||||
if (std::memcmp(device->padData.data(), buf.data(), sizeof(skateboard_input_report)) == 0)
|
||||
if (std::memcmp(&device->report, buf.data(), sizeof(skateboard_input_report)) == 0)
|
||||
return DataStatus::NoNewData;
|
||||
|
||||
// Get the new data
|
||||
memcpy(device->padData.data(), buf.data(), sizeof(skateboard_input_report));
|
||||
std::memcpy(&device->report, buf.data(), sizeof(skateboard_input_report));
|
||||
|
||||
// Check the skateboard's power state based on the input report
|
||||
device->skateboard_is_on =
|
||||
@ -272,35 +272,34 @@ PadHandlerBase::connection skateboard_pad_handler::update_connection(const std::
|
||||
std::unordered_map<u64, u16> skateboard_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
|
||||
{
|
||||
std::unordered_map<u64, u16> key_buf;
|
||||
skateboard_device* dualsense_dev = static_cast<skateboard_device*>(device.get());
|
||||
if (!dualsense_dev)
|
||||
skateboard_device* dev = static_cast<skateboard_device*>(device.get());
|
||||
if (!dev)
|
||||
return key_buf;
|
||||
|
||||
const std::array<u8, 64>& buf = dualsense_dev->padData;
|
||||
const skateboard_input_report* input = reinterpret_cast<const skateboard_input_report*>(buf.data());
|
||||
const skateboard_input_report& input = dev->report;
|
||||
|
||||
// D-Pad
|
||||
key_buf[skateboard_key_codes::left] = (input->d_pad == dpad_states::left || input->d_pad == dpad_states::up_left || input->d_pad == dpad_states::down_left) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::right] = (input->d_pad == dpad_states::right || input->d_pad == dpad_states::up_right || input->d_pad == dpad_states::down_right) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::up] = (input->d_pad == dpad_states::up || input->d_pad == dpad_states::up_left || input->d_pad == dpad_states::up_right) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::down] = (input->d_pad == dpad_states::down || input->d_pad == dpad_states::down_left || input->d_pad == dpad_states::down_right) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::left] = (input.d_pad == dpad_states::left || input.d_pad == dpad_states::up_left || input.d_pad == dpad_states::down_left) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::right] = (input.d_pad == dpad_states::right || input.d_pad == dpad_states::up_right || input.d_pad == dpad_states::down_right) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::up] = (input.d_pad == dpad_states::up || input.d_pad == dpad_states::up_left || input.d_pad == dpad_states::up_right) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::down] = (input.d_pad == dpad_states::down || input.d_pad == dpad_states::down_left || input.d_pad == dpad_states::down_right) ? 255 : 0;
|
||||
|
||||
// Face buttons
|
||||
key_buf[skateboard_key_codes::cross] = (input->buttons & button_flags::cross) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::square] = (input->buttons & button_flags::square) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::circle] = (input->buttons & button_flags::circle) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::triangle] = (input->buttons & button_flags::triangle) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::start] = (input->buttons & button_flags::start) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::select] = (input->buttons & button_flags::select) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::ps] = (input->buttons & button_flags::ps) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::cross] = (input.buttons & button_flags::cross) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::square] = (input.buttons & button_flags::square) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::circle] = (input.buttons & button_flags::circle) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::triangle] = (input.buttons & button_flags::triangle) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::start] = (input.buttons & button_flags::start) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::select] = (input.buttons & button_flags::select) ? 255 : 0;
|
||||
key_buf[skateboard_key_codes::ps] = (input.buttons & button_flags::ps) ? 255 : 0;
|
||||
|
||||
// Infrared
|
||||
key_buf[skateboard_key_codes::ir_nose] = input->pressure_triangle;
|
||||
key_buf[skateboard_key_codes::ir_tail] = input->pressure_circle;
|
||||
key_buf[skateboard_key_codes::ir_left] = input->pressure_cross;
|
||||
key_buf[skateboard_key_codes::ir_right] = input->pressure_square;
|
||||
key_buf[skateboard_key_codes::tilt_left] = input->pressure_l1;
|
||||
key_buf[skateboard_key_codes::tilt_right] = input->pressure_r1;
|
||||
key_buf[skateboard_key_codes::ir_nose] = input.pressure_triangle;
|
||||
key_buf[skateboard_key_codes::ir_tail] = input.pressure_circle;
|
||||
key_buf[skateboard_key_codes::ir_left] = input.pressure_cross;
|
||||
key_buf[skateboard_key_codes::ir_right] = input.pressure_square;
|
||||
key_buf[skateboard_key_codes::tilt_left] = input.pressure_l1;
|
||||
key_buf[skateboard_key_codes::tilt_right] = input.pressure_r1;
|
||||
|
||||
// NOTE: Axes X, Y, Z and RZ are always 128, which is the default anyway, so setting the values is omitted.
|
||||
|
||||
@ -316,13 +315,12 @@ void skateboard_pad_handler::get_extended_info(const pad_ensemble& binding)
|
||||
if (!dev || !pad)
|
||||
return;
|
||||
|
||||
const std::array<u8, 64>& buf = dev->padData;
|
||||
const skateboard_input_report* input = reinterpret_cast<const skateboard_input_report*>(buf.data());
|
||||
const skateboard_input_report& input = dev->report;
|
||||
|
||||
pad->m_sensors[0].m_value = Clamp0To1023(input->large_axes[0]);
|
||||
pad->m_sensors[1].m_value = Clamp0To1023(input->large_axes[1]);
|
||||
pad->m_sensors[2].m_value = Clamp0To1023(input->large_axes[2]);
|
||||
pad->m_sensors[3].m_value = Clamp0To1023(input->large_axes[3]);
|
||||
pad->m_sensors[0].m_value = Clamp0To1023(input.large_axes[0]);
|
||||
pad->m_sensors[1].m_value = Clamp0To1023(input.large_axes[1]);
|
||||
pad->m_sensors[2].m_value = Clamp0To1023(input.large_axes[2]);
|
||||
pad->m_sensors[3].m_value = Clamp0To1023(input.large_axes[3]);
|
||||
}
|
||||
|
||||
pad_preview_values skateboard_pad_handler::get_preview_values(const std::unordered_map<u64, u16>& /*data*/)
|
||||
|
@ -143,6 +143,7 @@ class skateboard_device : public HidDevice
|
||||
{
|
||||
public:
|
||||
bool skateboard_is_on = false;
|
||||
skateboard_input_report report{};
|
||||
};
|
||||
|
||||
class skateboard_pad_handler final : public hid_pad_handler<skateboard_device>
|
||||
|
Loading…
x
Reference in New Issue
Block a user