mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-13 16:18:56 +00:00
DualSense: inherit from hid_pad_handler
This commit is contained in:
parent
b9a4abce0e
commit
fbb9396813
@ -4,19 +4,24 @@
|
|||||||
|
|
||||||
LOG_CHANNEL(ds4_log, "DS4");
|
LOG_CHANNEL(ds4_log, "DS4");
|
||||||
|
|
||||||
|
constexpr u16 DS4_VID = 0x054C;
|
||||||
|
constexpr u16 DS4_PID_0 = 0xBA0;
|
||||||
|
constexpr u16 DS4_PID_1 = 0x5C4;
|
||||||
|
constexpr u16 DS4_PID_2 = 0x09CC;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const u32 DS4_ACC_RES_PER_G = 8192;
|
constexpr u32 DS4_ACC_RES_PER_G = 8192;
|
||||||
const u32 DS4_GYRO_RES_PER_DEG_S = 16; // technically this could be 1024, but keeping it at 16 keeps us within 16 bits of precision
|
constexpr u32 DS4_GYRO_RES_PER_DEG_S = 16; // technically this could be 1024, but keeping it at 16 keeps us within 16 bits of precision
|
||||||
const u32 DS4_FEATURE_REPORT_0x02_SIZE = 37;
|
constexpr u32 DS4_FEATURE_REPORT_0x02_SIZE = 37;
|
||||||
const u32 DS4_FEATURE_REPORT_0x05_SIZE = 41;
|
constexpr u32 DS4_FEATURE_REPORT_0x05_SIZE = 41;
|
||||||
const u32 DS4_FEATURE_REPORT_0x12_SIZE = 16;
|
constexpr u32 DS4_FEATURE_REPORT_0x12_SIZE = 16;
|
||||||
const u32 DS4_FEATURE_REPORT_0x81_SIZE = 7;
|
constexpr u32 DS4_FEATURE_REPORT_0x81_SIZE = 7;
|
||||||
const u32 DS4_INPUT_REPORT_0x11_SIZE = 78;
|
constexpr u32 DS4_INPUT_REPORT_0x11_SIZE = 78;
|
||||||
const u32 DS4_OUTPUT_REPORT_0x05_SIZE = 32;
|
constexpr u32 DS4_OUTPUT_REPORT_0x05_SIZE = 32;
|
||||||
const u32 DS4_OUTPUT_REPORT_0x11_SIZE = 78;
|
constexpr u32 DS4_OUTPUT_REPORT_0x11_SIZE = 78;
|
||||||
const u32 DS4_INPUT_REPORT_GYRO_X_OFFSET = 13;
|
constexpr u32 DS4_INPUT_REPORT_GYRO_X_OFFSET = 13;
|
||||||
const u32 DS4_INPUT_REPORT_BATTERY_OFFSET = 30;
|
constexpr u32 DS4_INPUT_REPORT_BATTERY_OFFSET = 30;
|
||||||
|
|
||||||
// This tries to convert axis to give us the max even in the corners,
|
// 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
|
// 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
|
||||||
@ -66,7 +71,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
ds4_pad_handler::ds4_pad_handler()
|
ds4_pad_handler::ds4_pad_handler()
|
||||||
: hid_pad_handler<DS4Device>(pad_handler::ds4, 0x054C, {0xBA0, 0x5C4, 0x09CC})
|
: hid_pad_handler<DS4Device>(pad_handler::ds4, DS4_VID, {DS4_PID_0, DS4_PID_1, DS4_PID_2})
|
||||||
{
|
{
|
||||||
// Unique names for the config files and our pad settings dialog
|
// Unique names for the config files and our pad settings dialog
|
||||||
button_list =
|
button_list =
|
||||||
@ -195,8 +200,8 @@ void ds4_pad_handler::SetPadData(const std::string& padId, u32 largeMotor, u32 s
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Set the device's motor speeds to our requested values 0-255
|
// Set the device's motor speeds to our requested values 0-255
|
||||||
device->largeVibrate = largeMotor;
|
device->large_motor = largeMotor;
|
||||||
device->smallVibrate = smallMotor;
|
device->small_motor = smallMotor;
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (uint i = 0; i < MAX_GAMEPADS; i++)
|
for (uint i = 0; i < MAX_GAMEPADS; i++)
|
||||||
@ -497,24 +502,25 @@ void ds4_pad_handler::check_add_device(hid_device* hidDevice, std::string_view p
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DS4Device* ds4_dev = nullptr;
|
DS4Device* device = nullptr;
|
||||||
|
|
||||||
for (auto& controller : m_controllers)
|
for (auto& controller : m_controllers)
|
||||||
{
|
{
|
||||||
if (!controller.second || !controller.second->hidDevice)
|
ensure(controller.second);
|
||||||
|
|
||||||
|
if (!controller.second->hidDevice)
|
||||||
{
|
{
|
||||||
ds4_dev = controller.second.get();
|
device = controller.second.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ds4_dev)
|
if (!device)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string serial;
|
std::string serial;
|
||||||
ds4_dev->hidDevice = hidDevice;
|
|
||||||
|
|
||||||
// There isnt a nice 'portable' way with hidapi to detect bt vs wired as the pid/vid's are the same
|
// There isnt a nice 'portable' way with hidapi to detect bt vs wired as the pid/vid's are the same
|
||||||
// Let's try getting 0x81 feature report, which should will return mac address on wired, and should error on bluetooth
|
// Let's try getting 0x81 feature report, which should will return mac address on wired, and should error on bluetooth
|
||||||
@ -540,15 +546,18 @@ void ds4_pad_handler::check_add_device(hid_device* hidDevice, std::string_view p
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ds4_dev->btCon = true;
|
device->btCon = true;
|
||||||
for (wchar_t ch : wide_serial)
|
for (wchar_t ch : wide_serial)
|
||||||
serial += static_cast<uchar>(ch);
|
serial += static_cast<uchar>(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!GetCalibrationData(ds4_dev))
|
device->hidDevice = hidDevice;
|
||||||
|
|
||||||
|
if (!GetCalibrationData(device))
|
||||||
{
|
{
|
||||||
ds4_log.error("check_add_device: GetCalibrationData failed!");
|
ds4_log.error("check_add_device: GetCalibrationData failed!");
|
||||||
hid_close(hidDevice);
|
hid_close(hidDevice);
|
||||||
|
device->hidDevice = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,13 +565,14 @@ void ds4_pad_handler::check_add_device(hid_device* hidDevice, std::string_view p
|
|||||||
{
|
{
|
||||||
ds4_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice));
|
ds4_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice));
|
||||||
hid_close(hidDevice);
|
hid_close(hidDevice);
|
||||||
|
device->hidDevice = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ds4_dev->hasCalibData = true;
|
device->hasCalibData = true;
|
||||||
ds4_dev->path = path;
|
device->path = path;
|
||||||
|
|
||||||
send_output_report(ds4_dev);
|
send_output_report(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds4_pad_handler::~ds4_pad_handler()
|
ds4_pad_handler::~ds4_pad_handler()
|
||||||
@ -572,8 +582,8 @@ ds4_pad_handler::~ds4_pad_handler()
|
|||||||
if (controller.second && controller.second->hidDevice)
|
if (controller.second && controller.second->hidDevice)
|
||||||
{
|
{
|
||||||
// Disable blinking and vibration
|
// Disable blinking and vibration
|
||||||
controller.second->smallVibrate = 0;
|
controller.second->small_motor = 0;
|
||||||
controller.second->largeVibrate = 0;
|
controller.second->large_motor = 0;
|
||||||
controller.second->led_delay_on = 0;
|
controller.second->led_delay_on = 0;
|
||||||
controller.second->led_delay_off = 0;
|
controller.second->led_delay_off = 0;
|
||||||
send_output_report(controller.second.get());
|
send_output_report(controller.second.get());
|
||||||
@ -597,8 +607,8 @@ int ds4_pad_handler::send_output_report(DS4Device* device)
|
|||||||
outputBuf[0] = 0x11;
|
outputBuf[0] = 0x11;
|
||||||
outputBuf[1] = 0xC4;
|
outputBuf[1] = 0xC4;
|
||||||
outputBuf[3] = 0x07;
|
outputBuf[3] = 0x07;
|
||||||
outputBuf[6] = device->smallVibrate;
|
outputBuf[6] = device->small_motor;
|
||||||
outputBuf[7] = device->largeVibrate;
|
outputBuf[7] = device->large_motor;
|
||||||
outputBuf[8] = config->colorR; // red
|
outputBuf[8] = config->colorR; // red
|
||||||
outputBuf[9] = config->colorG; // green
|
outputBuf[9] = config->colorG; // green
|
||||||
outputBuf[10] = config->colorB; // blue
|
outputBuf[10] = config->colorB; // blue
|
||||||
@ -624,8 +634,8 @@ int ds4_pad_handler::send_output_report(DS4Device* device)
|
|||||||
{
|
{
|
||||||
outputBuf[0] = 0x05;
|
outputBuf[0] = 0x05;
|
||||||
outputBuf[1] = 0x07;
|
outputBuf[1] = 0x07;
|
||||||
outputBuf[4] = device->smallVibrate;
|
outputBuf[4] = device->small_motor;
|
||||||
outputBuf[5] = device->largeVibrate;
|
outputBuf[5] = device->large_motor;
|
||||||
outputBuf[6] = config->colorR; // red
|
outputBuf[6] = config->colorR; // red
|
||||||
outputBuf[7] = config->colorG; // green
|
outputBuf[7] = config->colorG; // green
|
||||||
outputBuf[8] = config->colorB; // blue
|
outputBuf[8] = config->colorB; // blue
|
||||||
@ -636,7 +646,7 @@ int ds4_pad_handler::send_output_report(DS4Device* device)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ds4_pad_handler::DataStatus ds4_pad_handler::GetRawData(DS4Device* device)
|
ds4_pad_handler::DataStatus ds4_pad_handler::get_data(DS4Device* device)
|
||||||
{
|
{
|
||||||
if (!device || !device->hidDevice)
|
if (!device || !device->hidDevice)
|
||||||
return DataStatus::ReadError;
|
return DataStatus::ReadError;
|
||||||
@ -795,7 +805,7 @@ PadHandlerBase::connection ds4_pad_handler::update_connection(const std::shared_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetRawData(ds4_dev) == DataStatus::ReadError)
|
if (get_data(ds4_dev) == DataStatus::ReadError)
|
||||||
{
|
{
|
||||||
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
||||||
hid_close(ds4_dev->hidDevice);
|
hid_close(ds4_dev->hidDevice);
|
||||||
@ -898,10 +908,10 @@ void ds4_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& device, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ds4_dev->newVibrateData |= ds4_dev->largeVibrate != speed_large || ds4_dev->smallVibrate != speed_small || newBlinkData;
|
ds4_dev->newVibrateData |= ds4_dev->large_motor != speed_large || ds4_dev->small_motor != speed_small || newBlinkData;
|
||||||
|
|
||||||
ds4_dev->largeVibrate = speed_large;
|
ds4_dev->large_motor = speed_large;
|
||||||
ds4_dev->smallVibrate = speed_small;
|
ds4_dev->small_motor = speed_small;
|
||||||
|
|
||||||
if (ds4_dev->newVibrateData && send_output_report(ds4_dev) >= 0)
|
if (ds4_dev->newVibrateData && send_output_report(ds4_dev) >= 0)
|
||||||
{
|
{
|
||||||
|
@ -71,7 +71,7 @@ private:
|
|||||||
u32 get_battery_color(u8 battery_level, int brightness);
|
u32 get_battery_color(u8 battery_level, int brightness);
|
||||||
|
|
||||||
// Copies data into padData if status is NewData, otherwise buffer is untouched
|
// Copies data into padData if status is NewData, otherwise buffer is untouched
|
||||||
DataStatus GetRawData(DS4Device* ds4Device);
|
DataStatus get_data(DS4Device* ds4Device);
|
||||||
// This function gets us usuable buffer from the rawbuffer of padData
|
// This function gets us usuable buffer from the rawbuffer of padData
|
||||||
bool GetCalibrationData(DS4Device* ds4Device);
|
bool GetCalibrationData(DS4Device* ds4Device);
|
||||||
int send_output_report(DS4Device* device);
|
int send_output_report(DS4Device* device);
|
||||||
|
@ -6,13 +6,16 @@ LOG_CHANNEL(dualsense_log, "DualSense");
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
const u32 DUALSENSE_ACC_RES_PER_G = 8192;
|
constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192;
|
||||||
const u32 DUALSENSE_GYRO_RES_PER_DEG_S = 1024;
|
constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 1024;
|
||||||
const u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41;
|
constexpr u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41;
|
||||||
const u32 DUALSENSE_BLUETOOTH_REPORT_SIZE = 78;
|
constexpr u32 DUALSENSE_BLUETOOTH_REPORT_SIZE = 78;
|
||||||
const u32 DUALSENSE_USB_REPORT_SIZE = 63;
|
constexpr u32 DUALSENSE_USB_REPORT_SIZE = 63;
|
||||||
const u32 DUALSENSE_COMMON_REPORT_SIZE = 47;
|
constexpr u32 DUALSENSE_COMMON_REPORT_SIZE = 47;
|
||||||
const u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15;
|
constexpr u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15;
|
||||||
|
|
||||||
|
constexpr u16 DUALSENSE_VID = 0x054C;
|
||||||
|
constexpr u16 DUALSENSE_PID = 0x0CE6;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -68,20 +71,10 @@ namespace
|
|||||||
static_assert(sizeof(struct output_report_common) == DUALSENSE_COMMON_REPORT_SIZE);
|
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_bt) == DUALSENSE_BLUETOOTH_REPORT_SIZE);
|
||||||
static_assert(sizeof(struct output_report_usb) == DUALSENSE_USB_REPORT_SIZE);
|
static_assert(sizeof(struct output_report_usb) == DUALSENSE_USB_REPORT_SIZE);
|
||||||
|
|
||||||
inline s16 read_s16(const void* buf)
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<const s16*>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline u32 read_u32(const void* buf)
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<const u32*>(buf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dualsense_pad_handler::dualsense_pad_handler()
|
dualsense_pad_handler::dualsense_pad_handler()
|
||||||
: PadHandlerBase(pad_handler::dualsense)
|
: hid_pad_handler<DualSenseDevice>(pad_handler::dualsense, DUALSENSE_VID, {DUALSENSE_PID})
|
||||||
{
|
{
|
||||||
// Unique names for the config files and our pad settings dialog
|
// Unique names for the config files and our pad settings dialog
|
||||||
button_list =
|
button_list =
|
||||||
@ -138,11 +131,32 @@ dualsense_pad_handler::dualsense_pad_handler()
|
|||||||
m_thumb_threshold = thumb_max / 2;
|
m_thumb_threshold = thumb_max / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dualsense_pad_handler::CheckAddDevice(hid_device * hidDevice, hid_device_info* hidDevInfo)
|
void dualsense_pad_handler::check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial)
|
||||||
{
|
{
|
||||||
|
if (!hidDevice)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DualSenseDevice* device = nullptr;
|
||||||
|
|
||||||
|
for (auto& controller : m_controllers)
|
||||||
|
{
|
||||||
|
ensure(controller.second);
|
||||||
|
|
||||||
|
if (!controller.second->hidDevice)
|
||||||
|
{
|
||||||
|
device = controller.second.get();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string serial;
|
std::string serial;
|
||||||
std::shared_ptr<DualSenseDevice> dualsenseDev = std::make_shared<DualSenseDevice>();
|
|
||||||
dualsenseDev->hidDevice = hidDevice;
|
|
||||||
|
|
||||||
std::array<u8, 64> buf{};
|
std::array<u8, 64> buf{};
|
||||||
buf[0] = 0x09;
|
buf[0] = 0x09;
|
||||||
@ -153,78 +167,39 @@ void dualsense_pad_handler::CheckAddDevice(hid_device * hidDevice, hid_device_in
|
|||||||
if (hid_get_feature_report(hidDevice, buf.data(), 64) == 21)
|
if (hid_get_feature_report(hidDevice, buf.data(), 64) == 21)
|
||||||
{
|
{
|
||||||
serial = fmt::format("%x%x%x%x%x%x", buf[6], buf[5], buf[4], buf[3], buf[2], buf[1]);
|
serial = fmt::format("%x%x%x%x%x%x", buf[6], buf[5], buf[4], buf[3], buf[2], buf[1]);
|
||||||
dualsenseDev->dataMode = DualSenseDataMode::Enhanced;
|
device->dataMode = DualSenseDevice::DualSenseDataMode::Enhanced;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We're probably on Bluetooth in this case, but for whatever reason the feature report failed.
|
// We're probably on Bluetooth in this case, but for whatever reason the feature report failed.
|
||||||
// This will give us a less capable fallback.
|
// This will give us a less capable fallback.
|
||||||
dualsenseDev->dataMode = DualSenseDataMode::Simple;
|
device->dataMode = DualSenseDevice::DualSenseDataMode::Simple;
|
||||||
std::wstring_view wideSerial(hidDevInfo->serial_number);
|
for (wchar_t ch : wide_serial)
|
||||||
for (wchar_t ch : wideSerial)
|
|
||||||
serial += static_cast<uchar>(ch);
|
serial += static_cast<uchar>(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_calibration_data(dualsenseDev))
|
device->hidDevice = hidDevice;
|
||||||
|
|
||||||
|
if (!get_calibration_data(device))
|
||||||
{
|
{
|
||||||
dualsense_log.error("CheckAddDevice: get_calibration_data failed!");
|
dualsense_log.error("check_add_device: get_calibration_data failed!");
|
||||||
hid_close(hidDevice);
|
hid_close(hidDevice);
|
||||||
|
device->hidDevice = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hid_set_nonblocking(hidDevice, 1) == -1)
|
if (hid_set_nonblocking(hidDevice, 1) == -1)
|
||||||
{
|
{
|
||||||
dualsense_log.error("CheckAddDevice: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice));
|
dualsense_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(hidDevice));
|
||||||
hid_close(hidDevice);
|
hid_close(hidDevice);
|
||||||
|
device->hidDevice = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dualsenseDev->has_calib_data = true;
|
device->has_calib_data = true;
|
||||||
dualsenseDev->path = hidDevInfo->path;
|
device->path = path;
|
||||||
controllers.emplace(serial, dualsenseDev);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool dualsense_pad_handler::Init()
|
send_output_report(device);
|
||||||
{
|
|
||||||
if (is_init)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const int res = hid_init();
|
|
||||||
if (res != 0)
|
|
||||||
fmt::throw_exception("hidapi-init error.threadproc");
|
|
||||||
|
|
||||||
hid_device_info* devInfo = hid_enumerate(DUALSENSE_VID, DUALSENSE_PID);
|
|
||||||
hid_device_info* head = devInfo;
|
|
||||||
|
|
||||||
while (devInfo)
|
|
||||||
{
|
|
||||||
if (controllers.size() >= MAX_GAMEPADS)
|
|
||||||
break;
|
|
||||||
|
|
||||||
hid_device* dev = hid_open_path(devInfo->path);
|
|
||||||
if (dev)
|
|
||||||
{
|
|
||||||
CheckAddDevice(dev, devInfo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dualsense_log.error("hid_open_path failed! Reason: %s", hid_error(dev));
|
|
||||||
}
|
|
||||||
devInfo = devInfo->next;
|
|
||||||
}
|
|
||||||
hid_free_enumeration(head);
|
|
||||||
|
|
||||||
if (controllers.empty())
|
|
||||||
{
|
|
||||||
dualsense_log.warning("No controllers found!");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dualsense_log.success("Controllers found: %d", controllers.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
is_init = true;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dualsense_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
void dualsense_pad_handler::init_config(pad_config* cfg, const std::string& name)
|
||||||
@ -283,30 +258,10 @@ void dualsense_pad_handler::init_config(pad_config* cfg, const std::string& name
|
|||||||
cfg->from_default();
|
cfg->from_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> dualsense_pad_handler::ListDevices()
|
dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevice* device)
|
||||||
{
|
|
||||||
std::vector<std::string> dualsense_pads_list;
|
|
||||||
|
|
||||||
if (!Init())
|
|
||||||
return dualsense_pads_list;
|
|
||||||
|
|
||||||
for (usz i = 1; i < controllers.size(); ++i)
|
|
||||||
{
|
|
||||||
dualsense_pads_list.emplace_back(m_name_string + std::to_string(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& pad : dualsense_pads_list)
|
|
||||||
{
|
|
||||||
dualsense_log.success("%s", pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dualsense_pads_list;
|
|
||||||
}
|
|
||||||
|
|
||||||
dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(const std::shared_ptr<DualSenseDevice>& device)
|
|
||||||
{
|
{
|
||||||
if (!device)
|
if (!device)
|
||||||
return DualSenseDataStatus::ReadError;
|
return DataStatus::ReadError;
|
||||||
|
|
||||||
std::array<u8, 128> buf{};
|
std::array<u8, 128> buf{};
|
||||||
|
|
||||||
@ -315,11 +270,11 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con
|
|||||||
if (res == -1)
|
if (res == -1)
|
||||||
{
|
{
|
||||||
// looks like controller disconnected or read error
|
// looks like controller disconnected or read error
|
||||||
return DualSenseDataStatus::ReadError;
|
return DataStatus::ReadError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
return DualSenseDataStatus::NoNewData;
|
return DataStatus::NoNewData;
|
||||||
|
|
||||||
u8 offset = 0;
|
u8 offset = 0;
|
||||||
switch (buf[0])
|
switch (buf[0])
|
||||||
@ -328,13 +283,13 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con
|
|||||||
{
|
{
|
||||||
if (res == DUALSENSE_BLUETOOTH_REPORT_SIZE)
|
if (res == DUALSENSE_BLUETOOTH_REPORT_SIZE)
|
||||||
{
|
{
|
||||||
device->dataMode = DualSenseDataMode::Simple;
|
device->dataMode = DualSenseDevice::DualSenseDataMode::Simple;
|
||||||
device->btCon = true;
|
device->btCon = true;
|
||||||
offset = 1;
|
offset = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
device->dataMode = DualSenseDataMode::Enhanced;
|
device->dataMode = DualSenseDevice::DualSenseDataMode::Enhanced;
|
||||||
device->btCon = false;
|
device->btCon = false;
|
||||||
offset = 1;
|
offset = 1;
|
||||||
}
|
}
|
||||||
@ -342,7 +297,7 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con
|
|||||||
}
|
}
|
||||||
case 0x31:
|
case 0x31:
|
||||||
{
|
{
|
||||||
device->dataMode = DualSenseDataMode::Enhanced;
|
device->dataMode = DualSenseDevice::DualSenseDataMode::Enhanced;
|
||||||
device->btCon = true;
|
device->btCon = true;
|
||||||
offset = 2;
|
offset = 2;
|
||||||
|
|
||||||
@ -353,18 +308,18 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con
|
|||||||
if (crcCalc != crcReported)
|
if (crcCalc != crcReported)
|
||||||
{
|
{
|
||||||
dualsense_log.warning("Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x", crcReported, crcCalc);
|
dualsense_log.warning("Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x", crcReported, crcCalc);
|
||||||
return DualSenseDataStatus::NoNewData;
|
return DataStatus::NoNewData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return DualSenseDataStatus::NoNewData;
|
return DataStatus::NoNewData;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->has_calib_data)
|
if (device->has_calib_data)
|
||||||
{
|
{
|
||||||
int calib_offset = offset + DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET;
|
int calib_offset = offset + DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET;
|
||||||
for (int i = 0; i < DualSenseCalibIndex::COUNT; ++i)
|
for (int i = 0; i < CalibIndex::COUNT; ++i)
|
||||||
{
|
{
|
||||||
const s16 raw_value = read_s16(&buf[calib_offset]);
|
const s16 raw_value = read_s16(&buf[calib_offset]);
|
||||||
const s16 cal_value = apply_calibration(raw_value, device->calib_data[i]);
|
const s16 cal_value = apply_calibration(raw_value, device->calib_data[i]);
|
||||||
@ -374,10 +329,10 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(device->padData.data(), &buf[offset], 64);
|
memcpy(device->padData.data(), &buf[offset], 64);
|
||||||
return DualSenseDataStatus::NewData;
|
return DataStatus::NewData;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dualsense_pad_handler::get_calibration_data(const std::shared_ptr<DualSenseDevice>& dualsense_device)
|
bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_device)
|
||||||
{
|
{
|
||||||
if (!dualsense_device || !dualsense_device->hidDevice)
|
if (!dualsense_device || !dualsense_device->hidDevice)
|
||||||
{
|
{
|
||||||
@ -426,9 +381,9 @@ bool dualsense_pad_handler::get_calibration_data(const std::shared_ptr<DualSense
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::PITCH].bias = read_s16(&buf[1]);
|
dualsense_device->calib_data[CalibIndex::PITCH].bias = read_s16(&buf[1]);
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::YAW].bias = read_s16(&buf[3]);
|
dualsense_device->calib_data[CalibIndex::YAW].bias = read_s16(&buf[3]);
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::ROLL].bias = read_s16(&buf[5]);
|
dualsense_device->calib_data[CalibIndex::ROLL].bias = read_s16(&buf[5]);
|
||||||
|
|
||||||
s16 pitch_plus, pitch_minus, roll_plus, roll_minus, yaw_plus, yaw_minus;
|
s16 pitch_plus, pitch_minus, roll_plus, roll_minus, yaw_plus, yaw_minus;
|
||||||
|
|
||||||
@ -467,14 +422,14 @@ bool dualsense_pad_handler::get_calibration_data(const std::shared_ptr<DualSense
|
|||||||
|
|
||||||
const s32 gyro_speed_scale = read_s16(&buf[19]) + read_s16(&buf[21]);
|
const s32 gyro_speed_scale = read_s16(&buf[19]) + read_s16(&buf[21]);
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::PITCH].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
dualsense_device->calib_data[CalibIndex::PITCH].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::PITCH].sens_denom = pitch_plus - pitch_minus;
|
dualsense_device->calib_data[CalibIndex::PITCH].sens_denom = pitch_plus - pitch_minus;
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::YAW].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
dualsense_device->calib_data[CalibIndex::YAW].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::YAW].sens_denom = yaw_plus - yaw_minus;
|
dualsense_device->calib_data[CalibIndex::YAW].sens_denom = yaw_plus - yaw_minus;
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::ROLL].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
dualsense_device->calib_data[CalibIndex::ROLL].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::ROLL].sens_denom = roll_plus - roll_minus;
|
dualsense_device->calib_data[CalibIndex::ROLL].sens_denom = roll_plus - roll_minus;
|
||||||
|
|
||||||
const s16 accel_x_plus = read_s16(&buf[23]);
|
const s16 accel_x_plus = read_s16(&buf[23]);
|
||||||
const s16 accel_x_minus = read_s16(&buf[25]);
|
const s16 accel_x_minus = read_s16(&buf[25]);
|
||||||
@ -487,17 +442,17 @@ bool dualsense_pad_handler::get_calibration_data(const std::shared_ptr<DualSense
|
|||||||
const s32 accel_y_range = accel_y_plus - accel_y_minus;
|
const s32 accel_y_range = accel_y_plus - accel_y_minus;
|
||||||
const s32 accel_z_range = accel_z_plus - accel_z_minus;
|
const s32 accel_z_range = accel_z_plus - accel_z_minus;
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::X].bias = accel_x_plus - accel_x_range / 2;
|
dualsense_device->calib_data[CalibIndex::X].bias = accel_x_plus - accel_x_range / 2;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::X].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
dualsense_device->calib_data[CalibIndex::X].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::X].sens_denom = accel_x_range;
|
dualsense_device->calib_data[CalibIndex::X].sens_denom = accel_x_range;
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Y].bias = accel_y_plus - accel_y_range / 2;
|
dualsense_device->calib_data[CalibIndex::Y].bias = accel_y_plus - accel_y_range / 2;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Y].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
dualsense_device->calib_data[CalibIndex::Y].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Y].sens_denom = accel_y_range;
|
dualsense_device->calib_data[CalibIndex::Y].sens_denom = accel_y_range;
|
||||||
|
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Z].bias = accel_z_plus - accel_z_range / 2;
|
dualsense_device->calib_data[CalibIndex::Z].bias = accel_z_plus - accel_z_range / 2;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Z].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
dualsense_device->calib_data[CalibIndex::Z].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G;
|
||||||
dualsense_device->calib_data[DualSenseCalibIndex::Z].sens_denom = accel_z_range;
|
dualsense_device->calib_data[CalibIndex::Z].sens_denom = accel_z_range;
|
||||||
|
|
||||||
// Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected
|
// Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected
|
||||||
|
|
||||||
@ -553,8 +508,8 @@ bool dualsense_pad_handler::get_is_right_stick(u64 keyCode)
|
|||||||
|
|
||||||
PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
|
PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::shared_ptr<PadDevice>& device)
|
||||||
{
|
{
|
||||||
auto dualsense_dev = std::static_pointer_cast<DualSenseDevice>(device);
|
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get());
|
||||||
if (!dualsense_dev)
|
if (!dualsense_dev || dualsense_dev->path.empty())
|
||||||
return connection::disconnected;
|
return connection::disconnected;
|
||||||
|
|
||||||
if (dualsense_dev->hidDevice == nullptr)
|
if (dualsense_dev->hidDevice == nullptr)
|
||||||
@ -578,8 +533,7 @@ PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = GetRawData(dualsense_dev);
|
if (get_data(dualsense_dev) == DataStatus::ReadError)
|
||||||
if (status == DualSenseDataStatus::ReadError)
|
|
||||||
{
|
{
|
||||||
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
// this also can mean disconnected, either way deal with it on next loop and reconnect
|
||||||
hid_close(dualsense_dev->hidDevice);
|
hid_close(dualsense_dev->hidDevice);
|
||||||
@ -593,7 +547,7 @@ PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::s
|
|||||||
|
|
||||||
void dualsense_pad_handler::get_extended_info(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad)
|
void dualsense_pad_handler::get_extended_info(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad)
|
||||||
{
|
{
|
||||||
auto dualsense_device = std::static_pointer_cast<DualSenseDevice>(device);
|
DualSenseDevice* dualsense_device = static_cast<DualSenseDevice*>(device.get());
|
||||||
if (!dualsense_device || !pad)
|
if (!dualsense_device || !pad)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -631,13 +585,13 @@ void dualsense_pad_handler::get_extended_info(const std::shared_ptr<PadDevice>&
|
|||||||
std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
|
std::unordered_map<u64, u16> dualsense_pad_handler::get_button_values(const std::shared_ptr<PadDevice>& device)
|
||||||
{
|
{
|
||||||
std::unordered_map<u64, u16> keyBuffer;
|
std::unordered_map<u64, u16> keyBuffer;
|
||||||
auto dualsense_dev = std::static_pointer_cast<DualSenseDevice>(device);
|
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get());
|
||||||
if (!dualsense_dev)
|
if (!dualsense_dev)
|
||||||
return keyBuffer;
|
return keyBuffer;
|
||||||
|
|
||||||
auto buf = dualsense_dev->padData;
|
auto buf = dualsense_dev->padData;
|
||||||
|
|
||||||
if (dualsense_dev->dataMode == DualSenseDataMode::Simple)
|
if (dualsense_dev->dataMode == DualSenseDevice::DualSenseDataMode::Simple)
|
||||||
{
|
{
|
||||||
// Left Stick X Axis
|
// Left Stick X Axis
|
||||||
keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - buf[0]) * 2.0f);
|
keyBuffer[DualSenseKeyCodes::LSXNeg] = Clamp0To255((127.5f - buf[0]) * 2.0f);
|
||||||
@ -860,63 +814,23 @@ pad_preview_values dualsense_pad_handler::get_preview_values(const std::unordere
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<dualsense_pad_handler::DualSenseDevice> dualsense_pad_handler::GetDualSenseDevice(const std::string& padId)
|
|
||||||
{
|
|
||||||
if (!Init())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
usz pos = padId.find(m_name_string);
|
|
||||||
if (pos == umax)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
std::string pad_serial = padId.substr(pos + 15);
|
|
||||||
std::shared_ptr<DualSenseDevice> device = nullptr;
|
|
||||||
|
|
||||||
int i = 0; // Controllers 1-n in GUI
|
|
||||||
for (auto& cur_control : controllers)
|
|
||||||
{
|
|
||||||
if (pad_serial == std::to_string(++i) || pad_serial == cur_control.first)
|
|
||||||
{
|
|
||||||
device = cur_control.second;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return device;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<PadDevice> dualsense_pad_handler::get_device(const std::string& device)
|
|
||||||
{
|
|
||||||
std::shared_ptr<DualSenseDevice> dualsense_dev = GetDualSenseDevice(device);
|
|
||||||
if (dualsense_dev == nullptr || dualsense_dev->hidDevice == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return dualsense_dev;
|
|
||||||
}
|
|
||||||
|
|
||||||
dualsense_pad_handler::~dualsense_pad_handler()
|
dualsense_pad_handler::~dualsense_pad_handler()
|
||||||
{
|
{
|
||||||
for (auto& controller : controllers)
|
for (auto& controller : m_controllers)
|
||||||
{
|
{
|
||||||
if (controller.second->hidDevice)
|
if (controller.second && controller.second->hidDevice)
|
||||||
{
|
{
|
||||||
// Disable vibration
|
// Disable vibration
|
||||||
controller.second->smallVibrate = 0;
|
controller.second->small_motor = 0;
|
||||||
controller.second->largeVibrate = 0;
|
controller.second->large_motor = 0;
|
||||||
send_output_report(controller.second);
|
send_output_report(controller.second.get());
|
||||||
|
|
||||||
hid_close(controller.second->hidDevice);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (hid_exit() != 0)
|
|
||||||
{
|
|
||||||
dualsense_log.error("hid_exit failed!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dualsense_pad_handler::send_output_report(const std::shared_ptr<DualSenseDevice>& device)
|
int dualsense_pad_handler::send_output_report(DualSenseDevice* device)
|
||||||
{
|
{
|
||||||
if (!device)
|
if (!device || !device->hidDevice)
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
auto config = device->config;
|
auto config = device->config;
|
||||||
@ -926,8 +840,8 @@ int dualsense_pad_handler::send_output_report(const std::shared_ptr<DualSenseDev
|
|||||||
output_report_common common{};
|
output_report_common common{};
|
||||||
common.valid_flag_0 |= VALID_FLAG_0_COMPATIBLE_VIBRATION;
|
common.valid_flag_0 |= VALID_FLAG_0_COMPATIBLE_VIBRATION;
|
||||||
common.valid_flag_0 |= VALID_FLAG_0_HAPTICS_SELECT;
|
common.valid_flag_0 |= VALID_FLAG_0_HAPTICS_SELECT;
|
||||||
common.motor_left = device->largeVibrate;
|
common.motor_left = device->large_motor;
|
||||||
common.motor_right = device->smallVibrate;
|
common.motor_right = device->small_motor;
|
||||||
|
|
||||||
if (device->init_lightbar)
|
if (device->init_lightbar)
|
||||||
{
|
{
|
||||||
@ -1003,8 +917,8 @@ int dualsense_pad_handler::send_output_report(const std::shared_ptr<DualSenseDev
|
|||||||
|
|
||||||
void dualsense_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad)
|
void dualsense_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& device, const std::shared_ptr<Pad>& pad)
|
||||||
{
|
{
|
||||||
auto dualsense_dev = std::static_pointer_cast<DualSenseDevice>(device);
|
DualSenseDevice* dualsense_dev = static_cast<DualSenseDevice*>(device.get());
|
||||||
if (!dualsense_dev || !pad)
|
if (!dualsense_dev || !dualsense_dev->hidDevice || !pad)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto config = dualsense_dev->config;
|
auto config = dualsense_dev->config;
|
||||||
@ -1016,10 +930,10 @@ void dualsense_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& dev
|
|||||||
const int speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
const int speed_large = config->enable_vibration_motor_large ? pad->m_vibrateMotors[idx_l].m_value : vibration_min;
|
||||||
const int speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
const int speed_small = config->enable_vibration_motor_small ? pad->m_vibrateMotors[idx_s].m_value : vibration_min;
|
||||||
|
|
||||||
dualsense_dev->newVibrateData |= dualsense_dev->largeVibrate != speed_large || dualsense_dev->smallVibrate != speed_small;
|
dualsense_dev->newVibrateData |= dualsense_dev->large_motor != speed_large || dualsense_dev->small_motor != speed_small;
|
||||||
|
|
||||||
dualsense_dev->largeVibrate = speed_large;
|
dualsense_dev->large_motor = speed_large;
|
||||||
dualsense_dev->smallVibrate = speed_small;
|
dualsense_dev->small_motor = speed_small;
|
||||||
|
|
||||||
if (dualsense_dev->newVibrateData)
|
if (dualsense_dev->newVibrateData)
|
||||||
{
|
{
|
||||||
@ -1032,13 +946,13 @@ void dualsense_pad_handler::apply_pad_data(const std::shared_ptr<PadDevice>& dev
|
|||||||
|
|
||||||
void dualsense_pad_handler::SetPadData(const std::string& padId, u32 largeMotor, u32 smallMotor, s32 r, s32 g, s32 b, bool /*battery_led*/, u32 /*battery_led_brightness*/)
|
void dualsense_pad_handler::SetPadData(const std::string& padId, u32 largeMotor, u32 smallMotor, s32 r, s32 g, s32 b, bool /*battery_led*/, u32 /*battery_led_brightness*/)
|
||||||
{
|
{
|
||||||
std::shared_ptr<DualSenseDevice> device = GetDualSenseDevice(padId);
|
std::shared_ptr<DualSenseDevice> device = get_hid_device(padId);
|
||||||
if (device == nullptr || device->hidDevice == nullptr)
|
if (device == nullptr || device->hidDevice == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Set the device's motor speeds to our requested values 0-255
|
// Set the device's motor speeds to our requested values 0-255
|
||||||
device->largeVibrate = largeMotor;
|
device->large_motor = largeMotor;
|
||||||
device->smallVibrate = smallMotor;
|
device->small_motor = smallMotor;
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (uint i = 0; i < MAX_GAMEPADS; i++)
|
for (uint i = 0; i < MAX_GAMEPADS; i++)
|
||||||
@ -1065,5 +979,5 @@ void dualsense_pad_handler::SetPadData(const std::string& padId, u32 largeMotor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start/Stop the engines :)
|
// Start/Stop the engines :)
|
||||||
send_output_report(device);
|
send_output_report(device.get());
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Emu/Io/PadHandler.h"
|
#include "hid_pad_handler.h"
|
||||||
#include "Utilities/CRC.h"
|
#include "Utilities/CRC.h"
|
||||||
#include "hidapi.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class dualsense_pad_handler final : public PadHandlerBase
|
class DualSenseDevice : public HidDevice
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class DualSenseDataMode
|
||||||
|
{
|
||||||
|
Simple,
|
||||||
|
Enhanced
|
||||||
|
};
|
||||||
|
|
||||||
|
bool btCon{false};
|
||||||
|
u8 bt_sequence{0};
|
||||||
|
bool has_calib_data{false};
|
||||||
|
std::array<CalibData, CalibIndex::COUNT> calib_data{};
|
||||||
|
DualSenseDataMode dataMode{DualSenseDataMode::Simple};
|
||||||
|
std::array<u8, 64> padData{};
|
||||||
|
bool newVibrateData{true};
|
||||||
|
bool init_lightbar{true};
|
||||||
|
bool update_lightbar{true};
|
||||||
|
bool update_player_leds{true};
|
||||||
|
};
|
||||||
|
|
||||||
|
class dualsense_pad_handler final : public hid_pad_handler<DualSenseDevice>
|
||||||
{
|
{
|
||||||
enum DualSenseKeyCodes
|
enum DualSenseKeyCodes
|
||||||
{
|
{
|
||||||
@ -43,102 +63,19 @@ class dualsense_pad_handler final : public PadHandlerBase
|
|||||||
KeyCodeCount
|
KeyCodeCount
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DualSenseCalibIndex
|
|
||||||
{
|
|
||||||
// gyro
|
|
||||||
PITCH = 0,
|
|
||||||
YAW,
|
|
||||||
ROLL,
|
|
||||||
|
|
||||||
// accel
|
|
||||||
X,
|
|
||||||
Y,
|
|
||||||
Z,
|
|
||||||
COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class DualSenseDataStatus
|
|
||||||
{
|
|
||||||
NewData,
|
|
||||||
NoNewData,
|
|
||||||
ReadError,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class DualSenseDataMode
|
|
||||||
{
|
|
||||||
Simple,
|
|
||||||
Enhanced
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DualSenseCalibData
|
|
||||||
{
|
|
||||||
s16 bias;
|
|
||||||
s32 sens_numer;
|
|
||||||
s32 sens_denom;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DualSenseDevice : public PadDevice
|
|
||||||
{
|
|
||||||
hid_device* hidDevice{ nullptr };
|
|
||||||
std::string path{ "" };
|
|
||||||
bool btCon{ false };
|
|
||||||
u8 bt_sequence{ 0 };
|
|
||||||
bool has_calib_data{false};
|
|
||||||
std::array<DualSenseCalibData, DualSenseCalibIndex::COUNT> calib_data{};
|
|
||||||
DualSenseDataMode dataMode{ DualSenseDataMode::Simple };
|
|
||||||
std::array<u8, 64> padData{};
|
|
||||||
bool newVibrateData{true};
|
|
||||||
u8 largeVibrate{0};
|
|
||||||
u8 smallVibrate{0};
|
|
||||||
bool init_lightbar{true};
|
|
||||||
bool update_lightbar{true};
|
|
||||||
bool update_player_leds{true};
|
|
||||||
};
|
|
||||||
|
|
||||||
const u16 DUALSENSE_VID = 0x054C;
|
|
||||||
const u16 DUALSENSE_PID = 0x0CE6;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, std::shared_ptr<DualSenseDevice>> controllers;
|
|
||||||
CRCPP::CRC::Table<u32, 32> crcTable{CRCPP::CRC::CRC_32()};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
dualsense_pad_handler();
|
dualsense_pad_handler();
|
||||||
~dualsense_pad_handler();
|
~dualsense_pad_handler();
|
||||||
|
|
||||||
bool Init() override;
|
|
||||||
|
|
||||||
std::vector<std::string> ListDevices() override;
|
|
||||||
void SetPadData(const std::string& padId, u32 largeMotor, u32 smallMotor, s32 r, s32 g, s32 b, bool battery_led, u32 battery_led_brightness) override;
|
void SetPadData(const std::string& padId, u32 largeMotor, u32 smallMotor, s32 r, s32 g, s32 b, bool battery_led, u32 battery_led_brightness) override;
|
||||||
void init_config(pad_config* cfg, const std::string& name) override;
|
void init_config(pad_config* cfg, const std::string& name) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_init = false;
|
DataStatus get_data(DualSenseDevice* dualsenseDevice);
|
||||||
DualSenseDataStatus status;
|
bool get_calibration_data(DualSenseDevice* dualsense_device);
|
||||||
|
|
||||||
private:
|
void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial);
|
||||||
std::shared_ptr<DualSenseDevice> GetDualSenseDevice(const std::string& padId);
|
int send_output_report(DualSenseDevice* device);
|
||||||
|
|
||||||
DualSenseDataStatus GetRawData(const std::shared_ptr<DualSenseDevice>& dualsenseDevice);
|
|
||||||
bool get_calibration_data(const std::shared_ptr<DualSenseDevice>& dualsense_device);
|
|
||||||
|
|
||||||
inline s16 apply_calibration(s32 rawValue, const DualSenseCalibData& calib_data)
|
|
||||||
{
|
|
||||||
const s32 biased = rawValue - calib_data.bias;
|
|
||||||
const s32 quot = calib_data.sens_numer / calib_data.sens_denom;
|
|
||||||
const s32 rem = calib_data.sens_numer % calib_data.sens_denom;
|
|
||||||
const s32 output = (quot * biased) + ((rem * biased) / calib_data.sens_denom);
|
|
||||||
|
|
||||||
if (output > INT16_MAX)
|
|
||||||
return INT16_MAX;
|
|
||||||
else if (output < INT16_MIN)
|
|
||||||
return INT16_MIN;
|
|
||||||
else
|
|
||||||
return static_cast<s16>(output);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckAddDevice(hid_device* hidDevice, hid_device_info* hidDevInfo);
|
|
||||||
int send_output_report(const std::shared_ptr<DualSenseDevice>& device);
|
|
||||||
std::shared_ptr<PadDevice> get_device(const std::string& device) override;
|
|
||||||
bool get_is_left_trigger(u64 keyCode) override;
|
bool get_is_left_trigger(u64 keyCode) override;
|
||||||
bool get_is_right_trigger(u64 keyCode) override;
|
bool get_is_right_trigger(u64 keyCode) override;
|
||||||
bool get_is_left_stick(u64 keyCode) override;
|
bool get_is_left_stick(u64 keyCode) override;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "hid_pad_handler.h"
|
#include "hid_pad_handler.h"
|
||||||
#include "ds4_pad_handler.h"
|
#include "ds4_pad_handler.h"
|
||||||
|
#include "dualsense_pad_handler.h"
|
||||||
#include "util/logs.hpp"
|
#include "util/logs.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -198,3 +199,4 @@ std::shared_ptr<PadDevice> hid_pad_handler<Device>::get_device(const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
template class hid_pad_handler<DS4Device>;
|
template class hid_pad_handler<DS4Device>;
|
||||||
|
template class hid_pad_handler<DualSenseDevice>;
|
||||||
|
@ -31,8 +31,8 @@ class HidDevice : public PadDevice
|
|||||||
public:
|
public:
|
||||||
hid_device* hidDevice{nullptr};
|
hid_device* hidDevice{nullptr};
|
||||||
std::string path{""};
|
std::string path{""};
|
||||||
u8 largeVibrate{0};
|
u8 large_motor{0};
|
||||||
u8 smallVibrate{0};
|
u8 small_motor{0};
|
||||||
u8 led_delay_on{0};
|
u8 led_delay_on{0};
|
||||||
u8 led_delay_off{0};
|
u8 led_delay_off{0};
|
||||||
};
|
};
|
||||||
@ -72,6 +72,8 @@ protected:
|
|||||||
std::shared_ptr<Device> get_hid_device(const std::string& padId);
|
std::shared_ptr<Device> get_hid_device(const std::string& padId);
|
||||||
|
|
||||||
virtual void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view serial) = 0;
|
virtual void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view serial) = 0;
|
||||||
|
virtual int send_output_report(Device* device) = 0;
|
||||||
|
virtual DataStatus get_data(Device* device) = 0;
|
||||||
|
|
||||||
inline s16 apply_calibration(s32 rawValue, const CalibData& calibData)
|
inline s16 apply_calibration(s32 rawValue, const CalibData& calibData)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user