2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2020-02-15 23:36:20 +01:00
# include "ds4_pad_handler.h"
2020-02-22 20:42:49 +01:00
# include "Emu/Io/pad_config.h"
2017-04-29 03:02:28 +02:00
2020-02-01 09:23:50 +01:00
LOG_CHANNEL ( ds4_log , " DS4 " ) ;
2021-03-30 10:58:11 +02:00
constexpr id_pair SONY_DS4_ID_0 = { 0x054C , 0xBA0 } ;
constexpr id_pair SONY_DS4_ID_1 = { 0x054C , 0x5C4 } ;
constexpr id_pair SONY_DS4_ID_2 = { 0x054C , 0x09CC } ;
constexpr id_pair ZEROPLUS_ID_0 = { 0x0C12 , 0x0E20 } ;
2021-02-11 23:27:33 +01:00
2017-04-29 03:02:28 +02:00
namespace
{
2021-02-11 23:27:33 +01:00
constexpr u32 DS4_ACC_RES_PER_G = 8192 ;
2022-10-17 22:41:34 +02:00
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
2021-02-11 23:27:33 +01:00
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 ;
2021-10-15 00:12:15 +02:00
constexpr u32 DS4_FEATURE_REPORT_0xA3_SIZE = 49 ;
2021-02-11 23:27:33 +01:00
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 ;
2017-04-29 03:02:28 +02:00
// 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
//taken from http://theinstructionlimit.com/squaring-the-thumbsticks
/*std::tuple<u16, u16> ConvertToSquarePoint(u16 inX, u16 inY, u32 innerRoundness = 0) {
// convert inX and Y to a (-1, 1) vector;
const f32 x = ( inX - 127 ) / 127.f ;
const f32 y = ( ( inY - 127 ) / 127.f ) * - 1 ;
f32 outX , outY ;
const f32 piOver4 = M_PI / 4 ;
const f32 angle = std : : atan2 ( y , x ) + M_PI ;
// x+ wall
if ( angle < = piOver4 | | angle > 7 * piOver4 ) {
outX = x * ( f32 ) ( 1 / std : : cos ( angle ) ) ;
outY = y * ( f32 ) ( 1 / std : : cos ( angle ) ) ;
}
// y+ wall
else if ( angle > piOver4 & & angle < = 3 * piOver4 ) {
outX = x * ( f32 ) ( 1 / std : : sin ( angle ) ) ;
outY = y * ( f32 ) ( 1 / std : : sin ( angle ) ) ;
}
// x- wall
else if ( angle > 3 * piOver4 & & angle < = 5 * piOver4 ) {
outX = x * ( f32 ) ( - 1 / std : : cos ( angle ) ) ;
outY = y * ( f32 ) ( - 1 / std : : cos ( angle ) ) ;
}
// y- wall
else if ( angle > 5 * piOver4 & & angle < = 7 * piOver4 ) {
outX = x * ( f32 ) ( - 1 / std : : sin ( angle ) ) ;
outY = y * ( f32 ) ( - 1 / std : : sin ( angle ) ) ;
}
else fmt : : throw_exception ( " invalid angle in convertToSquarePoint " ) ;
if ( innerRoundness = = 0 )
return std : : tuple < u16 , u16 > ( Clamp0To255 ( ( outX + 1 ) * 127.f ) , Clamp0To255 ( ( ( outY * - 1 ) + 1 ) * 127.f ) ) ;
const f32 len = std : : sqrt ( std : : pow ( x , 2 ) + std : : pow ( y , 2 ) ) ;
const f32 factor = std : : pow ( len , innerRoundness ) ;
outX = ( 1 - factor ) * x + factor * outX ;
outY = ( 1 - factor ) * y + factor * outY ;
return std : : tuple < u16 , u16 > ( Clamp0To255 ( ( outX + 1 ) * 127.f ) , Clamp0To255 ( ( ( outY * - 1 ) + 1 ) * 127.f ) ) ;
} */
}
2017-11-27 22:31:15 +01:00
2021-02-11 22:13:21 +01:00
ds4_pad_handler : : ds4_pad_handler ( )
2021-03-30 10:58:11 +02:00
: hid_pad_handler < DS4Device > ( pad_handler : : ds4 , { SONY_DS4_ID_0 , SONY_DS4_ID_1 , SONY_DS4_ID_2 , ZEROPLUS_ID_0 } )
2017-04-29 03:02:28 +02:00
{
2019-09-20 16:28:55 +02:00
// Unique names for the config files and our pad settings dialog
button_list =
{
2021-08-08 16:45:45 +02:00
{ DS4KeyCodes : : None , " " } ,
2019-09-20 16:28:55 +02:00
{ DS4KeyCodes : : Triangle , " Triangle " } ,
{ DS4KeyCodes : : Circle , " Circle " } ,
{ DS4KeyCodes : : Cross , " Cross " } ,
{ DS4KeyCodes : : Square , " Square " } ,
{ DS4KeyCodes : : Left , " Left " } ,
{ DS4KeyCodes : : Right , " Right " } ,
{ DS4KeyCodes : : Up , " Up " } ,
{ DS4KeyCodes : : Down , " Down " } ,
{ DS4KeyCodes : : R1 , " R1 " } ,
{ DS4KeyCodes : : R2 , " R2 " } ,
{ DS4KeyCodes : : R3 , " R3 " } ,
{ DS4KeyCodes : : Options , " Options " } ,
{ DS4KeyCodes : : Share , " Share " } ,
{ DS4KeyCodes : : PSButton , " PS Button " } ,
{ DS4KeyCodes : : TouchPad , " Touch Pad " } ,
{ DS4KeyCodes : : L1 , " L1 " } ,
{ DS4KeyCodes : : L2 , " L2 " } ,
{ DS4KeyCodes : : L3 , " L3 " } ,
{ DS4KeyCodes : : LSXNeg , " LS X- " } ,
{ DS4KeyCodes : : LSXPos , " LS X+ " } ,
{ DS4KeyCodes : : LSYPos , " LS Y+ " } ,
{ DS4KeyCodes : : LSYNeg , " LS Y- " } ,
{ DS4KeyCodes : : RSXNeg , " RS X- " } ,
{ DS4KeyCodes : : RSXPos , " RS X+ " } ,
{ DS4KeyCodes : : RSYPos , " RS Y+ " } ,
{ DS4KeyCodes : : RSYNeg , " RS Y- " }
} ;
2017-12-23 22:25:51 +01:00
init_configs ( ) ;
2017-11-27 22:31:15 +01:00
// Define border values
thumb_max = 255 ;
trigger_min = 0 ;
trigger_max = 255 ;
2017-12-23 22:25:51 +01:00
// set capabilities
b_has_config = true ;
b_has_rumble = true ;
2022-08-13 09:56:04 +02:00
b_has_motion = true ;
2017-12-23 22:25:51 +01:00
b_has_deadzones = true ;
2019-05-09 21:31:43 +02:00
b_has_led = true ;
2021-02-28 04:50:23 +01:00
b_has_rgb = true ;
2020-03-05 19:02:28 +01:00
b_has_battery = true ;
2017-12-23 22:25:51 +01:00
2018-12-20 12:52:30 +01:00
m_name_string = " DS4 Pad # " ;
m_max_devices = CELL_PAD_MAX_PORT_NUM ;
2018-01-17 02:23:50 +01:00
2017-12-23 22:25:51 +01:00
m_trigger_threshold = trigger_max / 2 ;
m_thumb_threshold = thumb_max / 2 ;
}
2021-08-10 21:45:26 +02:00
void ds4_pad_handler : : init_config ( cfg_pad * cfg )
2017-12-23 22:25:51 +01:00
{
2020-11-26 00:06:03 +01:00
if ( ! cfg ) return ;
2017-11-27 22:31:15 +01:00
// Set default button mapping
2022-09-19 14:57:51 +02:00
cfg - > ls_left . def = : : at32 ( button_list , DS4KeyCodes : : LSXNeg ) ;
cfg - > ls_down . def = : : at32 ( button_list , DS4KeyCodes : : LSYNeg ) ;
cfg - > ls_right . def = : : at32 ( button_list , DS4KeyCodes : : LSXPos ) ;
cfg - > ls_up . def = : : at32 ( button_list , DS4KeyCodes : : LSYPos ) ;
cfg - > rs_left . def = : : at32 ( button_list , DS4KeyCodes : : RSXNeg ) ;
cfg - > rs_down . def = : : at32 ( button_list , DS4KeyCodes : : RSYNeg ) ;
cfg - > rs_right . def = : : at32 ( button_list , DS4KeyCodes : : RSXPos ) ;
cfg - > rs_up . def = : : at32 ( button_list , DS4KeyCodes : : RSYPos ) ;
cfg - > start . def = : : at32 ( button_list , DS4KeyCodes : : Options ) ;
cfg - > select . def = : : at32 ( button_list , DS4KeyCodes : : Share ) ;
cfg - > ps . def = : : at32 ( button_list , DS4KeyCodes : : PSButton ) ;
cfg - > square . def = : : at32 ( button_list , DS4KeyCodes : : Square ) ;
cfg - > cross . def = : : at32 ( button_list , DS4KeyCodes : : Cross ) ;
cfg - > circle . def = : : at32 ( button_list , DS4KeyCodes : : Circle ) ;
cfg - > triangle . def = : : at32 ( button_list , DS4KeyCodes : : Triangle ) ;
cfg - > left . def = : : at32 ( button_list , DS4KeyCodes : : Left ) ;
cfg - > down . def = : : at32 ( button_list , DS4KeyCodes : : Down ) ;
cfg - > right . def = : : at32 ( button_list , DS4KeyCodes : : Right ) ;
cfg - > up . def = : : at32 ( button_list , DS4KeyCodes : : Up ) ;
cfg - > r1 . def = : : at32 ( button_list , DS4KeyCodes : : R1 ) ;
cfg - > r2 . def = : : at32 ( button_list , DS4KeyCodes : : R2 ) ;
cfg - > r3 . def = : : at32 ( button_list , DS4KeyCodes : : R3 ) ;
cfg - > l1 . def = : : at32 ( button_list , DS4KeyCodes : : L1 ) ;
cfg - > l2 . def = : : at32 ( button_list , DS4KeyCodes : : L2 ) ;
cfg - > l3 . def = : : at32 ( button_list , DS4KeyCodes : : L3 ) ;
cfg - > pressure_intensity_button . def = : : at32 ( button_list , DS4KeyCodes : : None ) ;
2021-08-06 02:08:18 +02:00
2017-11-27 22:31:15 +01:00
// Set default misc variables
2017-12-23 22:25:51 +01:00
cfg - > lstickdeadzone . def = 40 ; // between 0 and 255
cfg - > rstickdeadzone . def = 40 ; // between 0 and 255
cfg - > ltriggerthreshold . def = 0 ; // between 0 and 255
cfg - > rtriggerthreshold . def = 0 ; // between 0 and 255
2020-07-12 19:30:45 +02:00
cfg - > lpadsquircling . def = 8000 ;
cfg - > rpadsquircling . def = 8000 ;
2017-11-27 22:31:15 +01:00
2020-03-05 19:02:28 +01:00
// Set default color value
2017-12-23 22:25:51 +01:00
cfg - > colorR . def = 0 ;
cfg - > colorG . def = 0 ;
cfg - > colorB . def = 20 ;
2017-11-27 22:31:15 +01:00
2020-03-05 19:02:28 +01:00
// Set default LED options
cfg - > led_battery_indicator . def = false ;
cfg - > led_battery_indicator_brightness . def = 10 ;
cfg - > led_low_battery_blink . def = true ;
2017-11-27 22:31:15 +01:00
// apply defaults
2017-12-23 22:25:51 +01:00
cfg - > from_default ( ) ;
2017-04-29 03:02:28 +02:00
}
2020-03-05 19:02:28 +01:00
u32 ds4_pad_handler : : get_battery_level ( const std : : string & padId )
{
2021-04-07 23:05:18 +02:00
const std : : shared_ptr < DS4Device > device = get_hid_device ( padId ) ;
2020-03-05 19:02:28 +01:00
if ( device = = nullptr | | device - > hidDevice = = nullptr )
{
return 0 ;
}
2021-02-13 01:25:39 +01:00
return std : : min < u32 > ( device - > battery_level * 10 , 100 ) ;
2020-03-05 19:02:28 +01:00
}
2022-10-21 22:35:31 +02:00
void ds4_pad_handler : : SetPadData ( const std : : string & padId , u8 player_id , u8 large_motor , u8 small_motor , s32 r , s32 g , s32 b , bool /*player_led*/ , bool battery_led , u32 battery_led_brightness )
2017-11-27 22:31:15 +01:00
{
2021-02-11 22:13:21 +01:00
std : : shared_ptr < DS4Device > device = get_hid_device ( padId ) ;
2023-01-17 00:45:09 +01:00
if ( ! device | | ! device - > hidDevice )
2017-11-27 22:31:15 +01:00
return ;
2017-04-29 03:02:28 +02:00
2017-11-30 00:43:52 +01:00
// Set the device's motor speeds to our requested values 0-255
2022-10-21 22:35:31 +02:00
device - > large_motor = large_motor ;
device - > small_motor = small_motor ;
2021-08-09 23:41:49 +02:00
device - > player_id = player_id ;
2017-08-15 14:03:07 +02:00
2017-12-23 22:25:51 +01:00
int index = 0 ;
2020-02-19 18:03:59 +01:00
for ( uint i = 0 ; i < MAX_GAMEPADS ; i + + )
2017-12-23 22:25:51 +01:00
{
2021-02-08 23:02:18 +01:00
if ( g_cfg_input . player [ i ] - > handler = = m_type )
2017-12-23 22:25:51 +01:00
{
if ( g_cfg_input . player [ i ] - > device . to_string ( ) = = padId )
{
2021-08-10 21:45:26 +02:00
m_pad_configs [ index ] . from_string ( g_cfg_input . player [ i ] - > config . to_string ( ) ) ;
2017-12-23 22:25:51 +01:00
device - > config = & m_pad_configs [ index ] ;
break ;
}
index + + ;
}
}
2021-02-28 04:32:08 +01:00
ensure ( device - > config ) ;
2019-05-26 09:43:04 +02:00
// Set new LED color
2020-03-05 19:02:28 +01:00
if ( battery_led )
{
2021-02-13 01:25:39 +01:00
const u32 combined_color = get_battery_color ( device - > battery_level , battery_led_brightness ) ;
2020-03-05 19:02:28 +01:00
device - > config - > colorR . set ( combined_color > > 8 ) ;
device - > config - > colorG . set ( combined_color & 0xff ) ;
device - > config - > colorB . set ( 0 ) ;
}
else if ( r > = 0 & & g > = 0 & & b > = 0 & & r < = 255 & & g < = 255 & & b < = 255 )
2019-05-09 21:31:43 +02:00
{
2019-05-26 09:43:04 +02:00
device - > config - > colorR . set ( r ) ;
device - > config - > colorG . set ( g ) ;
device - > config - > colorB . set ( b ) ;
2019-05-09 21:31:43 +02:00
}
2019-05-26 09:43:04 +02:00
// Start/Stop the engines :)
2021-02-11 22:13:21 +01:00
send_output_report ( device . get ( ) ) ;
2017-11-30 00:43:52 +01:00
}
2017-11-27 22:31:15 +01:00
2019-09-20 16:28:55 +02:00
std : : unordered_map < u64 , u16 > ds4_pad_handler : : get_button_values ( const std : : shared_ptr < PadDevice > & device )
2017-04-29 03:02:28 +02:00
{
2019-09-20 16:28:55 +02:00
std : : unordered_map < u64 , u16 > keyBuffer ;
2021-02-11 22:13:21 +01:00
DS4Device * ds4_dev = static_cast < DS4Device * > ( device . get ( ) ) ;
2019-09-20 16:28:55 +02:00
if ( ! ds4_dev )
return keyBuffer ;
2017-11-27 22:31:15 +01:00
2019-09-20 16:28:55 +02:00
auto buf = ds4_dev - > padData ;
2017-04-29 03:02:28 +02:00
2017-11-27 22:31:15 +01:00
// Left Stick X Axis
keyBuffer [ DS4KeyCodes : : LSXNeg ] = Clamp0To255 ( ( 127.5f - buf [ 1 ] ) * 2.0f ) ;
keyBuffer [ DS4KeyCodes : : LSXPos ] = Clamp0To255 ( ( buf [ 1 ] - 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 ) ;
// Right Stick X Axis
keyBuffer [ DS4KeyCodes : : RSXNeg ] = Clamp0To255 ( ( 127.5f - buf [ 3 ] ) * 2.0f ) ;
keyBuffer [ DS4KeyCodes : : RSXPos ] = Clamp0To255 ( ( buf [ 3 ] - 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 ) ;
// bleh, dpad in buffer is stored in a different state
2021-04-07 23:05:18 +02:00
const u8 dpadState = buf [ 5 ] & 0xf ;
2017-11-27 22:31:15 +01:00
switch ( dpadState )
{
case 0x08 : // none pressed
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
case 0x07 : // NW...left and up
keyBuffer [ DS4KeyCodes : : Up ] = 255 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 255 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
case 0x06 : // W..left
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 255 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
case 0x05 : // SW..left down
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 255 ;
keyBuffer [ DS4KeyCodes : : Left ] = 255 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
case 0x04 : // S..down
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 255 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
case 0x03 : // SE..down and right
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 255 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 255 ;
break ;
case 0x02 : // E... right
keyBuffer [ DS4KeyCodes : : Up ] = 0 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 255 ;
break ;
case 0x01 : // NE.. up right
keyBuffer [ DS4KeyCodes : : Up ] = 255 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 255 ;
break ;
case 0x00 : // n.. up
keyBuffer [ DS4KeyCodes : : Up ] = 255 ;
keyBuffer [ DS4KeyCodes : : Down ] = 0 ;
keyBuffer [ DS4KeyCodes : : Left ] = 0 ;
keyBuffer [ DS4KeyCodes : : Right ] = 0 ;
break ;
default :
fmt : : throw_exception ( " ds4 dpad state encountered unexpected input " ) ;
2017-08-15 14:03:07 +02:00
}
2017-11-27 22:31:15 +01:00
// 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 ;
// 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 ;
// PS Button, Touch Button
keyBuffer [ DS4KeyCodes : : PSButton ] = ( ( buf [ 7 ] & ( 1 < < 0 ) ) ! = 0 ) ? 255 : 0 ;
keyBuffer [ DS4KeyCodes : : TouchPad ] = ( ( buf [ 7 ] & ( 1 < < 1 ) ) ! = 0 ) ? 255 : 0 ;
// L2, R2
keyBuffer [ DS4KeyCodes : : L2 ] = buf [ 8 ] ;
keyBuffer [ DS4KeyCodes : : R2 ] = buf [ 9 ] ;
return keyBuffer ;
2017-04-29 03:02:28 +02:00
}
2020-12-14 14:33:43 +01:00
pad_preview_values ds4_pad_handler : : get_preview_values ( const std : : unordered_map < u64 , u16 > & data )
2017-11-27 22:31:15 +01:00
{
2020-12-14 14:33:43 +01:00
return {
2022-09-19 14:57:51 +02:00
: : at32 ( data , L2 ) ,
: : at32 ( data , R2 ) ,
: : at32 ( data , LSXPos ) - : : at32 ( data , LSXNeg ) ,
: : at32 ( data , LSYPos ) - : : at32 ( data , LSYNeg ) ,
: : at32 ( data , RSXPos ) - : : at32 ( data , RSXNeg ) ,
: : at32 ( data , RSYPos ) - : : at32 ( data , RSYNeg )
2020-12-14 14:33:43 +01:00
} ;
2017-11-27 22:31:15 +01:00
}
2021-04-07 23:05:18 +02:00
bool ds4_pad_handler : : GetCalibrationData ( DS4Device * ds4Dev ) const
2017-05-19 05:06:31 +02:00
{
2020-10-25 20:59:03 +01:00
if ( ! ds4Dev | | ! ds4Dev - > hidDevice )
{
ds4_log . error ( " GetCalibrationData called with null device " ) ;
return false ;
}
2022-06-05 14:35:58 +02:00
std : : array < u8 , 64 > buf { } ;
2021-02-13 01:25:39 +01:00
if ( ds4Dev - > bt_controller )
2017-05-19 05:06:31 +02:00
{
2017-11-27 22:31:15 +01:00
for ( int tries = 0 ; tries < 3 ; + + tries )
{
2022-06-05 14:35:58 +02:00
buf = { } ;
2017-05-19 05:06:31 +02:00
buf [ 0 ] = 0x05 ;
2020-10-25 20:59:03 +01:00
2022-06-05 15:20:38 +02:00
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 )
2020-10-25 20:59:03 +01:00
{
2021-10-01 01:47:14 +02:00
ds4_log . error ( " GetCalibrationData: hid_get_feature_report 0x05 for bluetooth controller failed! result=%d, error=%s " , res , hid_error ( ds4Dev - > hidDevice ) ) ;
2017-05-19 05:06:31 +02:00
return false ;
2020-10-25 20:59:03 +01:00
}
2017-05-19 05:06:31 +02:00
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 ) ;
2019-12-03 22:24:37 +01:00
const u32 crcReported = read_u32 ( & buf [ DS4_FEATURE_REPORT_0x05_SIZE - 4 ] ) ;
2020-10-25 20:59:03 +01:00
if ( crcCalc = = crcReported )
break ;
ds4_log . warning ( " Calibration CRC check failed! Will retry up to 3 times. Received 0x%x, Expected 0x%x " , crcReported , crcCalc ) ;
2017-05-19 05:06:31 +02:00
if ( tries = = 2 )
2020-10-25 20:59:03 +01:00
{
ds4_log . error ( " Calibration CRC check failed too many times! " ) ;
2017-05-19 05:06:31 +02:00
return false ;
2020-10-25 20:59:03 +01:00
}
2017-05-19 05:06:31 +02:00
}
}
else
{
buf [ 0 ] = 0x02 ;
2022-06-05 15:20:38 +02:00
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 )
2017-09-20 20:16:09 +02:00
{
2021-10-01 01:47:14 +02:00
ds4_log . error ( " GetCalibrationData: hid_get_feature_report 0x02 for wired controller failed! result=%d, error=%s " , res , hid_error ( ds4Dev - > hidDevice ) ) ;
2017-05-19 05:06:31 +02:00
return false ;
2017-09-20 20:16:09 +02:00
}
2017-05-19 05:06:31 +02:00
}
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : PITCH ] . bias = read_s16 ( & buf [ 1 ] ) ;
ds4Dev - > calib_data [ CalibIndex : : YAW ] . bias = read_s16 ( & buf [ 3 ] ) ;
ds4Dev - > calib_data [ CalibIndex : : ROLL ] . bias = read_s16 ( & buf [ 5 ] ) ;
2017-05-19 05:06:31 +02:00
s16 pitchPlus , pitchNeg , rollPlus , rollNeg , yawPlus , yawNeg ;
2019-12-03 22:24:37 +01:00
// Check for calibration data format
// It's going to be either alternating +/- or +++---
if ( read_s16 ( & buf [ 9 ] ) < 0 & & read_s16 ( & buf [ 7 ] ) > 0 )
2017-05-19 05:06:31 +02:00
{
2019-12-03 22:24:37 +01:00
// Wired mode for OEM controllers
pitchPlus = read_s16 ( & buf [ 7 ] ) ;
pitchNeg = read_s16 ( & buf [ 9 ] ) ;
yawPlus = read_s16 ( & buf [ 11 ] ) ;
yawNeg = read_s16 ( & buf [ 13 ] ) ;
rollPlus = read_s16 ( & buf [ 15 ] ) ;
rollNeg = read_s16 ( & buf [ 17 ] ) ;
2017-05-19 05:06:31 +02:00
}
else
{
2019-12-03 22:24:37 +01:00
// Bluetooth mode and wired mode for some 3rd party controllers
pitchPlus = read_s16 ( & buf [ 7 ] ) ;
yawPlus = read_s16 ( & buf [ 9 ] ) ;
rollPlus = read_s16 ( & buf [ 11 ] ) ;
pitchNeg = read_s16 ( & buf [ 13 ] ) ;
yawNeg = read_s16 ( & buf [ 15 ] ) ;
rollNeg = read_s16 ( & buf [ 17 ] ) ;
}
// Confirm correctness. Need confirmation with dongle with no active controller
if ( pitchPlus < = 0 | | yawPlus < = 0 | | rollPlus < = 0 | |
pitchNeg > = 0 | | yawNeg > = 0 | | rollNeg > = 0 )
{
2020-10-25 20:59:03 +01:00
ds4_log . error ( " GetCalibrationData: calibration data check failed! pitchPlus=%d, pitchNeg=%d, rollPlus=%d, rollNeg=%d, yawPlus=%d, yawNeg=%d " , pitchPlus , pitchNeg , rollPlus , rollNeg , yawPlus , yawNeg ) ;
2019-12-03 22:24:37 +01:00
return false ;
2017-05-19 05:06:31 +02:00
}
2019-12-03 22:24:37 +01:00
const s32 gyroSpeedScale = read_s16 ( & buf [ 19 ] ) + read_s16 ( & buf [ 21 ] ) ;
2017-05-19 05:06:31 +02:00
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : PITCH ] . sens_numer = gyroSpeedScale * DS4_GYRO_RES_PER_DEG_S ;
ds4Dev - > calib_data [ CalibIndex : : PITCH ] . sens_denom = pitchPlus - pitchNeg ;
2017-05-19 05:06:31 +02:00
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : YAW ] . sens_numer = gyroSpeedScale * DS4_GYRO_RES_PER_DEG_S ;
ds4Dev - > calib_data [ CalibIndex : : YAW ] . sens_denom = yawPlus - yawNeg ;
2017-05-19 05:06:31 +02:00
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : ROLL ] . sens_numer = gyroSpeedScale * DS4_GYRO_RES_PER_DEG_S ;
ds4Dev - > calib_data [ CalibIndex : : ROLL ] . sens_denom = rollPlus - rollNeg ;
2017-05-19 05:06:31 +02:00
2019-12-03 22:24:37 +01:00
const s16 accelXPlus = read_s16 ( & buf [ 23 ] ) ;
const s16 accelXNeg = read_s16 ( & buf [ 25 ] ) ;
const s16 accelYPlus = read_s16 ( & buf [ 27 ] ) ;
const s16 accelYNeg = read_s16 ( & buf [ 29 ] ) ;
const s16 accelZPlus = read_s16 ( & buf [ 31 ] ) ;
const s16 accelZNeg = read_s16 ( & buf [ 33 ] ) ;
2017-05-19 05:06:31 +02:00
const s32 accelXRange = accelXPlus - accelXNeg ;
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : X ] . bias = accelXPlus - accelXRange / 2 ;
ds4Dev - > calib_data [ CalibIndex : : X ] . sens_numer = 2 * DS4_ACC_RES_PER_G ;
ds4Dev - > calib_data [ CalibIndex : : X ] . sens_denom = accelXRange ;
2017-05-19 05:06:31 +02:00
const s32 accelYRange = accelYPlus - accelYNeg ;
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : Y ] . bias = accelYPlus - accelYRange / 2 ;
ds4Dev - > calib_data [ CalibIndex : : Y ] . sens_numer = 2 * DS4_ACC_RES_PER_G ;
ds4Dev - > calib_data [ CalibIndex : : Y ] . sens_denom = accelYRange ;
2017-05-19 05:06:31 +02:00
const s32 accelZRange = accelZPlus - accelZNeg ;
2021-02-13 01:25:39 +01:00
ds4Dev - > calib_data [ CalibIndex : : Z ] . bias = accelZPlus - accelZRange / 2 ;
ds4Dev - > calib_data [ CalibIndex : : Z ] . sens_numer = 2 * DS4_ACC_RES_PER_G ;
ds4Dev - > calib_data [ CalibIndex : : Z ] . sens_denom = accelZRange ;
2017-05-19 05:06:31 +02:00
2017-09-20 20:16:09 +02:00
// Make sure data 'looks' valid, dongle will report invalid calibration data with no controller connected
2021-02-13 01:25:39 +01:00
for ( const auto & data : ds4Dev - > calib_data )
2017-09-20 20:16:09 +02:00
{
2021-02-11 22:13:21 +01:00
if ( data . sens_denom = = 0 )
2020-10-25 20:59:03 +01:00
{
2021-02-13 01:25:39 +01:00
ds4_log . error ( " GetCalibrationData: Failure: sens_denom == 0 " ) ;
2017-09-20 20:16:09 +02:00
return false ;
2020-10-25 20:59:03 +01:00
}
2017-09-20 20:16:09 +02:00
}
2017-05-19 05:06:31 +02:00
return true ;
}
2021-02-11 22:13:21 +01:00
void ds4_pad_handler : : check_add_device ( hid_device * hidDevice , std : : string_view path , std : : wstring_view wide_serial )
2017-05-19 05:06:31 +02:00
{
2021-02-11 22:13:21 +01:00
if ( ! hidDevice )
{
return ;
}
2021-02-11 23:27:33 +01:00
DS4Device * device = nullptr ;
2020-11-01 01:11:16 +01:00
2021-02-11 22:13:21 +01:00
for ( auto & controller : m_controllers )
2020-11-01 01:11:16 +01:00
{
2021-02-11 23:27:33 +01:00
ensure ( controller . second ) ;
if ( ! controller . second - > hidDevice )
2020-11-01 01:11:16 +01:00
{
2021-02-11 23:27:33 +01:00
device = controller . second . get ( ) ;
2020-11-01 01:11:16 +01:00
break ;
}
}
2021-02-11 23:27:33 +01:00
if ( ! device )
2020-11-01 01:11:16 +01:00
{
return ;
}
2020-02-26 21:13:54 +01:00
std : : string serial ;
2021-02-11 22:13:21 +01:00
2017-05-19 05:06:31 +02:00
// There isnt a nice 'portable' way with hidapi to detect bt vs wired as the pid/vid's are the same
2021-10-01 01:47:14 +02:00
// Let's try getting 0x81 feature report, which should return the mac address on wired, and should an error on bluetooth
2017-05-19 05:06:31 +02:00
std : : array < u8 , 64 > buf { } ;
buf [ 0 ] = 0x81 ;
2021-10-01 01:47:14 +02:00
int res = hid_get_feature_report ( hidDevice , buf . data ( ) , DS4_FEATURE_REPORT_0x81_SIZE ) ;
if ( res > 0 )
2017-05-19 05:06:31 +02:00
{
2022-06-05 15:20:38 +02:00
if ( res ! = DS4_FEATURE_REPORT_0x81_SIZE | | buf [ 0 ] ! = 0x81 )
2019-11-27 11:39:38 +01:00
{
// Controller may not be genuine. These controllers do not have feature 0x81 implemented and calibration data is in bluetooth format even in USB mode!
2022-06-05 15:20:38 +02:00
ds4_log . warning ( " check_add_device: DS4 controller may not be genuine. Workaround enabled. (result=%d, buf[0]=0x%x) " , res , buf [ 0 ] ) ;
2019-11-27 11:39:38 +01:00
// Read feature report 0x12 instead which is what the console uses.
2022-06-05 14:35:58 +02:00
buf = { } ;
2019-11-27 11:39:38 +01:00
buf [ 0 ] = 0x12 ;
2022-06-05 15:20:38 +02:00
if ( res = hid_get_feature_report ( hidDevice , buf . data ( ) , DS4_FEATURE_REPORT_0x12_SIZE ) ; res ! = DS4_FEATURE_REPORT_0x12_SIZE | | buf [ 0 ] ! = 0x12 )
2020-10-25 20:59:03 +01:00
{
2022-06-05 15:20:38 +02:00
ds4_log . error ( " check_add_device: hid_get_feature_report 0x12 failed! result=%d, buf[0]=0x%x, error=%s " , res , buf [ 0 ] , hid_error ( hidDevice ) ) ;
2020-10-25 20:59:03 +01:00
}
2019-11-27 11:39:38 +01:00
}
2017-05-19 05:06:31 +02:00
serial = fmt : : format ( " %x%x%x%x%x%x " , buf [ 6 ] , buf [ 5 ] , buf [ 4 ] , buf [ 3 ] , buf [ 2 ] , buf [ 1 ] ) ;
}
else
{
2022-06-05 15:20:38 +02:00
ds4_log . warning ( " check_add_device: DS4 Bluetooth controller detected. (hid_get_feature_report 0x81 failed, result=%d, buf[0]=0x%x, error=%s) " , res , buf [ 0 ] , hid_error ( hidDevice ) ) ;
2021-02-13 01:25:39 +01:00
device - > bt_controller = true ;
2020-11-01 01:11:16 +01:00
for ( wchar_t ch : wide_serial )
2020-03-10 16:43:50 +01:00
serial + = static_cast < uchar > ( ch ) ;
2017-05-19 05:06:31 +02:00
}
2021-02-11 23:27:33 +01:00
device - > hidDevice = hidDevice ;
if ( ! GetCalibrationData ( device ) )
2017-05-19 05:06:31 +02:00
{
2021-02-11 22:13:21 +01:00
ds4_log . error ( " check_add_device: GetCalibrationData failed! " ) ;
2020-10-25 20:59:03 +01:00
hid_close ( hidDevice ) ;
2021-02-11 23:27:33 +01:00
device - > hidDevice = nullptr ;
2020-10-25 20:59:03 +01:00
return ;
}
2021-10-15 00:12:15 +02:00
u32 hw_version { } ;
u32 fw_version { } ;
2022-06-05 14:35:58 +02:00
buf = { } ;
2021-10-15 00:12:15 +02:00
buf [ 0 ] = 0xA3 ;
res = hid_get_feature_report ( hidDevice , buf . data ( ) , DS4_FEATURE_REPORT_0xA3_SIZE ) ;
2022-06-05 15:20:38 +02:00
if ( res ! = DS4_FEATURE_REPORT_0xA3_SIZE | | buf [ 0 ] ! = 0xA3 )
2021-10-15 00:12:15 +02:00
{
2022-06-05 15:20:38 +02:00
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 ) ) ;
2021-10-15 00:12:15 +02:00
}
else
{
hw_version = read_u32 ( & buf [ 35 ] ) ;
fw_version = read_u32 ( & buf [ 41 ] ) ;
}
2020-10-25 20:59:03 +01:00
if ( hid_set_nonblocking ( hidDevice , 1 ) = = - 1 )
{
2021-02-11 22:13:21 +01:00
ds4_log . error ( " check_add_device: hid_set_nonblocking failed! Reason: %s " , hid_error ( hidDevice ) ) ;
2017-05-19 05:06:31 +02:00
hid_close ( hidDevice ) ;
2021-02-11 23:27:33 +01:00
device - > hidDevice = nullptr ;
2017-05-19 05:06:31 +02:00
return ;
}
2021-02-13 01:25:39 +01:00
device - > has_calib_data = true ;
device - > path = path ;
2017-05-19 05:06:31 +02:00
2021-02-11 23:27:33 +01:00
send_output_report ( device ) ;
2021-02-13 01:25:39 +01:00
2021-10-15 00:12:15 +02:00
ds4_log . notice ( " Added device: bluetooth=%d, serial='%s', hw_version: 0x%x, fw_version: 0x%x, path='%s' " , device - > bt_controller , serial , hw_version , fw_version , device - > path ) ;
2017-05-19 05:06:31 +02:00
}
2017-08-15 14:03:07 +02:00
ds4_pad_handler : : ~ ds4_pad_handler ( )
2017-04-29 03:02:28 +02:00
{
2021-02-11 22:13:21 +01:00
for ( auto & controller : m_controllers )
2017-04-29 03:02:28 +02:00
{
2020-11-01 01:11:16 +01:00
if ( controller . second & & controller . second - > hidDevice )
2017-11-27 22:31:15 +01:00
{
// Disable blinking and vibration
2021-02-11 23:27:33 +01:00
controller . second - > small_motor = 0 ;
controller . second - > large_motor = 0 ;
2017-11-27 22:31:15 +01:00
controller . second - > led_delay_on = 0 ;
controller . second - > led_delay_off = 0 ;
2021-02-11 22:13:21 +01:00
send_output_report ( controller . second . get ( ) ) ;
2017-11-27 22:31:15 +01:00
}
2017-04-29 03:02:28 +02:00
}
}
2021-02-11 22:13:21 +01:00
int ds4_pad_handler : : send_output_report ( DS4Device * device )
2017-05-19 05:06:31 +02:00
{
2020-11-01 01:11:16 +01:00
if ( ! device | | ! device - > hidDevice )
2019-09-20 16:28:55 +02:00
return - 2 ;
2021-04-07 23:05:18 +02:00
const auto config = device - > config ;
2021-02-09 00:31:07 +01:00
if ( config = = nullptr )
2017-12-23 22:25:51 +01:00
return - 2 ; // hid_write and hid_write_control return -1 on error
2017-05-19 05:06:31 +02:00
std : : array < u8 , 78 > outputBuf { 0 } ;
// write rumble state
2021-02-13 01:25:39 +01:00
if ( device - > bt_controller )
2017-05-19 05:06:31 +02:00
{
outputBuf [ 0 ] = 0x11 ;
outputBuf [ 1 ] = 0xC4 ;
outputBuf [ 3 ] = 0x07 ;
2021-02-11 23:27:33 +01:00
outputBuf [ 6 ] = device - > small_motor ;
outputBuf [ 7 ] = device - > large_motor ;
2021-02-09 00:31:07 +01:00
outputBuf [ 8 ] = config - > colorR ; // red
outputBuf [ 9 ] = config - > colorG ; // green
outputBuf [ 10 ] = config - > colorB ; // blue
2017-11-27 22:31:15 +01:00
// 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
2017-12-07 18:53:03 +01:00
outputBuf [ 11 ] = device - > led_delay_on ;
outputBuf [ 12 ] = device - > led_delay_off ;
2017-05-19 05:06:31 +02:00
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 ) ;
outputBuf [ 74 ] = ( crcCalc > > 0 ) & 0xFF ;
outputBuf [ 75 ] = ( crcCalc > > 8 ) & 0xFF ;
outputBuf [ 76 ] = ( crcCalc > > 16 ) & 0xFF ;
outputBuf [ 77 ] = ( crcCalc > > 24 ) & 0xFF ;
2017-11-27 22:31:15 +01:00
return hid_write_control ( device - > hidDevice , outputBuf . data ( ) , DS4_OUTPUT_REPORT_0x11_SIZE ) ;
2017-05-19 05:06:31 +02:00
}
else
{
outputBuf [ 0 ] = 0x05 ;
outputBuf [ 1 ] = 0x07 ;
2021-02-11 23:27:33 +01:00
outputBuf [ 4 ] = device - > small_motor ;
outputBuf [ 5 ] = device - > large_motor ;
2021-02-09 00:31:07 +01:00
outputBuf [ 6 ] = config - > colorR ; // red
outputBuf [ 7 ] = config - > colorG ; // green
outputBuf [ 8 ] = config - > colorB ; // blue
2017-11-27 22:31:15 +01:00
outputBuf [ 9 ] = device - > led_delay_on ;
outputBuf [ 10 ] = device - > led_delay_off ;
2017-05-19 05:06:31 +02:00
2017-11-27 22:31:15 +01:00
return hid_write ( device - > hidDevice , outputBuf . data ( ) , DS4_OUTPUT_REPORT_0x05_SIZE ) ;
2017-05-19 05:06:31 +02:00
}
}
2021-02-11 23:27:33 +01:00
ds4_pad_handler : : DataStatus ds4_pad_handler : : get_data ( DS4Device * device )
2020-11-01 01:11:16 +01:00
{
2021-02-11 22:13:21 +01:00
if ( ! device | | ! device - > hidDevice )
return DataStatus : : ReadError ;
2019-09-20 16:28:55 +02:00
2017-11-27 22:31:15 +01:00
std : : array < u8 , 78 > buf { } ;
2017-08-15 14:03:07 +02:00
2022-06-05 15:20:38 +02:00
const int res = hid_read ( device - > hidDevice , buf . data ( ) , device - > bt_controller ? DS4_INPUT_REPORT_0x11_SIZE : 64 ) ;
2017-11-27 22:31:15 +01:00
if ( res = = - 1 )
{
// looks like controller disconnected or read error
2021-02-11 22:13:21 +01:00
return DataStatus : : ReadError ;
2017-11-27 22:31:15 +01:00
}
2017-04-29 03:02:28 +02:00
2017-11-27 22:31:15 +01:00
// no data? keep going
if ( res = = 0 )
2021-02-11 22:13:21 +01:00
return DataStatus : : NoNewData ;
2017-09-20 20:16:09 +02:00
2017-11-27 22:31:15 +01:00
// bt controller sends this until 0x02 feature report is sent back (happens on controller init/restart)
2021-02-13 01:25:39 +01:00
if ( device - > bt_controller & & buf [ 0 ] = = 0x1 )
2017-11-27 22:31:15 +01:00
{
// tells controller to send 0x11 reports
std : : array < u8 , 64 > buf_error { } ;
buf_error [ 0 ] = 0x2 ;
2022-06-05 15:20:38 +02:00
if ( int res = hid_get_feature_report ( device - > hidDevice , buf_error . data ( ) , buf_error . size ( ) ) ; res ! = static_cast < int > ( buf_error . size ( ) ) | | buf_error [ 0 ] ! = 0x2 )
2020-10-25 20:59:03 +01:00
{
2022-06-05 15:20:38 +02:00
ds4_log . error ( " GetRawData: hid_get_feature_report 0x2 failed! result=%d, buf[0]=0x%x, error=%s " , res , buf [ 0 ] , hid_error ( device - > hidDevice ) ) ;
2020-10-25 20:59:03 +01:00
}
2021-02-11 22:13:21 +01:00
return DataStatus : : NoNewData ;
2017-11-27 22:31:15 +01:00
}
2021-04-07 23:05:18 +02:00
int offset ;
2017-11-27 22:31:15 +01:00
// check report and set offset
2022-06-05 15:20:38 +02:00
if ( device - > bt_controller & & buf [ 0 ] = = 0x11 & & res = = DS4_INPUT_REPORT_0x11_SIZE )
2017-11-27 22:31:15 +01:00
{
offset = 2 ;
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 ) ;
2019-12-03 22:24:37 +01:00
const u32 crcReported = read_u32 ( & buf [ DS4_INPUT_REPORT_0x11_SIZE - 4 ] ) ;
2017-11-27 22:31:15 +01:00
if ( crcCalc ! = crcReported )
{
2020-02-01 09:23:50 +01:00
ds4_log . warning ( " Data packet CRC check failed, ignoring! Received 0x%x, Expected 0x%x " , crcReported , crcCalc ) ;
2021-02-11 22:13:21 +01:00
return DataStatus : : NoNewData ;
2017-09-20 20:16:09 +02:00
}
2017-11-27 22:31:15 +01:00
}
2021-02-13 01:25:39 +01:00
else if ( ! device - > bt_controller & & buf [ 0 ] = = 0x01 & & res = = 64 )
2017-11-27 22:31:15 +01:00
{
// Ds4 Dongle uses this bit to actually report whether a controller is connected
2020-03-05 19:02:28 +01:00
const bool connected = ( buf [ 31 ] & 0x04 ) ? false : true ;
2021-02-13 01:25:39 +01:00
if ( connected & & ! device - > has_calib_data )
device - > has_calib_data = GetCalibrationData ( device ) ;
2017-11-27 22:31:15 +01:00
offset = 0 ;
}
else
2021-02-11 22:13:21 +01:00
return DataStatus : : NoNewData ;
2017-11-27 22:31:15 +01:00
2020-03-05 19:02:28 +01:00
const int battery_offset = offset + DS4_INPUT_REPORT_BATTERY_OFFSET ;
2021-02-13 01:25:39 +01:00
device - > cable_state = ( buf [ battery_offset ] > > 4 ) & 0x01 ;
2021-02-28 04:32:08 +01:00
device - > battery_level = buf [ battery_offset ] & 0x0F ; // 0 - 9 while unplugged, 0 - 10 while plugged in, 11 charge complete
2017-11-27 22:31:15 +01:00
2021-02-13 01:25:39 +01:00
if ( device - > has_calib_data )
2017-11-27 22:31:15 +01:00
{
int calibOffset = offset + DS4_INPUT_REPORT_GYRO_X_OFFSET ;
2021-02-11 22:13:21 +01:00
for ( int i = 0 ; i < CalibIndex : : COUNT ; + + i )
2017-08-15 14:03:07 +02:00
{
2019-12-03 22:24:37 +01:00
const s16 rawValue = read_s16 ( & buf [ calibOffset ] ) ;
2021-02-13 01:25:39 +01:00
const s16 calValue = apply_calibration ( rawValue , device - > calib_data [ i ] ) ;
2019-12-04 21:56:19 +01:00
buf [ calibOffset + + ] = ( static_cast < u16 > ( calValue ) > > 0 ) & 0xFF ;
buf [ calibOffset + + ] = ( static_cast < u16 > ( calValue ) > > 8 ) & 0xFF ;
2017-08-15 14:03:07 +02:00
}
2017-04-29 03:02:28 +02:00
}
2017-11-27 22:31:15 +01:00
memcpy ( device - > padData . data ( ) , & buf [ offset ] , 64 ) ;
2017-08-10 23:41:13 +02:00
2021-02-11 22:13:21 +01:00
return DataStatus : : NewData ;
2019-09-20 16:28:55 +02:00
}
2022-10-15 12:41:21 +02:00
bool ds4_pad_handler : : get_is_left_trigger ( const std : : shared_ptr < PadDevice > & /*device*/ , u64 keyCode )
2019-09-20 16:28:55 +02:00
{
return keyCode = = DS4KeyCodes : : L2 ;
}
2022-10-15 12:41:21 +02:00
bool ds4_pad_handler : : get_is_right_trigger ( const std : : shared_ptr < PadDevice > & /*device*/ , u64 keyCode )
2019-09-20 16:28:55 +02:00
{
return keyCode = = DS4KeyCodes : : R2 ;
}
2022-10-15 12:41:21 +02:00
bool ds4_pad_handler : : get_is_left_stick ( const std : : shared_ptr < PadDevice > & /*device*/ , u64 keyCode )
2019-09-20 16:28:55 +02:00
{
switch ( keyCode )
{
case DS4KeyCodes : : LSXNeg :
case DS4KeyCodes : : LSXPos :
case DS4KeyCodes : : LSYPos :
case DS4KeyCodes : : LSYNeg :
return true ;
default :
return false ;
}
}
2022-10-15 12:41:21 +02:00
bool ds4_pad_handler : : get_is_right_stick ( const std : : shared_ptr < PadDevice > & /*device*/ , u64 keyCode )
2019-09-20 16:28:55 +02:00
{
switch ( keyCode )
{
case DS4KeyCodes : : RSXNeg :
case DS4KeyCodes : : RSXPos :
case DS4KeyCodes : : RSYPos :
case DS4KeyCodes : : RSYNeg :
return true ;
default :
return false ;
}
}
PadHandlerBase : : connection ds4_pad_handler : : update_connection ( const std : : shared_ptr < PadDevice > & device )
{
2021-02-11 22:13:21 +01:00
DS4Device * ds4_dev = static_cast < DS4Device * > ( device . get ( ) ) ;
2020-11-01 01:11:16 +01:00
if ( ! ds4_dev | | ds4_dev - > path . empty ( ) )
2019-09-20 16:28:55 +02:00
return connection : : disconnected ;
if ( ds4_dev - > hidDevice = = nullptr )
{
// try to reconnect
hid_device * dev = hid_open_path ( ds4_dev - > path . c_str ( ) ) ;
if ( dev )
{
2020-10-25 20:59:03 +01:00
if ( hid_set_nonblocking ( dev , 1 ) = = - 1 )
{
ds4_log . error ( " Reconnecting Device %s: hid_set_nonblocking failed with error %s " , ds4_dev - > path , hid_error ( dev ) ) ;
}
2019-09-20 16:28:55 +02:00
ds4_dev - > hidDevice = dev ;
2021-02-13 01:25:39 +01:00
if ( ! ds4_dev - > has_calib_data )
ds4_dev - > has_calib_data = GetCalibrationData ( ds4_dev ) ;
2019-09-20 16:28:55 +02:00
}
else
{
// nope, not there
return connection : : disconnected ;
}
}
2021-02-11 23:27:33 +01:00
if ( get_data ( ds4_dev ) = = DataStatus : : ReadError )
2019-09-20 16:28:55 +02:00
{
// this also can mean disconnected, either way deal with it on next loop and reconnect
hid_close ( ds4_dev - > hidDevice ) ;
ds4_dev - > hidDevice = nullptr ;
return connection : : no_data ;
}
return connection : : connected ;
}
2022-08-13 09:56:04 +02:00
void ds4_pad_handler : : get_extended_info ( const pad_ensemble & binding )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
const auto & device = binding . device ;
const auto & pad = binding . pad ;
2021-02-11 22:13:21 +01:00
DS4Device * ds4_device = static_cast < DS4Device * > ( device . get ( ) ) ;
2019-09-20 16:28:55 +02:00
if ( ! ds4_device | | ! pad )
return ;
auto buf = ds4_device - > padData ;
2021-02-13 01:25:39 +01:00
pad - > m_battery_level = ds4_device - > battery_level ;
pad - > m_cable_state = ds4_device - > cable_state ;
2019-09-20 16:28:55 +02:00
2021-02-04 22:05:12 +01:00
// these values come already calibrated, all we need to do is convert to ds3 range
2019-09-20 16:28:55 +02:00
// accel
2019-12-04 21:56:19 +01:00
f32 accelX = static_cast < s16 > ( ( buf [ 20 ] < < 8 ) | buf [ 19 ] ) / static_cast < f32 > ( DS4_ACC_RES_PER_G ) * - 1 ;
f32 accelY = static_cast < s16 > ( ( buf [ 22 ] < < 8 ) | buf [ 21 ] ) / static_cast < f32 > ( DS4_ACC_RES_PER_G ) * - 1 ;
f32 accelZ = static_cast < s16 > ( ( buf [ 24 ] < < 8 ) | buf [ 23 ] ) / static_cast < f32 > ( DS4_ACC_RES_PER_G ) * - 1 ;
2019-09-20 16:28:55 +02:00
// now just use formula from ds3
accelX = accelX * 113 + 512 ;
accelY = accelY * 113 + 512 ;
accelZ = accelZ * 113 + 512 ;
pad - > m_sensors [ 0 ] . m_value = Clamp0To1023 ( accelX ) ;
pad - > m_sensors [ 1 ] . m_value = Clamp0To1023 ( accelY ) ;
pad - > m_sensors [ 2 ] . m_value = Clamp0To1023 ( accelZ ) ;
2022-10-17 22:41:34 +02:00
// gyroY is yaw, which is all that we need
//f32 gyroX = static_cast<s16>((u16)(buf[14] << 8) | buf[13]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
f32 gyroY = static_cast < s16 > ( ( buf [ 16 ] < < 8 ) | buf [ 15 ] ) / static_cast < f32 > ( DS4_GYRO_RES_PER_DEG_S ) * - 1 ;
//f32 gyroZ = static_cast<s16>((u16)(buf[18] << 8) | buf[17]) / static_cast<f32>(DS4_GYRO_RES_PER_DEG_S) * -1;
2019-09-20 16:28:55 +02:00
2022-10-17 22:41:34 +02:00
// Convert to ds3. The ds3 resolution is 123/90°/sec.
gyroY = gyroY * ( 123.f / 90.f ) + 512 ;
2019-09-20 16:28:55 +02:00
2022-10-17 22:41:34 +02:00
pad - > m_sensors [ 3 ] . m_value = Clamp0To1023 ( gyroY ) ;
2019-09-20 16:28:55 +02:00
}
2022-08-13 09:56:04 +02:00
void ds4_pad_handler : : apply_pad_data ( const pad_ensemble & binding )
2019-09-20 16:28:55 +02:00
{
2022-08-13 09:56:04 +02:00
const auto & device = binding . device ;
const auto & pad = binding . pad ;
2021-02-11 22:13:21 +01:00
DS4Device * ds4_dev = static_cast < DS4Device * > ( device . get ( ) ) ;
2021-02-12 01:44:39 +01:00
if ( ! ds4_dev | | ! ds4_dev - > hidDevice | | ! ds4_dev - > config | | ! pad )
2019-09-20 16:28:55 +02:00
return ;
2021-08-10 21:45:26 +02:00
cfg_pad * config = ds4_dev - > config ;
2019-09-20 16:28:55 +02:00
// Attempt to send rumble no matter what
2020-12-14 14:33:43 +01:00
const int idx_l = config - > switch_vibration_motors ? 1 : 0 ;
2021-02-13 01:25:39 +01:00
const int idx_s = config - > switch_vibration_motors ? 0 : 1 ;
2020-12-14 14:33:43 +01:00
2022-10-21 22:35:31 +02:00
const u8 speed_large = config - > enable_vibration_motor_large ? pad - > m_vibrateMotors [ idx_l ] . m_value : 0 ;
const u8 speed_small = config - > enable_vibration_motor_small ? pad - > m_vibrateMotors [ idx_s ] . m_value : 0 ;
2019-09-20 16:28:55 +02:00
2021-02-28 04:32:08 +01:00
const bool wireless = ds4_dev - > cable_state = = 0 ;
const bool low_battery = ds4_dev - > battery_level < 2 ;
const bool is_blinking = ds4_dev - > led_delay_on > 0 | | ds4_dev - > led_delay_off > 0 ;
2019-09-20 16:28:55 +02:00
2020-03-05 19:02:28 +01:00
// Blink LED when battery is low
2020-12-14 14:33:43 +01:00
if ( config - > led_low_battery_blink )
2019-09-20 16:28:55 +02:00
{
2020-03-05 19:02:28 +01:00
// we are now wired or have okay battery level -> stop blinking
2021-02-28 04:32:08 +01:00
if ( is_blinking & & ! ( wireless & & low_battery ) )
2020-03-05 19:02:28 +01:00
{
ds4_dev - > led_delay_on = 0 ;
ds4_dev - > led_delay_off = 0 ;
2021-02-12 01:44:39 +01:00
ds4_dev - > new_output_data = true ;
2020-03-05 19:02:28 +01:00
}
// we are now wireless and low on battery -> blink
2021-02-28 04:32:08 +01:00
else if ( ! is_blinking & & wireless & & low_battery )
2020-03-05 19:02:28 +01:00
{
ds4_dev - > led_delay_on = 100 ;
ds4_dev - > led_delay_off = 100 ;
2021-02-12 01:44:39 +01:00
ds4_dev - > new_output_data = true ;
2020-03-05 19:02:28 +01:00
}
2019-09-20 16:28:55 +02:00
}
2020-03-05 19:02:28 +01:00
// Use LEDs to indicate battery level
2020-12-14 14:33:43 +01:00
if ( config - > led_battery_indicator )
2019-09-20 16:28:55 +02:00
{
2020-03-05 19:02:28 +01:00
// This makes sure that the LED color doesn't update every 1ms. DS4 only reports battery level in 10% increments
2021-02-13 01:25:39 +01:00
if ( ds4_dev - > last_battery_level ! = ds4_dev - > battery_level )
2020-03-05 19:02:28 +01:00
{
2021-02-13 01:25:39 +01:00
const u32 combined_color = get_battery_color ( ds4_dev - > battery_level , config - > led_battery_indicator_brightness ) ;
2020-12-14 14:33:43 +01:00
config - > colorR . set ( combined_color > > 8 ) ;
config - > colorG . set ( combined_color & 0xff ) ;
config - > colorB . set ( 0 ) ;
2021-02-12 01:44:39 +01:00
ds4_dev - > new_output_data = true ;
2021-03-05 22:09:28 +01:00
ds4_dev - > last_battery_level = ds4_dev - > battery_level ;
2020-03-05 19:02:28 +01:00
}
2019-09-20 16:28:55 +02:00
}
2021-02-12 01:44:39 +01:00
ds4_dev - > new_output_data | = ds4_dev - > large_motor ! = speed_large | | ds4_dev - > small_motor ! = speed_small ;
2019-09-20 16:28:55 +02:00
2021-02-11 23:27:33 +01:00
ds4_dev - > large_motor = speed_large ;
ds4_dev - > small_motor = speed_small ;
2019-09-20 16:28:55 +02:00
2021-02-12 01:44:39 +01:00
if ( ds4_dev - > new_output_data )
2019-09-20 16:28:55 +02:00
{
2021-02-12 01:44:39 +01:00
if ( send_output_report ( ds4_dev ) > = 0 )
{
ds4_dev - > new_output_data = false ;
}
2019-09-20 16:28:55 +02:00
}
}