diff --git a/rpcs3/Input/ds3_pad_handler.cpp b/rpcs3/Input/ds3_pad_handler.cpp index 7c80b57e0f..6050f25770 100644 --- a/rpcs3/Input/ds3_pad_handler.cpp +++ b/rpcs3/Input/ds3_pad_handler.cpp @@ -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 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 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>(ds3dev->padData, 41 + DS3_HID_OFFSET); + pad->m_sensors[0].m_value = read_from_ptr>(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>(ds3dev->padData, 41 + DS3_HID_OFFSET) - 512); + pad->m_sensors[0].m_value = 512 - (read_from_ptr>(ds3dev->report.data, 41 + DS3_HID_OFFSET) - 512); #endif - pad->m_sensors[1].m_value = read_from_ptr>(ds3dev->padData, 45 + DS3_HID_OFFSET); - pad->m_sensors[2].m_value = read_from_ptr>(ds3dev->padData, 43 + DS3_HID_OFFSET); - pad->m_sensors[3].m_value = read_from_ptr>(ds3dev->padData, 47 + DS3_HID_OFFSET); + pad->m_sensors[1].m_value = read_from_ptr>(ds3dev->report.data, 45 + DS3_HID_OFFSET); + pad->m_sensors[2].m_value = read_from_ptr>(ds3dev->report.data, 43 + DS3_HID_OFFSET); + pad->m_sensors[3].m_value = read_from_ptr>(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 diff --git a/rpcs3/Input/ds3_pad_handler.h b/rpcs3/Input/ds3_pad_handler.h index 327feead80..144fb95c2e 100644 --- a/rpcs3/Input/ds3_pad_handler.h +++ b/rpcs3/Input/ds3_pad_handler.h @@ -4,12 +4,54 @@ #include +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 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 diff --git a/rpcs3/Input/ds4_pad_handler.cpp b/rpcs3/Input/ds4_pad_handler.cpp index 817d07d9b9..ea0fd4a1b7 100644 --- a/rpcs3/Input/ds4_pad_handler.cpp +++ b/rpcs3/Input/ds4_pad_handler.cpp @@ -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 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 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 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 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 buf{}; + std::array 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(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((buf[20] << 8) | buf[19]) / static_cast(DS4_ACC_RES_PER_G) * -1; - f32 accelY = static_cast((buf[22] << 8) | buf[21]) / static_cast(DS4_ACC_RES_PER_G) * -1; - f32 accelZ = static_cast((buf[24] << 8) | buf[23]) / static_cast(DS4_ACC_RES_PER_G) * -1; + f32 accelX = static_cast(input.accel[0]) / static_cast(DS4_ACC_RES_PER_G) * -1; + f32 accelY = static_cast(input.accel[1]) / static_cast(DS4_ACC_RES_PER_G) * -1; + f32 accelZ = static_cast(input.accel[2]) / static_cast(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((u16)(buf[14] << 8) | buf[13]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; - f32 gyroY = static_cast((buf[16] << 8) | buf[15]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; - //f32 gyroZ = static_cast((u16)(buf[18] << 8) | buf[17]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; + //f32 gyroX = static_cast(input.gyro[0]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; + f32 gyroY = static_cast(input.gyro[1]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; + //f32 gyroZ = static_cast(input.gyro[2]) / static_cast(DS4_GYRO_RES_PER_DEG_S) * -1; // Convert to ds3. The ds3 resolution is 123/90°/sec. gyroY = gyroY * (123.f / 90.f) + 512; diff --git a/rpcs3/Input/ds4_pad_handler.h b/rpcs3/Input/ds4_pad_handler.h index 448528404b..635dab8e60 100644 --- a/rpcs3/Input/ds4_pad_handler.h +++ b/rpcs3/Input/ds4_pad_handler.h @@ -4,12 +4,123 @@ #include +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 sensor_timestamp; + u8 sensor_temperature; + le_t gyro[3]; + le_t 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 calib_data{}; + ds4_input_report_usb report_usb{}; + ds4_input_report_bt report_bt{}; }; class ds4_pad_handler final : public hid_pad_handler diff --git a/rpcs3/Input/dualsense_pad_handler.cpp b/rpcs3/Input/dualsense_pad_handler.cpp index 6c1a7aa52e..9959d1dfa2 100644 --- a/rpcs3/Input/dualsense_pad_handler.cpp +++ b/rpcs3/Input/dualsense_pad_handler.cpp @@ -21,79 +21,8 @@ void fmt_class_string::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 buf{}; + std::array 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& 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((buf[16] << 8) | buf[15]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; - f32 gyroY = static_cast((buf[18] << 8) | buf[17]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; - //f32 gyroZ = static_cast((buf[20] << 8) | buf[19]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; + //f32 gyroX = static_cast(input.gyro[0]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; + f32 gyroY = static_cast(input.gyro[1]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; + //f32 gyroZ = static_cast(input.gyro[2]) / static_cast(DUALSENSE_GYRO_RES_PER_DEG_S) * -1.f; // accel - f32 accelX = static_cast((buf[22] << 8) | buf[21]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; - f32 accelY = static_cast((buf[24] << 8) | buf[23]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; - f32 accelZ = static_cast((buf[26] << 8) | buf[25]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; + f32 accelX = static_cast(input.accel[0]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; + f32 accelY = static_cast(input.accel[1]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; + f32 accelZ = static_cast(input.accel[2]) / static_cast(DUALSENSE_ACC_RES_PER_G) * -1; // now just use formula from ds3 accelX = accelX * 113 + 512; @@ -705,30 +637,30 @@ std::unordered_map dualsense_pad_handler::get_button_values(const std: if (!dualsense_dev) return keyBuffer; - const std::array& 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 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 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); } diff --git a/rpcs3/Input/dualsense_pad_handler.h b/rpcs3/Input/dualsense_pad_handler.h index fec445bb3a..3b05dbc3d5 100644 --- a/rpcs3/Input/dualsense_pad_handler.h +++ b/rpcs3/Input/dualsense_pad_handler.h @@ -4,6 +4,155 @@ #include +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 gyro[3]; + le_t accel[3]; + le_t 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 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}; diff --git a/rpcs3/Input/hid_pad_handler.h b/rpcs3/Input/hid_pad_handler.h index 9de2e3f9d5..2f616db945 100644 --- a/rpcs3/Input/hid_pad_handler.h +++ b/rpcs3/Input/hid_pad_handler.h @@ -6,8 +6,6 @@ #include "hidapi.h" -#include - struct CalibData { s16 bias; @@ -34,7 +32,6 @@ class HidDevice : public PadDevice public: hid_device* hidDevice{nullptr}; std::string path; - std::array padData{}; bool new_output_data{true}; bool enable_player_leds{false}; u8 led_delay_on{0}; diff --git a/rpcs3/Input/skateboard_pad_handler.cpp b/rpcs3/Input/skateboard_pad_handler.cpp index 83092295b1..126e005a33 100644 --- a/rpcs3/Input/skateboard_pad_handler.cpp +++ b/rpcs3/Input/skateboard_pad_handler.cpp @@ -209,11 +209,11 @@ skateboard_pad_handler::DataStatus skateboard_pad_handler::get_data(skateboard_d if (res != static_cast(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 skateboard_pad_handler::get_button_values(const std::shared_ptr& device) { std::unordered_map key_buf; - skateboard_device* dualsense_dev = static_cast(device.get()); - if (!dualsense_dev) + skateboard_device* dev = static_cast(device.get()); + if (!dev) return key_buf; - const std::array& buf = dualsense_dev->padData; - const skateboard_input_report* input = reinterpret_cast(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& buf = dev->padData; - const skateboard_input_report* input = reinterpret_cast(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& /*data*/) diff --git a/rpcs3/Input/skateboard_pad_handler.h b/rpcs3/Input/skateboard_pad_handler.h index df239122ed..c5ca7a3224 100644 --- a/rpcs3/Input/skateboard_pad_handler.h +++ b/rpcs3/Input/skateboard_pad_handler.h @@ -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