From fbb93968131e0cb984b94158cc2061ed7944b664 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 11 Feb 2021 23:27:33 +0100 Subject: [PATCH] DualSense: inherit from hid_pad_handler --- rpcs3/Input/ds4_pad_handler.cpp | 80 +++---- rpcs3/Input/ds4_pad_handler.h | 2 +- rpcs3/Input/dualsense_pad_handler.cpp | 290 +++++++++----------------- rpcs3/Input/dualsense_pad_handler.h | 117 +++-------- rpcs3/Input/hid_pad_handler.cpp | 2 + rpcs3/Input/hid_pad_handler.h | 6 +- 6 files changed, 181 insertions(+), 316 deletions(-) diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index fad938739d..021c4546fa 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -4,19 +4,24 @@ 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 { - const 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 - const u32 DS4_FEATURE_REPORT_0x02_SIZE = 37; - const u32 DS4_FEATURE_REPORT_0x05_SIZE = 41; - const u32 DS4_FEATURE_REPORT_0x12_SIZE = 16; - const u32 DS4_FEATURE_REPORT_0x81_SIZE = 7; - const u32 DS4_INPUT_REPORT_0x11_SIZE = 78; - const u32 DS4_OUTPUT_REPORT_0x05_SIZE = 32; - const u32 DS4_OUTPUT_REPORT_0x11_SIZE = 78; - const u32 DS4_INPUT_REPORT_GYRO_X_OFFSET = 13; - const u32 DS4_INPUT_REPORT_BATTERY_OFFSET = 30; + constexpr u32 DS4_ACC_RES_PER_G = 8192; + 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 + 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_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 @@ -66,7 +71,7 @@ namespace } ds4_pad_handler::ds4_pad_handler() - : hid_pad_handler(pad_handler::ds4, 0x054C, {0xBA0, 0x5C4, 0x09CC}) + : hid_pad_handler(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 button_list = @@ -195,8 +200,8 @@ void ds4_pad_handler::SetPadData(const std::string& padId, u32 largeMotor, u32 s return; // Set the device's motor speeds to our requested values 0-255 - device->largeVibrate = largeMotor; - device->smallVibrate = smallMotor; + device->large_motor = largeMotor; + device->small_motor = smallMotor; int index = 0; 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; } - DS4Device* ds4_dev = nullptr; + DS4Device* device = nullptr; 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; } } - if (!ds4_dev) + if (!device) { return; } 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 // 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 { - ds4_dev->btCon = true; + device->btCon = true; for (wchar_t ch : wide_serial) serial += static_cast(ch); } - if (!GetCalibrationData(ds4_dev)) + device->hidDevice = hidDevice; + + if (!GetCalibrationData(device)) { ds4_log.error("check_add_device: GetCalibrationData failed!"); hid_close(hidDevice); + device->hidDevice = nullptr; 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)); hid_close(hidDevice); + device->hidDevice = nullptr; return; } - ds4_dev->hasCalibData = true; - ds4_dev->path = path; + device->hasCalibData = true; + device->path = path; - send_output_report(ds4_dev); + send_output_report(device); } ds4_pad_handler::~ds4_pad_handler() @@ -572,8 +582,8 @@ ds4_pad_handler::~ds4_pad_handler() if (controller.second && controller.second->hidDevice) { // Disable blinking and vibration - controller.second->smallVibrate = 0; - controller.second->largeVibrate = 0; + controller.second->small_motor = 0; + controller.second->large_motor = 0; controller.second->led_delay_on = 0; controller.second->led_delay_off = 0; send_output_report(controller.second.get()); @@ -597,8 +607,8 @@ int ds4_pad_handler::send_output_report(DS4Device* device) outputBuf[0] = 0x11; outputBuf[1] = 0xC4; outputBuf[3] = 0x07; - outputBuf[6] = device->smallVibrate; - outputBuf[7] = device->largeVibrate; + 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 @@ -624,8 +634,8 @@ int ds4_pad_handler::send_output_report(DS4Device* device) { outputBuf[0] = 0x05; outputBuf[1] = 0x07; - outputBuf[4] = device->smallVibrate; - outputBuf[5] = device->largeVibrate; + 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 @@ -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) 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 hid_close(ds4_dev->hidDevice); @@ -898,10 +908,10 @@ void ds4_pad_handler::apply_pad_data(const std::shared_ptr& 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->smallVibrate = speed_small; + ds4_dev->large_motor = speed_large; + ds4_dev->small_motor = speed_small; if (ds4_dev->newVibrateData && send_output_report(ds4_dev) >= 0) { diff --git a/rpcs3/Input/ds4_pad_handler.h b/rpcs3/Input/ds4_pad_handler.h index 8ff9632f42..2bf651fd53 100644 --- a/rpcs3/Input/ds4_pad_handler.h +++ b/rpcs3/Input/ds4_pad_handler.h @@ -71,7 +71,7 @@ private: u32 get_battery_color(u8 battery_level, int brightness); // 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 bool GetCalibrationData(DS4Device* ds4Device); int send_output_report(DS4Device* device); diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index bf0c94ba72..d57c661ae7 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -6,13 +6,16 @@ LOG_CHANNEL(dualsense_log, "DualSense"); namespace { - const u32 DUALSENSE_ACC_RES_PER_G = 8192; - const u32 DUALSENSE_GYRO_RES_PER_DEG_S = 1024; - const u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41; - const u32 DUALSENSE_BLUETOOTH_REPORT_SIZE = 78; - const u32 DUALSENSE_USB_REPORT_SIZE = 63; - const u32 DUALSENSE_COMMON_REPORT_SIZE = 47; - const u32 DUALSENSE_INPUT_REPORT_GYRO_X_OFFSET = 15; + constexpr u32 DUALSENSE_ACC_RES_PER_G = 8192; + constexpr u32 DUALSENSE_GYRO_RES_PER_DEG_S = 1024; + constexpr u32 DUALSENSE_CALIBRATION_REPORT_SIZE = 41; + 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 u16 DUALSENSE_VID = 0x054C; + constexpr u16 DUALSENSE_PID = 0x0CE6; enum { @@ -68,20 +71,10 @@ namespace 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); - - inline s16 read_s16(const void* buf) - { - return *reinterpret_cast(buf); - } - - inline u32 read_u32(const void* buf) - { - return *reinterpret_cast(buf); - } } dualsense_pad_handler::dualsense_pad_handler() - : PadHandlerBase(pad_handler::dualsense) + : hid_pad_handler(pad_handler::dualsense, DUALSENSE_VID, {DUALSENSE_PID}) { // Unique names for the config files and our pad settings dialog button_list = @@ -138,11 +131,32 @@ dualsense_pad_handler::dualsense_pad_handler() 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::shared_ptr dualsenseDev = std::make_shared(); - dualsenseDev->hidDevice = hidDevice; std::array buf{}; 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) { 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 { // We're probably on Bluetooth in this case, but for whatever reason the feature report failed. // This will give us a less capable fallback. - dualsenseDev->dataMode = DualSenseDataMode::Simple; - std::wstring_view wideSerial(hidDevInfo->serial_number); - for (wchar_t ch : wideSerial) + device->dataMode = DualSenseDevice::DualSenseDataMode::Simple; + for (wchar_t ch : wide_serial) serial += static_cast(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); + device->hidDevice = nullptr; return; } 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); + device->hidDevice = nullptr; return; } - dualsenseDev->has_calib_data = true; - dualsenseDev->path = hidDevInfo->path; - controllers.emplace(serial, dualsenseDev); -} + device->has_calib_data = true; + device->path = path; -bool dualsense_pad_handler::Init() -{ - 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; + send_output_report(device); } 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(); } -std::vector dualsense_pad_handler::ListDevices() -{ - std::vector 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& device) +dualsense_pad_handler::DataStatus dualsense_pad_handler::get_data(DualSenseDevice* device) { if (!device) - return DualSenseDataStatus::ReadError; + return DataStatus::ReadError; std::array buf{}; @@ -315,11 +270,11 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con if (res == -1) { // looks like controller disconnected or read error - return DualSenseDataStatus::ReadError; + return DataStatus::ReadError; } if (res == 0) - return DualSenseDataStatus::NoNewData; + return DataStatus::NoNewData; u8 offset = 0; switch (buf[0]) @@ -328,13 +283,13 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con { if (res == DUALSENSE_BLUETOOTH_REPORT_SIZE) { - device->dataMode = DualSenseDataMode::Simple; + device->dataMode = DualSenseDevice::DualSenseDataMode::Simple; device->btCon = true; offset = 1; } else { - device->dataMode = DualSenseDataMode::Enhanced; + device->dataMode = DualSenseDevice::DualSenseDataMode::Enhanced; device->btCon = false; offset = 1; } @@ -342,7 +297,7 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con } case 0x31: { - device->dataMode = DualSenseDataMode::Enhanced; + device->dataMode = DualSenseDevice::DualSenseDataMode::Enhanced; device->btCon = true; offset = 2; @@ -353,18 +308,18 @@ dualsense_pad_handler::DualSenseDataStatus dualsense_pad_handler::GetRawData(con if (crcCalc != crcReported) { dualsense_log.warning("Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x", crcReported, crcCalc); - return DualSenseDataStatus::NoNewData; + return DataStatus::NoNewData; } break; } default: - return DualSenseDataStatus::NoNewData; + return DataStatus::NoNewData; } if (device->has_calib_data) { 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 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); - return DualSenseDataStatus::NewData; + return DataStatus::NewData; } -bool dualsense_pad_handler::get_calibration_data(const std::shared_ptr& dualsense_device) +bool dualsense_pad_handler::get_calibration_data(DualSenseDevice* dualsense_device) { if (!dualsense_device || !dualsense_device->hidDevice) { @@ -426,9 +381,9 @@ bool dualsense_pad_handler::get_calibration_data(const std::shared_ptrcalib_data[DualSenseCalibIndex::PITCH].bias = read_s16(&buf[1]); - dualsense_device->calib_data[DualSenseCalibIndex::YAW].bias = read_s16(&buf[3]); - dualsense_device->calib_data[DualSenseCalibIndex::ROLL].bias = read_s16(&buf[5]); + dualsense_device->calib_data[CalibIndex::PITCH].bias = read_s16(&buf[1]); + dualsense_device->calib_data[CalibIndex::YAW].bias = read_s16(&buf[3]); + dualsense_device->calib_data[CalibIndex::ROLL].bias = read_s16(&buf[5]); 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_ptrcalib_data[DualSenseCalibIndex::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_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; + 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[DualSenseCalibIndex::YAW].sens_denom = yaw_plus - yaw_minus; + dualsense_device->calib_data[CalibIndex::YAW].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; + 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[DualSenseCalibIndex::ROLL].sens_denom = roll_plus - roll_minus; + dualsense_device->calib_data[CalibIndex::ROLL].sens_numer = gyro_speed_scale * DUALSENSE_GYRO_RES_PER_DEG_S; + 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_minus = read_s16(&buf[25]); @@ -487,17 +442,17 @@ bool dualsense_pad_handler::get_calibration_data(const std::shared_ptrcalib_data[DualSenseCalibIndex::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[DualSenseCalibIndex::X].sens_denom = accel_x_range; + dualsense_device->calib_data[CalibIndex::X].bias = accel_x_plus - accel_x_range / 2; + dualsense_device->calib_data[CalibIndex::X].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; + 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[DualSenseCalibIndex::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].bias = accel_y_plus - accel_y_range / 2; + dualsense_device->calib_data[CalibIndex::Y].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; + 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[DualSenseCalibIndex::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].bias = accel_z_plus - accel_z_range / 2; + dualsense_device->calib_data[CalibIndex::Z].sens_numer = 2 * DUALSENSE_ACC_RES_PER_G; + 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 @@ -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& device) { - auto dualsense_dev = std::static_pointer_cast(device); - if (!dualsense_dev) + DualSenseDevice* dualsense_dev = static_cast(device.get()); + if (!dualsense_dev || dualsense_dev->path.empty()) return connection::disconnected; if (dualsense_dev->hidDevice == nullptr) @@ -578,8 +533,7 @@ PadHandlerBase::connection dualsense_pad_handler::update_connection(const std::s } } - status = GetRawData(dualsense_dev); - if (status == DualSenseDataStatus::ReadError) + if (get_data(dualsense_dev) == DataStatus::ReadError) { // this also can mean disconnected, either way deal with it on next loop and reconnect 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& device, const std::shared_ptr& pad) { - auto dualsense_device = std::static_pointer_cast(device); + DualSenseDevice* dualsense_device = static_cast(device.get()); if (!dualsense_device || !pad) return; @@ -631,13 +585,13 @@ void dualsense_pad_handler::get_extended_info(const std::shared_ptr& std::unordered_map dualsense_pad_handler::get_button_values(const std::shared_ptr& device) { std::unordered_map keyBuffer; - auto dualsense_dev = std::static_pointer_cast(device); + DualSenseDevice* dualsense_dev = static_cast(device.get()); if (!dualsense_dev) return keyBuffer; auto buf = dualsense_dev->padData; - if (dualsense_dev->dataMode == DualSenseDataMode::Simple) + if (dualsense_dev->dataMode == DualSenseDevice::DualSenseDataMode::Simple) { // Left Stick X Axis 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::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 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 dualsense_pad_handler::get_device(const std::string& device) -{ - std::shared_ptr dualsense_dev = GetDualSenseDevice(device); - if (dualsense_dev == nullptr || dualsense_dev->hidDevice == nullptr) - return nullptr; - - return dualsense_dev; -} - 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 - controller.second->smallVibrate = 0; - controller.second->largeVibrate = 0; - send_output_report(controller.second); - - hid_close(controller.second->hidDevice); + controller.second->small_motor = 0; + controller.second->large_motor = 0; + send_output_report(controller.second.get()); } } - if (hid_exit() != 0) - { - dualsense_log.error("hid_exit failed!"); - } } -int dualsense_pad_handler::send_output_report(const std::shared_ptr& device) +int dualsense_pad_handler::send_output_report(DualSenseDevice* device) { - if (!device) + if (!device || !device->hidDevice) return -2; auto config = device->config; @@ -926,8 +840,8 @@ int dualsense_pad_handler::send_output_report(const std::shared_ptrlargeVibrate; - common.motor_right = device->smallVibrate; + common.motor_left = device->large_motor; + common.motor_right = device->small_motor; if (device->init_lightbar) { @@ -1003,8 +917,8 @@ int dualsense_pad_handler::send_output_report(const std::shared_ptr& device, const std::shared_ptr& pad) { - auto dualsense_dev = std::static_pointer_cast(device); - if (!dualsense_dev || !pad) + DualSenseDevice* dualsense_dev = static_cast(device.get()); + if (!dualsense_dev || !dualsense_dev->hidDevice || !pad) return; auto config = dualsense_dev->config; @@ -1016,10 +930,10 @@ void dualsense_pad_handler::apply_pad_data(const std::shared_ptr& dev 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; - 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->smallVibrate = speed_small; + dualsense_dev->large_motor = speed_large; + dualsense_dev->small_motor = speed_small; if (dualsense_dev->newVibrateData) { @@ -1032,13 +946,13 @@ void dualsense_pad_handler::apply_pad_data(const std::shared_ptr& 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*/) { - std::shared_ptr device = GetDualSenseDevice(padId); + std::shared_ptr device = get_hid_device(padId); if (device == nullptr || device->hidDevice == nullptr) return; // Set the device's motor speeds to our requested values 0-255 - device->largeVibrate = largeMotor; - device->smallVibrate = smallMotor; + device->large_motor = largeMotor; + device->small_motor = smallMotor; int index = 0; 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 :) - send_output_report(device); + send_output_report(device.get()); } diff --git a/rpcs3/Input/dualsense_pad_handler.h b/rpcs3/Input/dualsense_pad_handler.h index e061d409ec..028d8fa84a 100644 --- a/rpcs3/Input/dualsense_pad_handler.h +++ b/rpcs3/Input/dualsense_pad_handler.h @@ -1,12 +1,32 @@ #pragma once -#include "Emu/Io/PadHandler.h" +#include "hid_pad_handler.h" #include "Utilities/CRC.h" -#include "hidapi.h" #include -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 calib_data{}; + DualSenseDataMode dataMode{DualSenseDataMode::Simple}; + std::array 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 { enum DualSenseKeyCodes { @@ -43,102 +63,19 @@ class dualsense_pad_handler final : public PadHandlerBase 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 calib_data{}; - DualSenseDataMode dataMode{ DualSenseDataMode::Simple }; - std::array 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> controllers; - CRCPP::CRC::Table crcTable{CRCPP::CRC::CRC_32()}; - public: dualsense_pad_handler(); ~dualsense_pad_handler(); - bool Init() override; - - std::vector 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 init_config(pad_config* cfg, const std::string& name) override; private: - bool is_init = false; - DualSenseDataStatus status; + DataStatus get_data(DualSenseDevice* dualsenseDevice); + bool get_calibration_data(DualSenseDevice* dualsense_device); -private: - std::shared_ptr GetDualSenseDevice(const std::string& padId); - - DualSenseDataStatus GetRawData(const std::shared_ptr& dualsenseDevice); - bool get_calibration_data(const std::shared_ptr& 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(output); - } - - void CheckAddDevice(hid_device* hidDevice, hid_device_info* hidDevInfo); - int send_output_report(const std::shared_ptr& device); - std::shared_ptr get_device(const std::string& device) override; + void check_add_device(hid_device* hidDevice, std::string_view path, std::wstring_view wide_serial); + int send_output_report(DualSenseDevice* device); bool get_is_left_trigger(u64 keyCode) override; bool get_is_right_trigger(u64 keyCode) override; bool get_is_left_stick(u64 keyCode) override; diff --git a/rpcs3/Input/hid_pad_handler.cpp b/rpcs3/Input/hid_pad_handler.cpp index f624a3e413..5d6153883e 100644 --- a/rpcs3/Input/hid_pad_handler.cpp +++ b/rpcs3/Input/hid_pad_handler.cpp @@ -1,5 +1,6 @@ #include "hid_pad_handler.h" #include "ds4_pad_handler.h" +#include "dualsense_pad_handler.h" #include "util/logs.hpp" #include @@ -198,3 +199,4 @@ std::shared_ptr hid_pad_handler::get_device(const std::string } template class hid_pad_handler; +template class hid_pad_handler; diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index 6af2535c38..f81b2e2f57 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -31,8 +31,8 @@ class HidDevice : public PadDevice public: hid_device* hidDevice{nullptr}; std::string path{""}; - u8 largeVibrate{0}; - u8 smallVibrate{0}; + u8 large_motor{0}; + u8 small_motor{0}; u8 led_delay_on{0}; u8 led_delay_off{0}; }; @@ -72,6 +72,8 @@ protected: std::shared_ptr 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 int send_output_report(Device* device) = 0; + virtual DataStatus get_data(Device* device) = 0; inline s16 apply_calibration(s32 rawValue, const CalibData& calibData) {