2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2016-03-21 20:43:03 +01:00
# include "Emu/IdManager.h"
2022-07-05 21:47:05 +02:00
# include "Emu/system_config.h"
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/PPUModule.h"
2019-10-14 12:48:26 +02:00
# include "Emu/Cell/lv2/sys_process.h"
2023-08-09 10:11:59 +02:00
# include "Emu/Cell/lv2/sys_sync.h"
2020-02-22 20:42:49 +01:00
# include "Emu/Io/pad_types.h"
2019-12-22 17:39:42 +01:00
# include "Input/pad_thread.h"
2020-04-24 22:49:36 +02:00
# include "Input/product_info.h"
2014-09-03 18:33:30 +02:00
# include "cellPad.h"
2012-11-15 00:39:56 +01:00
2023-08-09 10:11:59 +02:00
error_code sys_config_start ( ppu_thread & ppu ) ;
error_code sys_config_stop ( ppu_thread & ppu ) ;
2020-09-26 09:08:12 +02:00
2022-07-05 21:47:05 +02:00
extern bool is_input_allowed ( ) ;
2020-01-31 10:01:17 +01:00
LOG_CHANNEL ( sys_io ) ;
2012-11-15 00:39:56 +01:00
2018-06-07 15:26:07 +02:00
template < >
void fmt_class_string < CellPadError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_PAD_ERROR_FATAL ) ;
STR_CASE ( CELL_PAD_ERROR_INVALID_PARAMETER ) ;
STR_CASE ( CELL_PAD_ERROR_ALREADY_INITIALIZED ) ;
STR_CASE ( CELL_PAD_ERROR_UNINITIALIZED ) ;
STR_CASE ( CELL_PAD_ERROR_RESOURCE_ALLOCATION_FAILED ) ;
STR_CASE ( CELL_PAD_ERROR_DATA_READ_FAILED ) ;
STR_CASE ( CELL_PAD_ERROR_NO_DEVICE ) ;
STR_CASE ( CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD ) ;
STR_CASE ( CELL_PAD_ERROR_TOO_MANY_DEVICES ) ;
STR_CASE ( CELL_PAD_ERROR_EBUSY ) ;
}
return unknown ;
} ) ;
}
2019-09-29 09:58:21 +02:00
template < >
void fmt_class_string < CellPadFilterError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_PADFILTER_ERROR_INVALID_PARAMETER ) ;
}
return unknown ;
} ) ;
}
2023-08-24 18:59:24 +02:00
extern void sys_io_serialize ( utils : : serial & ar ) ;
2022-07-04 15:02:17 +02:00
pad_info : : pad_info ( utils : : serial & ar )
: max_connect ( ar )
, port_setting ( ar )
2023-12-30 19:23:54 +01:00
, reported_info ( ar )
2022-07-04 15:02:17 +02:00
{
2024-01-01 19:23:06 +01:00
//reported_info = {};
2023-08-24 18:59:24 +02:00
sys_io_serialize ( ar ) ;
2022-07-04 15:02:17 +02:00
}
void pad_info : : save ( utils : : serial & ar )
{
2023-08-24 18:59:24 +02:00
USING_SERIALIZATION_VERSION ( sys_io ) ;
2023-12-30 19:23:54 +01:00
ar ( max_connect , port_setting , reported_info ) ;
2023-08-24 22:03:51 +02:00
sys_io_serialize ( ar ) ;
2022-07-04 15:02:17 +02:00
}
2023-08-25 21:42:29 +02:00
extern void send_sys_io_connect_event ( usz index , u32 state ) ;
2022-07-04 15:02:17 +02:00
2024-01-01 08:18:55 +01:00
void cellPad_NotifyStateChange ( usz index , u64 /*state*/ , bool locked )
2023-08-09 10:11:59 +02:00
{
auto info = g_fxo - > try_get < pad_info > ( ) ;
if ( ! info )
{
return ;
}
2024-01-01 08:18:55 +01:00
std : : unique_lock lock ( pad : : g_pad_mutex , std : : defer_lock ) ;
if ( locked )
{
lock . lock ( ) ;
}
2023-08-09 10:11:59 +02:00
2023-08-25 21:42:29 +02:00
if ( index > = info - > get_max_connect ( ) )
2023-08-09 10:11:59 +02:00
{
return ;
}
2023-08-19 12:29:46 +02:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-08-25 22:12:30 +02:00
const auto & pad = pads [ index ] ;
2023-08-19 12:29:46 +02:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move )
{
return ;
}
2023-08-25 22:12:30 +02:00
pad_data_internal & reported_info = info - > reported_info [ index ] ;
const u32 old_status = reported_info . port_status ;
2023-08-19 12:29:46 +02:00
// Ignore sent status for now, use the latest instead
2023-08-25 22:12:30 +02:00
// NOTE 1: The state's CONNECTED bit should currently be identical to the current
// m_port_status CONNECTED bit when called from our pad handlers.
// NOTE 2: Make sure to propagate all other status bits to the reported status.
2024-03-26 12:44:25 +01:00
const u32 new_status = pad - > m_port_status ;
2023-08-09 10:11:59 +02:00
2023-08-25 22:12:30 +02:00
if ( ~ ( old_status ^ new_status ) & CELL_PAD_STATUS_CONNECTED )
2023-08-09 10:11:59 +02:00
{
2023-08-25 22:12:30 +02:00
// old and new have the same connection status
2023-08-09 10:11:59 +02:00
return ;
}
2023-08-25 22:12:30 +02:00
reported_info . port_status = new_status | CELL_PAD_STATUS_ASSIGN_CHANGES ;
reported_info . device_capability = pad - > m_device_capability ;
reported_info . device_type = pad - > m_device_type ;
reported_info . pclass_type = pad - > m_class_type ;
reported_info . pclass_profile = pad - > m_class_profile ;
2023-08-19 12:29:46 +02:00
2023-08-25 22:12:30 +02:00
if ( pad - > m_vendor_id = = 0 | | pad - > m_product_id = = 0 )
2023-08-19 12:29:46 +02:00
{
// Fallback to defaults
input : : product_info product ;
2023-08-25 22:12:30 +02:00
switch ( pad - > m_class_type )
2023-08-19 12:29:46 +02:00
{
case CELL_PAD_PCLASS_TYPE_GUITAR :
product = input : : get_product_info ( input : : product_type : : red_octane_gh_guitar ) ;
break ;
case CELL_PAD_PCLASS_TYPE_DRUM :
product = input : : get_product_info ( input : : product_type : : red_octane_gh_drum_kit ) ;
break ;
case CELL_PAD_PCLASS_TYPE_DJ :
product = input : : get_product_info ( input : : product_type : : dj_hero_turntable ) ;
break ;
case CELL_PAD_PCLASS_TYPE_DANCEMAT :
product = input : : get_product_info ( input : : product_type : : dance_dance_revolution_mat ) ;
break ;
case CELL_PAD_PCLASS_TYPE_NAVIGATION :
2023-08-21 21:14:42 +02:00
product = input : : get_product_info ( input : : product_type : : ps_move_navigation ) ;
break ;
2023-08-26 15:47:52 +02:00
case CELL_PAD_PCLASS_TYPE_SKATEBOARD :
product = input : : get_product_info ( input : : product_type : : ride_skateboard ) ;
break ;
2023-08-19 12:29:46 +02:00
case CELL_PAD_PCLASS_TYPE_STANDARD :
default :
product = input : : get_product_info ( input : : product_type : : playstation_3_controller ) ;
break ;
}
2023-08-25 22:12:30 +02:00
reported_info . vendor_id = product . vendor_id ;
reported_info . product_id = product . product_id ;
2023-08-19 12:29:46 +02:00
}
else
{
2023-08-25 22:12:30 +02:00
reported_info . vendor_id = pad - > m_vendor_id ;
reported_info . product_id = pad - > m_product_id ;
2023-08-19 12:29:46 +02:00
}
2023-08-09 10:11:59 +02:00
}
2023-08-25 21:42:29 +02:00
extern void pad_state_notify_state_change ( usz index , u32 state )
2023-08-09 10:11:59 +02:00
{
2024-02-11 16:39:31 +01:00
send_sys_io_connect_event ( index , state ) ;
2023-08-09 10:11:59 +02:00
}
error_code cellPadInit ( ppu_thread & ppu , u32 max_connect )
2012-11-15 00:39:56 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . warning ( " cellPadInit(max_connect=%d) " , max_connect ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( config . max_connect )
2016-03-21 20:43:03 +01:00
return CELL_PAD_ERROR_ALREADY_INITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( max_connect = = 0 | | max_connect > CELL_MAX_PADS )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2023-08-09 10:11:59 +02:00
sys_config_start ( ppu ) ;
2023-08-08 10:03:39 +02:00
config . max_connect = max_connect ;
2021-03-02 12:59:19 +01:00
config . port_setting . fill ( CELL_PAD_SETTING_PRESS_OFF | CELL_PAD_SETTING_SENSOR_OFF ) ;
2023-08-19 12:29:46 +02:00
config . reported_info = { } ;
2023-08-09 10:11:59 +02:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2024-03-26 12:44:25 +01:00
for ( usz i = 0 ; i < config . get_max_connect ( ) ; + + i )
2023-08-09 10:11:59 +02:00
{
2024-03-26 14:14:54 +01:00
if ( ! pads [ i ] - > is_fake_move & & ( pads [ i ] - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2023-08-09 10:11:59 +02:00
{
send_sys_io_connect_event ( i , CELL_PAD_STATUS_CONNECTED ) ;
}
}
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2023-08-09 10:11:59 +02:00
error_code cellPadEnd ( ppu_thread & ppu )
2012-11-15 00:39:56 +01:00
{
2016-03-21 20:43:03 +01:00
sys_io . notice ( " cellPadEnd() " ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect . exchange ( 0 ) )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2023-08-09 10:11:59 +02:00
sys_config_stop ( ppu ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2021-02-12 02:31:49 +01:00
void clear_pad_buffer ( const std : : shared_ptr < Pad > & pad )
2019-10-06 12:35:02 +02:00
{
if ( ! pad )
return ;
// Set 'm_buffer_cleared' to force a resend of everything
// might as well also reset everything in our pad 'buffer' to nothing as well
pad - > m_buffer_cleared = true ;
pad - > m_analog_left_x = pad - > m_analog_left_y = pad - > m_analog_right_x = pad - > m_analog_right_y = 128 ;
pad - > m_digital_1 = pad - > m_digital_2 = 0 ;
pad - > m_press_right = pad - > m_press_left = pad - > m_press_up = pad - > m_press_down = 0 ;
pad - > m_press_triangle = pad - > m_press_circle = pad - > m_press_cross = pad - > m_press_square = 0 ;
pad - > m_press_L1 = pad - > m_press_L2 = pad - > m_press_R1 = pad - > m_press_R2 = 0 ;
// ~399 on sensor y is a level non moving controller
pad - > m_sensor_y = 399 ;
pad - > m_sensor_x = pad - > m_sensor_z = pad - > m_sensor_g = 512 ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadClearBuf ( u32 port_no )
2012-11-15 00:39:56 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadClearBuf(port_no=%d) " , port_no ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2014-05-07 06:09:10 +02:00
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2017-12-27 11:01:13 +01:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-16 20:00:22 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2014-05-07 06:09:10 +02:00
2019-10-06 12:35:02 +02:00
clear_pad_buffer ( pad ) ;
2017-12-27 11:01:13 +01:00
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2023-08-26 18:25:56 +02:00
void pad_get_data ( u32 port_no , CellPadData * data , bool get_periph_data = false )
2021-05-28 11:35:03 +02:00
{
auto & config = g_fxo - > get < pad_info > ( ) ;
const auto handler = pad : : get_current_handler ( ) ;
const auto & pad = handler - > GetPads ( ) [ port_no ] ;
2019-06-13 21:15:21 +02:00
const PadInfo & rinfo = handler - > GetInfo ( ) ;
2019-10-06 12:35:02 +02:00
if ( rinfo . system_info & CELL_PAD_INFO_INTERCEPTED )
2019-06-13 21:15:21 +02:00
{
data - > len = CELL_PAD_LEN_NO_CHANGE ;
2021-05-28 11:35:03 +02:00
return ;
2019-06-13 21:15:21 +02:00
}
2019-09-20 08:11:30 +02:00
2023-08-26 18:25:56 +02:00
const u32 setting = config . port_setting [ port_no ] ;
2019-10-06 12:35:02 +02:00
bool btnChanged = false ;
2022-07-05 21:47:05 +02:00
if ( rinfo . ignore_input | | ! is_input_allowed ( ) )
2019-10-06 12:35:02 +02:00
{
// Needed for Hotline Miami and Ninja Gaiden Sigma after dialogs were closed and buttons are still pressed.
// Gran Turismo 6 would keep registering the Start button during OSK Dialogs if this wasn't cleared and if we'd return with len as CELL_PAD_LEN_NO_CHANGE.
clear_pad_buffer ( pad ) ;
}
else if ( pad - > ldd )
2019-04-28 23:35:11 +02:00
{
2023-02-12 11:33:23 +01:00
pad - > ldd_data = * data ;
2019-04-28 23:35:11 +02:00
if ( setting & CELL_PAD_SETTING_SENSOR_ON )
data - > len = CELL_PAD_LEN_CHANGE_SENSOR_ON ;
else
data - > len = ( setting & CELL_PAD_SETTING_PRESS_ON ) ? CELL_PAD_LEN_CHANGE_PRESS_ON : CELL_PAD_LEN_CHANGE_DEFAULT ;
2021-05-28 11:35:03 +02:00
return ;
2019-04-28 23:35:11 +02:00
}
2019-10-06 12:35:02 +02:00
else
2012-11-15 00:39:56 +01:00
{
2021-04-19 23:09:25 +02:00
const u16 d1Initial = pad - > m_digital_1 ;
const u16 d2Initial = pad - > m_digital_2 ;
2014-05-07 06:04:47 +02:00
2023-08-26 15:47:52 +02:00
// Check if this pad is configured as a skateboard which ignores sticks and pressure button values.
// Curiously it maps infrared on the press value of the face buttons for some reason.
const bool use_piggyback = pad - > m_class_type = = CELL_PAD_PCLASS_TYPE_SKATEBOARD ;
const auto set_value = [ & btnChanged , use_piggyback ] ( u16 & value , u16 new_value , bool is_piggyback = false )
2023-02-10 02:41:32 +01:00
{
2023-08-26 15:47:52 +02:00
if ( use_piggyback & & ! is_piggyback )
return ;
2023-02-10 02:41:32 +01:00
if ( value ! = new_value )
{
btnChanged = true ;
value = new_value ;
}
} ;
2019-10-06 12:35:02 +02:00
for ( Button & button : pad - > m_buttons )
2012-11-15 00:39:56 +01:00
{
2019-10-06 12:35:02 +02:00
// here we check btns, and set pad accordingly,
// if something changed, set btnChanged
2014-05-07 06:04:47 +02:00
2023-08-26 15:47:52 +02:00
switch ( button . m_offset )
{
case CELL_PAD_BTN_OFFSET_DIGITAL1 :
2014-05-07 06:04:47 +02:00
{
2019-10-06 12:35:02 +02:00
if ( button . m_pressed )
pad - > m_digital_1 | = button . m_outKeyCode ;
else
pad - > m_digital_1 & = ~ button . m_outKeyCode ;
switch ( button . m_outKeyCode )
{
2023-02-10 02:41:32 +01:00
case CELL_PAD_CTRL_LEFT : set_value ( pad - > m_press_left , button . m_value ) ; break ;
case CELL_PAD_CTRL_DOWN : set_value ( pad - > m_press_down , button . m_value ) ; break ;
case CELL_PAD_CTRL_RIGHT : set_value ( pad - > m_press_right , button . m_value ) ; break ;
case CELL_PAD_CTRL_UP : set_value ( pad - > m_press_up , button . m_value ) ; break ;
2019-10-06 12:35:02 +02:00
// These arent pressure btns
case CELL_PAD_CTRL_R3 :
case CELL_PAD_CTRL_L3 :
case CELL_PAD_CTRL_START :
case CELL_PAD_CTRL_SELECT :
default : break ;
}
2023-08-26 15:47:52 +02:00
break ;
2019-10-06 12:35:02 +02:00
}
2023-08-26 15:47:52 +02:00
case CELL_PAD_BTN_OFFSET_DIGITAL2 :
2019-10-06 12:35:02 +02:00
{
if ( button . m_pressed )
pad - > m_digital_2 | = button . m_outKeyCode ;
else
pad - > m_digital_2 & = ~ button . m_outKeyCode ;
switch ( button . m_outKeyCode )
{
2023-02-10 02:41:32 +01:00
case CELL_PAD_CTRL_SQUARE : set_value ( pad - > m_press_square , button . m_value ) ; break ;
case CELL_PAD_CTRL_CROSS : set_value ( pad - > m_press_cross , button . m_value ) ; break ;
case CELL_PAD_CTRL_CIRCLE : set_value ( pad - > m_press_circle , button . m_value ) ; break ;
case CELL_PAD_CTRL_TRIANGLE : set_value ( pad - > m_press_triangle , button . m_value ) ; break ;
case CELL_PAD_CTRL_R1 : set_value ( pad - > m_press_R1 , button . m_value ) ; break ;
case CELL_PAD_CTRL_L1 : set_value ( pad - > m_press_L1 , button . m_value ) ; break ;
case CELL_PAD_CTRL_R2 : set_value ( pad - > m_press_R2 , button . m_value ) ; break ;
case CELL_PAD_CTRL_L2 : set_value ( pad - > m_press_L2 , button . m_value ) ; break ;
2019-10-06 12:35:02 +02:00
default : break ;
}
2023-08-26 15:47:52 +02:00
break ;
}
case CELL_PAD_BTN_OFFSET_PRESS_PIGGYBACK :
{
switch ( button . m_outKeyCode )
{
case CELL_PAD_CTRL_PRESS_RIGHT : set_value ( pad - > m_press_right , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_LEFT : set_value ( pad - > m_press_left , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_UP : set_value ( pad - > m_press_up , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_DOWN : set_value ( pad - > m_press_down , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_TRIANGLE : set_value ( pad - > m_press_triangle , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_CIRCLE : set_value ( pad - > m_press_circle , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_CROSS : set_value ( pad - > m_press_cross , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_SQUARE : set_value ( pad - > m_press_square , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_L1 : set_value ( pad - > m_press_L1 , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_R1 : set_value ( pad - > m_press_R1 , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_L2 : set_value ( pad - > m_press_L2 , button . m_value , true ) ; break ;
case CELL_PAD_CTRL_PRESS_R2 : set_value ( pad - > m_press_R2 , button . m_value , true ) ; break ;
default : break ;
}
break ;
}
default :
break ;
2014-05-07 06:04:47 +02:00
}
}
2014-05-08 01:08:16 +02:00
2019-10-06 12:35:02 +02:00
for ( const AnalogStick & stick : pad - > m_sticks )
{
switch ( stick . m_offset )
2014-05-07 06:04:47 +02:00
{
2023-02-10 02:41:32 +01:00
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X : set_value ( pad - > m_analog_left_x , stick . m_value ) ; break ;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y : set_value ( pad - > m_analog_left_y , stick . m_value ) ; break ;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X : set_value ( pad - > m_analog_right_x , stick . m_value ) ; break ;
case CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y : set_value ( pad - > m_analog_right_y , stick . m_value ) ; break ;
2014-05-07 06:04:47 +02:00
default : break ;
}
2012-11-15 00:39:56 +01:00
}
2019-10-06 12:35:02 +02:00
if ( setting & CELL_PAD_SETTING_SENSOR_ON )
2017-04-29 03:02:28 +02:00
{
2019-10-06 12:35:02 +02:00
for ( const AnalogSensor & sensor : pad - > m_sensors )
2018-11-05 20:34:40 +01:00
{
2019-10-06 12:35:02 +02:00
switch ( sensor . m_offset )
{
2023-08-26 15:47:52 +02:00
case CELL_PAD_BTN_OFFSET_SENSOR_X : set_value ( pad - > m_sensor_x , sensor . m_value , true ) ; break ;
case CELL_PAD_BTN_OFFSET_SENSOR_Y : set_value ( pad - > m_sensor_y , sensor . m_value , true ) ; break ;
case CELL_PAD_BTN_OFFSET_SENSOR_Z : set_value ( pad - > m_sensor_z , sensor . m_value , true ) ; break ;
case CELL_PAD_BTN_OFFSET_SENSOR_G : set_value ( pad - > m_sensor_g , sensor . m_value , true ) ; break ;
2019-10-06 12:35:02 +02:00
default : break ;
}
2018-11-05 20:34:40 +01:00
}
2017-04-29 03:02:28 +02:00
}
2019-10-06 12:35:02 +02:00
if ( d1Initial ! = pad - > m_digital_1 | | d2Initial ! = pad - > m_digital_2 )
{
btnChanged = true ;
}
2014-05-21 02:56:36 +02:00
}
2018-12-13 06:24:17 +01:00
if ( setting & CELL_PAD_SETTING_SENSOR_ON )
2017-09-24 20:39:56 +02:00
{
// report back new data every ~10 ms even if the input doesn't change
// this is observed behaviour when using a Dualshock 3 controller
2020-12-11 14:31:32 +01:00
static std : : array < steady_clock : : time_point , CELL_PAD_MAX_PORT_NUM > last_update = { } ;
const auto now = steady_clock : : now ( ) ;
2014-05-21 02:56:36 +02:00
2020-12-11 14:31:32 +01:00
if ( btnChanged | | pad - > m_buffer_cleared | | now - last_update [ port_no ] > = 10 ms )
2017-09-24 20:39:56 +02:00
{
data - > len = CELL_PAD_LEN_CHANGE_SENSOR_ON ;
last_update [ port_no ] = now ;
}
else
{
data - > len = CELL_PAD_LEN_NO_CHANGE ;
}
}
else if ( btnChanged | | pad - > m_buffer_cleared )
{
// only give back valid data if a controller state changed
2018-12-13 06:24:17 +01:00
data - > len = ( setting & CELL_PAD_SETTING_PRESS_ON ) ? CELL_PAD_LEN_CHANGE_PRESS_ON : CELL_PAD_LEN_CHANGE_DEFAULT ;
2017-09-24 20:39:56 +02:00
}
else
2014-05-21 02:56:36 +02:00
{
2017-09-24 20:39:56 +02:00
// report no state changes
data - > len = CELL_PAD_LEN_NO_CHANGE ;
2014-05-21 02:56:36 +02:00
}
2017-09-24 20:39:56 +02:00
pad - > m_buffer_cleared = false ;
2017-12-27 11:01:13 +01:00
2017-09-24 20:39:56 +02:00
// only update parts of the output struct depending on the controller setting
if ( data - > len > CELL_PAD_LEN_NO_CHANGE )
{
data - > button [ 0 ] = 0x0 ; // always 0
// bits 15-8 reserved, 7-4 = 0x7, 3-0: data->len/2;
data - > button [ 1 ] = ( 0x7 < < 4 ) | std : : min ( data - > len / 2 , 15 ) ;
data - > button [ CELL_PAD_BTN_OFFSET_DIGITAL1 ] = pad - > m_digital_1 ;
data - > button [ CELL_PAD_BTN_OFFSET_DIGITAL2 ] = pad - > m_digital_2 ;
data - > button [ CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X ] = pad - > m_analog_right_x ;
data - > button [ CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y ] = pad - > m_analog_right_y ;
data - > button [ CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X ] = pad - > m_analog_left_x ;
data - > button [ CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y ] = pad - > m_analog_left_y ;
2018-12-13 06:24:17 +01:00
if ( setting & CELL_PAD_SETTING_PRESS_ON )
2018-11-05 20:34:40 +01:00
{
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_RIGHT ] = pad - > m_press_right ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_LEFT ] = pad - > m_press_left ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_UP ] = pad - > m_press_up ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_DOWN ] = pad - > m_press_down ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE ] = pad - > m_press_triangle ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_CIRCLE ] = pad - > m_press_circle ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_CROSS ] = pad - > m_press_cross ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_SQUARE ] = pad - > m_press_square ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_L1 ] = pad - > m_press_L1 ;
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_R1 ] = pad - > m_press_R1 ;
2023-08-26 15:47:52 +02:00
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_L2 ] = pad - > m_press_L2 ;
2018-11-05 20:34:40 +01:00
data - > button [ CELL_PAD_BTN_OFFSET_PRESS_R2 ] = pad - > m_press_R2 ;
}
else
{
// Clear area if setting is not used
constexpr u32 area_lengh = ( CELL_PAD_LEN_CHANGE_PRESS_ON - CELL_PAD_LEN_CHANGE_DEFAULT ) * sizeof ( u16 ) ;
std : : memset ( & data - > button [ CELL_PAD_LEN_CHANGE_DEFAULT ] , 0 , area_lengh ) ;
}
2017-09-24 20:39:56 +02:00
2018-11-05 20:34:40 +01:00
if ( data - > len = = CELL_PAD_LEN_CHANGE_SENSOR_ON )
{
data - > button [ CELL_PAD_BTN_OFFSET_SENSOR_X ] = pad - > m_sensor_x ;
data - > button [ CELL_PAD_BTN_OFFSET_SENSOR_Y ] = pad - > m_sensor_y ;
data - > button [ CELL_PAD_BTN_OFFSET_SENSOR_Z ] = pad - > m_sensor_z ;
data - > button [ CELL_PAD_BTN_OFFSET_SENSOR_G ] = pad - > m_sensor_g ;
}
2014-05-21 02:56:36 +02:00
}
2023-08-26 18:25:56 +02:00
if ( ! get_periph_data | | data - > len < = CELL_PAD_LEN_CHANGE_SENSOR_ON )
{
return ;
}
const auto get_pressure_value = [ setting ] ( u16 val , u16 min , u16 max ) - > u16
{
if ( setting & CELL_PAD_SETTING_PRESS_ON )
{
return std : : clamp ( val , min , max ) ;
}
if ( val > 0 )
{
return max ;
}
return 0 ;
} ;
// TODO: support for 'unique' controllers, which goes in offsets 24+ in padData (CELL_PAD_PCLASS_BTN_OFFSET)
// TODO: update data->len accordingly
switch ( pad - > m_class_profile )
{
default :
case CELL_PAD_PCLASS_TYPE_STANDARD :
case CELL_PAD_PCLASS_TYPE_NAVIGATION :
2023-08-26 15:47:52 +02:00
case CELL_PAD_PCLASS_TYPE_SKATEBOARD :
2023-08-26 18:25:56 +02:00
{
break ;
}
case CELL_PAD_PCLASS_TYPE_GUITAR :
{
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_1 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_2 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_3 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_4 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_5 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_STRUM_UP ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_STRUM_DOWN ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_WHAMMYBAR ] = 0x80 ; // 0x80 – 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H1 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H2 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H3 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H4 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_FRET_H5 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_5WAY_EFFECT ] = 0x0019 ; // One of 5 values: 0x0019, 0x004C, 0x007F (or 0x0096), 0x00B2, 0x00E5 (or 0x00E2)
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_GUITAR_TILT_SENS ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
break ;
}
case CELL_PAD_PCLASS_TYPE_DRUM :
{
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_SNARE ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM2 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_TOM_FLOOR ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_KICK ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_HiHAT ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_CRASH ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_CYM_RIDE ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DRUM_KICK2 ] = get_pressure_value ( 0 , 0x0 , 0xFF ) ;
break ;
}
case CELL_PAD_PCLASS_TYPE_DJ :
{
// First deck
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_ATTACK ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_CROSSFADER ] = 0 ; // 0x0 - 0x3FF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_MIXER_DSP_DIAL ] = 0 ; // 0x0 - 0x3FF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM1 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM2 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_STREAM3 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK1_PLATTER ] = 0x80 ; // 0x0 - 0xFF (neutral: 0x80)
// Second deck
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM1 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM2 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_STREAM3 ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DJ_DECK2_PLATTER ] = 0x80 ; // 0x0 - 0xFF (neutral: 0x80)
break ;
}
case CELL_PAD_PCLASS_TYPE_DANCEMAT :
{
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_CIRCLE ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_CROSS ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_TRIANGLE ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_SQUARE ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_RIGHT ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_LEFT ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_UP ] = 0 ; // 0x0 or 0xFF
data - > button [ CELL_PAD_PCLASS_BTN_OFFSET_DANCEMAT_DOWN ] = 0 ; // 0x0 or 0xFF
break ;
}
}
}
error_code cellPadGetData ( u32 port_no , vm : : ptr < CellPadData > data )
{
sys_io . trace ( " cellPadGetData(port_no=%d, data=*0x%x) " , port_no , data ) ;
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
auto & config = g_fxo - > get < pad_info > ( ) ;
if ( ! config . max_connect )
return CELL_PAD_ERROR_UNINITIALIZED ;
if ( port_no > = CELL_MAX_PADS | | ! data )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
if ( port_no > = config . get_max_connect ( ) )
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-08-26 18:25:56 +02:00
const auto & pad = pads [ port_no ] ;
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2023-08-26 18:25:56 +02:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
pad_get_data ( port_no , data . get_ptr ( ) ) ;
return CELL_OK ;
2012-11-15 00:39:56 +01:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadPeriphGetInfo ( vm : : ptr < CellPadPeriphInfo > info )
2017-05-26 23:02:36 +02:00
{
sys_io . trace ( " cellPadPeriphGetInfo(info=*0x%x) " , info ) ;
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2017-05-26 23:02:36 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2017-05-26 23:02:36 +02:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-04-08 22:34:37 +02:00
if ( ! info )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2017-05-26 23:02:36 +02:00
const PadInfo & rinfo = handler - > GetInfo ( ) ;
2017-05-31 04:54:35 +02:00
std : : memset ( info . get_ptr ( ) , 0 , sizeof ( CellPadPeriphInfo ) ) ;
2021-03-02 12:59:19 +01:00
info - > max_connect = config . max_connect ;
2017-05-26 23:02:36 +02:00
info - > system_info = rinfo . system_info ;
2023-08-19 12:29:46 +02:00
u32 now_connect = 0 ;
2024-03-26 12:44:25 +01:00
for ( u32 i = 0 ; i < config . get_max_connect ( ) ; + + i )
2017-05-26 23:02:36 +02:00
{
2023-08-25 21:34:53 +02:00
pad_data_internal & reported_info = config . reported_info [ i ] ;
info - > port_status [ i ] = reported_info . port_status ;
2021-03-02 12:59:19 +01:00
info - > port_setting [ i ] = config . port_setting [ i ] ;
2023-08-19 12:29:46 +02:00
2023-08-25 21:34:53 +02:00
reported_info . port_status & = ~ CELL_PAD_STATUS_ASSIGN_CHANGES ;
if ( ~ reported_info . port_status & CELL_PAD_STATUS_CONNECTED )
2023-08-19 12:29:46 +02:00
{
continue ;
}
2023-08-25 21:34:53 +02:00
info - > device_capability [ i ] = reported_info . device_capability ;
info - > device_type [ i ] = reported_info . device_type ;
info - > pclass_type [ i ] = reported_info . pclass_type ;
info - > pclass_profile [ i ] = reported_info . pclass_profile ;
2023-08-19 12:29:46 +02:00
now_connect + + ;
2017-05-26 23:02:36 +02:00
}
2023-08-19 12:29:46 +02:00
info - > now_connect = now_connect ;
2017-05-26 23:02:36 +02:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadPeriphGetData ( u32 port_no , vm : : ptr < CellPadPeriphData > data )
2017-05-26 23:02:36 +02:00
{
sys_io . trace ( " cellPadPeriphGetData(port_no=%d, data=*0x%x) " , port_no , data ) ;
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2018-12-13 06:24:17 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2017-05-26 23:02:36 +02:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
// port_no can only be 0-6 in this function
if ( port_no > = CELL_PAD_MAX_PORT_NUM | | ! data )
2017-05-26 23:02:36 +02:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2017-12-27 11:01:13 +01:00
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2021-05-28 11:35:03 +02:00
const auto & pad = pads [ port_no ] ;
2017-12-27 11:01:13 +01:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-27 08:44:30 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2017-05-26 23:02:36 +02:00
2023-08-26 18:25:56 +02:00
pad_get_data ( port_no , & data - > cellpad_data , true ) ;
2021-05-28 11:35:03 +02:00
2019-02-25 18:47:16 +01:00
data - > pclass_type = pad - > m_class_type ;
2020-04-25 02:12:19 +02:00
data - > pclass_profile = pad - > m_class_profile ;
2018-06-07 15:26:07 +02:00
2021-05-28 11:35:03 +02:00
return CELL_OK ;
2017-05-26 23:02:36 +02:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadGetRawData ( u32 port_no , vm : : ptr < CellPadData > data )
2015-08-01 03:46:42 +02:00
{
2018-06-07 15:26:07 +02:00
sys_io . todo ( " cellPadGetRawData(port_no=%d, data=*0x%x) " , port_no , data ) ;
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2018-06-07 15:26:07 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_UNINITIALIZED ;
if ( port_no > = CELL_MAX_PADS | | ! data )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2018-06-07 15:26:07 +02:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-16 20:00:22 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2018-06-07 15:26:07 +02:00
// ?
return CELL_OK ;
2015-08-01 03:46:42 +02:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadGetDataExtra ( u32 port_no , vm : : ptr < u32 > device_type , vm : : ptr < CellPadData > data )
2012-11-15 00:39:56 +01:00
{
2018-06-07 15:26:07 +02:00
sys_io . trace ( " cellPadGetDataExtra(port_no=%d, device_type=*0x%x, data=*0x%x) " , port_no , device_type , data ) ;
2015-02-22 09:50:26 +01:00
2017-04-28 09:17:31 +02:00
// TODO: This is used just to get data from a BD/CEC remote,
2023-02-10 02:40:54 +01:00
// but if the port isnt a remote, device type is set to CELL_PAD_DEV_TYPE_STANDARD and just regular cellPadGetData is returned
2017-04-28 09:17:31 +02:00
2021-05-28 11:35:03 +02:00
if ( auto err = cellPadGetData ( port_no , data ) )
{
return err ;
}
2018-06-07 15:26:07 +02:00
if ( device_type ) // no error is returned on NULL
{
2023-02-10 02:40:54 +01:00
* device_type = CELL_PAD_DEV_TYPE_STANDARD ;
2018-06-07 15:26:07 +02:00
}
2017-04-28 09:17:31 +02:00
2021-05-28 11:35:03 +02:00
// Set BD data
2017-04-28 09:17:31 +02:00
data - > button [ 24 ] = 0x0 ;
data - > button [ 25 ] = 0x0 ;
2021-05-28 11:35:03 +02:00
return CELL_OK ;
2012-11-15 00:39:56 +01:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadSetActDirect ( u32 port_no , vm : : ptr < CellPadActParam > param )
2012-11-15 00:39:56 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadSetActDirect(port_no=%d, param=*0x%x) " , port_no , param ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS | | ! param )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2017-12-27 11:01:13 +01:00
2019-10-14 12:48:26 +02:00
// Note: signed check unlike the usual unsigned check
2019-12-02 22:31:34 +01:00
if ( static_cast < s32 > ( g_ps3_process_info . sdk_ver ) > 0x1FFFFF )
2019-10-14 12:48:26 +02:00
{
// make sure reserved bits are 0
for ( int i = 0 ; i < 6 ; i + + )
{
if ( param - > reserved [ i ] )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
}
}
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2017-12-27 11:01:13 +01:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-16 20:00:22 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2014-05-07 05:54:41 +02:00
2018-06-07 15:26:07 +02:00
// TODO: find out if this is checked here or later or at all
if ( ! ( pad - > m_device_capability & CELL_PAD_CAPABILITY_ACTUATOR ) )
return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD ;
2017-04-29 03:02:28 +02:00
handler - > SetRumble ( port_no , param - > motor [ 1 ] , param - > motor [ 0 ] > 0 ) ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadGetInfo ( vm : : ptr < CellPadInfo > info )
2013-12-08 14:47:54 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadGetInfo(info=*0x%x) " , info ) ;
2013-12-08 14:47:54 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2013-12-08 14:47:54 +01:00
2018-04-08 22:34:37 +02:00
if ( ! info )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2017-05-31 04:54:35 +02:00
std : : memset ( info . get_ptr ( ) , 0 , sizeof ( CellPadInfo ) ) ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2016-03-21 20:43:03 +01:00
const PadInfo & rinfo = handler - > GetInfo ( ) ;
2021-03-02 12:59:19 +01:00
info - > max_connect = config . max_connect ;
2014-09-03 18:33:30 +02:00
info - > system_info = rinfo . system_info ;
2013-12-08 14:47:54 +01:00
2023-08-09 10:11:59 +02:00
u32 now_connect = 0 ;
2024-03-26 12:44:25 +01:00
for ( u32 i = 0 ; i < config . get_max_connect ( ) ; + + i )
2013-12-08 14:47:54 +01:00
{
2023-08-25 21:34:53 +02:00
pad_data_internal & reported_info = config . reported_info [ i ] ;
reported_info . port_status & = ~ CELL_PAD_STATUS_ASSIGN_CHANGES ; // TODO: should ASSIGN flags be cleared here?
info - > status [ i ] = reported_info . port_status ;
2023-08-09 10:11:59 +02:00
2023-08-25 21:34:53 +02:00
if ( ~ reported_info . port_status & CELL_PAD_STATUS_CONNECTED )
2023-08-09 10:11:59 +02:00
{
2023-08-19 12:29:46 +02:00
continue ;
2023-08-09 10:11:59 +02:00
}
2019-02-28 02:38:03 +01:00
2023-08-25 21:34:53 +02:00
info - > vendor_id [ i ] = reported_info . vendor_id ;
info - > product_id [ i ] = reported_info . product_id ;
2020-04-24 22:49:36 +02:00
2023-08-19 12:29:46 +02:00
now_connect + + ;
2013-12-08 14:47:54 +01:00
}
2023-08-09 10:11:59 +02:00
info - > now_connect = now_connect ;
2013-12-08 14:47:54 +01:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadGetInfo2 ( vm : : ptr < CellPadInfo2 > info )
2012-11-15 00:39:56 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadGetInfo2(info=*0x%x) " , info ) ;
2012-11-15 00:39:56 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2012-11-15 00:39:56 +01:00
2018-04-08 22:34:37 +02:00
if ( ! info )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2017-05-31 04:54:35 +02:00
std : : memset ( info . get_ptr ( ) , 0 , sizeof ( CellPadInfo2 ) ) ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2016-03-21 20:43:03 +01:00
const PadInfo & rinfo = handler - > GetInfo ( ) ;
2023-08-08 10:03:39 +02:00
info - > max_connect = config . get_max_connect ( ) ; // Here it is forcibly clamped
2014-09-03 18:33:30 +02:00
info - > system_info = rinfo . system_info ;
2012-11-15 00:39:56 +01:00
2023-08-09 10:11:59 +02:00
u32 now_connect = 0 ;
2017-12-27 11:01:13 +01:00
const auto & pads = handler - > GetPads ( ) ;
2012-11-15 00:39:56 +01:00
2024-03-26 12:44:25 +01:00
for ( u32 i = 0 ; i < config . get_max_connect ( ) ; + + i )
2012-11-15 00:39:56 +01:00
{
2023-08-25 21:34:53 +02:00
pad_data_internal & reported_info = config . reported_info [ i ] ;
info - > port_status [ i ] = reported_info . port_status ;
2023-08-19 12:29:46 +02:00
info - > port_setting [ i ] = config . port_setting [ i ] ;
2023-08-25 21:34:53 +02:00
reported_info . port_status & = ~ CELL_PAD_STATUS_ASSIGN_CHANGES ;
if ( ~ reported_info . port_status & CELL_PAD_STATUS_CONNECTED )
2023-08-19 12:29:46 +02:00
{
2023-08-09 10:11:59 +02:00
continue ;
2023-08-19 12:29:46 +02:00
}
2023-08-09 10:11:59 +02:00
2017-08-15 14:03:07 +02:00
info - > device_capability [ i ] = pads [ i ] - > m_device_capability ;
info - > device_type [ i ] = pads [ i ] - > m_device_type ;
2023-08-09 10:11:59 +02:00
2023-08-19 12:29:46 +02:00
now_connect + + ;
2012-11-15 00:39:56 +01:00
}
2023-08-09 10:11:59 +02:00
info - > now_connect = now_connect ;
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadGetCapabilityInfo ( u32 port_no , vm : : ptr < CellPadCapabilityInfo > info )
2014-05-07 05:46:18 +02:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadGetCapabilityInfo(port_no=%d, data_addr:=0x%x) " , port_no , info . addr ( ) ) ;
2014-09-03 18:33:30 +02:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS | | ! info )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2014-05-07 05:46:18 +02:00
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2017-12-27 11:01:13 +01:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-27 08:44:30 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2014-05-07 05:46:18 +02:00
2018-06-07 15:26:07 +02:00
// Should return the same as device capability mask, psl1ght has it backwards in pad->h
2019-02-28 02:38:03 +01:00
memset ( info - > info , 0 , CELL_PAD_MAX_CAPABILITY_INFO * sizeof ( u32 ) ) ;
info - > info [ 0 ] = pad - > m_device_capability ;
2014-05-07 05:46:18 +02:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadSetPortSetting ( u32 port_no , u32 port_setting )
2012-11-15 00:39:56 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadSetPortSetting(port_no=%d, port_setting=0x%x) " , port_no , port_setting ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2012-11-15 00:39:56 +01:00
2018-06-07 15:26:07 +02:00
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
2018-12-13 06:24:17 +01:00
if ( port_no > = CELL_PAD_MAX_PORT_NUM )
2018-06-07 15:26:07 +02:00
return CELL_OK ;
2021-03-02 12:59:19 +01:00
config . port_setting [ port_no ] = port_setting ;
2012-11-15 00:39:56 +01:00
2023-02-10 02:40:54 +01:00
// can also return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD <- Update: seems to be just internal and ignored
2017-12-24 15:47:36 +01:00
2012-11-15 00:39:56 +01:00
return CELL_OK ;
}
2014-01-05 00:58:03 +01:00
2019-09-29 11:01:52 +02:00
error_code cellPadInfoPressMode ( u32 port_no )
2014-01-05 00:58:03 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadInfoPressMode(port_no=%d) " , port_no ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2014-05-07 05:54:41 +02:00
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2014-05-07 05:54:41 +02:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-27 08:44:30 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2017-12-27 11:01:13 +01:00
2019-09-29 11:01:52 +02:00
return not_an_error ( ( pad - > m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE ) ? 1 : 0 ) ;
2014-01-05 00:58:03 +01:00
}
2019-09-29 11:01:52 +02:00
error_code cellPadInfoSensorMode ( u32 port_no )
2014-01-05 00:58:03 +01:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadInfoSensorMode(port_no=%d) " , port_no ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2014-05-07 05:54:41 +02:00
2023-08-08 10:03:39 +02:00
if ( port_no > = config . get_max_connect ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_NO_DEVICE ;
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2017-12-27 11:01:13 +01:00
2024-03-26 14:14:54 +01:00
if ( pad - > is_fake_move | | ! config . is_reportedly_connected ( port_no ) | | ! ( pad - > m_port_status & CELL_PAD_STATUS_CONNECTED ) )
2022-11-27 08:44:30 +01:00
return not_an_error ( CELL_PAD_ERROR_NO_DEVICE ) ;
2014-05-07 05:54:41 +02:00
2019-09-29 11:01:52 +02:00
return not_an_error ( ( pad - > m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE ) ? 1 : 0 ) ;
2014-04-06 21:47:21 +02:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadSetPressMode ( u32 port_no , u32 mode )
2014-04-06 21:47:21 +02:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadSetPressMode(port_no=%d, mode=%d) " , port_no , mode ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2016-03-21 20:43:03 +01:00
2018-12-13 06:24:17 +01:00
if ( port_no > = CELL_PAD_MAX_PORT_NUM )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2018-06-07 15:26:07 +02:00
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
2018-12-13 06:24:17 +01:00
if ( port_no > = CELL_PAD_MAX_PORT_NUM )
2018-06-07 15:26:07 +02:00
return CELL_OK ;
2014-05-07 05:54:41 +02:00
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
const auto & pad = pads [ port_no ] ;
2014-05-07 05:54:41 +02:00
2018-06-07 15:26:07 +02:00
// TODO: find out if this is checked here or later or at all
if ( ! ( pad - > m_device_capability & CELL_PAD_CAPABILITY_PRESS_MODE ) )
return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD ;
2014-05-07 05:54:41 +02:00
if ( mode )
2021-03-02 12:59:19 +01:00
config . port_setting [ port_no ] | = CELL_PAD_SETTING_PRESS_ON ;
2014-05-07 05:54:41 +02:00
else
2021-03-02 12:59:19 +01:00
config . port_setting [ port_no ] & = ~ CELL_PAD_SETTING_PRESS_ON ;
2017-12-27 11:01:13 +01:00
2014-04-06 21:47:21 +02:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadSetSensorMode ( u32 port_no , u32 mode )
2014-04-06 21:47:21 +02:00
{
2016-01-12 22:57:16 +01:00
sys_io . trace ( " cellPadSetSensorMode(port_no=%d, mode=%d) " , port_no , mode ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2016-03-21 20:43:03 +01:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2016-03-21 20:43:03 +01:00
2018-06-07 15:26:07 +02:00
if ( port_no > = CELL_MAX_PADS )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2018-06-07 15:26:07 +02:00
// CELL_PAD_ERROR_NO_DEVICE is not returned in this case.
2018-12-13 06:24:17 +01:00
if ( port_no > = CELL_PAD_MAX_PORT_NUM )
2018-06-07 15:26:07 +02:00
return CELL_OK ;
2014-05-07 05:54:41 +02:00
2024-03-26 12:39:56 +01:00
const auto handler = pad : : get_current_handler ( ) ;
const auto & pads = handler - > GetPads ( ) ;
2021-08-08 18:50:37 +02:00
const auto & pad = pads [ port_no ] ;
2014-05-07 05:54:41 +02:00
2018-06-07 15:26:07 +02:00
// TODO: find out if this is checked here or later or at all
if ( ! ( pad - > m_device_capability & CELL_PAD_CAPABILITY_SENSOR_MODE ) )
return CELL_PAD_ERROR_UNSUPPORTED_GAMEPAD ;
2014-05-07 05:54:41 +02:00
if ( mode )
2021-03-02 12:59:19 +01:00
config . port_setting [ port_no ] | = CELL_PAD_SETTING_SENSOR_ON ;
2014-05-07 05:54:41 +02:00
else
2021-03-02 12:59:19 +01:00
config . port_setting [ port_no ] & = ~ CELL_PAD_SETTING_SENSOR_ON ;
2017-12-27 11:01:13 +01:00
2014-04-06 21:47:21 +02:00
return CELL_OK ;
2014-07-12 09:46:14 +02:00
}
2014-09-03 18:33:30 +02:00
2018-06-07 15:26:07 +02:00
error_code cellPadLddRegisterController ( )
2015-02-22 09:50:26 +01:00
{
2019-04-28 23:35:11 +02:00
sys_io . warning ( " cellPadLddRegisterController() " ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-12-13 06:24:17 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2019-04-28 23:35:11 +02:00
const s32 handle = handler - > AddLddPad ( ) ;
2018-06-07 15:26:07 +02:00
2019-04-28 23:35:11 +02:00
if ( handle < 0 )
return CELL_PAD_ERROR_TOO_MANY_DEVICES ;
2021-03-02 12:59:19 +01:00
config . port_setting [ handle ] = 0 ;
2019-04-28 23:35:11 +02:00
2024-01-01 12:25:25 +01:00
cellPad_NotifyStateChange ( handle , CELL_PAD_STATUS_CONNECTED , false ) ;
2019-04-28 23:35:11 +02:00
return not_an_error ( handle ) ;
2015-02-22 09:50:26 +01:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadLddDataInsert ( s32 handle , vm : : ptr < CellPadData > data )
2015-02-22 09:50:26 +01:00
{
2019-04-28 23:35:11 +02:00
sys_io . trace ( " cellPadLddDataInsert(handle=%d, data=*0x%x) " , handle , data ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-12-13 06:24:17 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2023-02-10 02:40:54 +01:00
auto & pads = handler - > GetPads ( ) ;
2018-12-13 06:24:17 +01:00
2023-02-10 02:40:54 +01:00
if ( handle < 0 | | static_cast < u32 > ( handle ) > = pads . size ( ) | | ! data ) // data == NULL stalls on decr
2018-04-08 22:34:37 +02:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2019-04-28 23:35:11 +02:00
if ( ! pads [ handle ] - > ldd )
return CELL_PAD_ERROR_NO_DEVICE ;
2023-02-12 11:33:23 +01:00
pads [ handle ] - > ldd_data = * data ;
2018-06-07 15:26:07 +02:00
2015-02-22 09:50:26 +01:00
return CELL_OK ;
}
2018-06-07 15:26:07 +02:00
error_code cellPadLddGetPortNo ( s32 handle )
2015-02-22 09:50:26 +01:00
{
2019-04-28 23:35:11 +02:00
sys_io . trace ( " cellPadLddGetPortNo(handle=%d) " , handle ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-12-13 06:24:17 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2023-02-10 02:40:54 +01:00
auto & pads = handler - > GetPads ( ) ;
2018-12-13 06:24:17 +01:00
2023-02-10 02:40:54 +01:00
if ( handle < 0 | | static_cast < u32 > ( handle ) > = pads . size ( ) )
2018-06-07 15:26:07 +02:00
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2019-04-28 23:35:11 +02:00
if ( ! pads [ handle ] - > ldd )
return CELL_PAD_ERROR_FATAL ; // might be incorrect
// Other possible return values: CELL_PAD_ERROR_EBUSY, CELL_EBUSY
return not_an_error ( handle ) ; // handle is port
2015-02-22 09:50:26 +01:00
}
2018-06-07 15:26:07 +02:00
error_code cellPadLddUnregisterController ( s32 handle )
2015-02-22 09:50:26 +01:00
{
2019-04-28 23:35:11 +02:00
sys_io . warning ( " cellPadLddUnregisterController(handle=%d) " , handle ) ;
2015-02-22 09:50:26 +01:00
2018-12-17 19:13:35 +01:00
std : : lock_guard lock ( pad : : g_pad_mutex ) ;
2021-03-02 12:59:19 +01:00
auto & config = g_fxo - > get < pad_info > ( ) ;
2019-08-25 14:42:22 +02:00
2021-03-02 12:59:19 +01:00
if ( ! config . max_connect )
2015-02-22 09:50:26 +01:00
return CELL_PAD_ERROR_UNINITIALIZED ;
2018-12-13 06:24:17 +01:00
const auto handler = pad : : get_current_handler ( ) ;
2019-04-28 23:35:11 +02:00
const auto & pads = handler - > GetPads ( ) ;
2023-02-10 02:40:54 +01:00
if ( handle < 0 | | static_cast < u32 > ( handle ) > = pads . size ( ) )
return CELL_PAD_ERROR_INVALID_PARAMETER ;
2021-08-08 18:50:37 +02:00
2019-04-28 23:35:11 +02:00
if ( ! pads [ handle ] - > ldd )
return CELL_PAD_ERROR_NO_DEVICE ;
handler - > UnregisterLddPad ( handle ) ;
2024-01-01 08:18:55 +01:00
cellPad_NotifyStateChange ( handle , CELL_PAD_STATUS_DISCONNECTED , false ) ;
2018-06-07 15:26:07 +02:00
2015-02-22 09:50:26 +01:00
return CELL_OK ;
}
2019-09-29 09:58:21 +02:00
error_code cellPadFilterIIRInit ( vm : : ptr < CellPadFilterIIRSos > pSos , s32 cutoff )
{
sys_io . todo ( " cellPadFilterIIRInit(pSos=*0x%x, cutoff=%d) " , pSos , cutoff ) ;
if ( ! pSos ) // TODO: does this check for cutoff > 2 ?
{
return CELL_PADFILTER_ERROR_INVALID_PARAMETER ;
}
return CELL_OK ;
}
u32 cellPadFilterIIRFilter ( vm : : ptr < CellPadFilterIIRSos > pSos , u32 filterIn )
{
sys_io . todo ( " cellPadFilterIIRFilter(pSos=*0x%x, filterIn=%d) " , pSos , filterIn ) ;
// TODO: apply filter
return std : : clamp ( filterIn , 0u , 1023u ) ;
}
2018-06-23 11:36:16 +02:00
s32 sys_io_3733EA3C ( u32 port_no , vm : : ptr < u32 > device_type , vm : : ptr < CellPadData > data )
{
2018-06-07 15:26:07 +02:00
// Used by the ps1 emulator built into the firmware
// Seems to call the same function that getdataextra does
2018-06-23 11:36:16 +02:00
sys_io . trace ( " sys_io_3733EA3C(port_no=%d, device_type=*0x%x, data=*0x%x) " , port_no , device_type , data ) ;
return cellPadGetDataExtra ( port_no , device_type , data ) ;
}
2014-09-03 18:33:30 +02:00
void cellPad_init ( )
{
2015-02-20 14:58:40 +01:00
REG_FUNC ( sys_io , cellPadInit ) ;
REG_FUNC ( sys_io , cellPadEnd ) ;
REG_FUNC ( sys_io , cellPadClearBuf ) ;
REG_FUNC ( sys_io , cellPadGetData ) ;
2015-08-01 03:46:42 +02:00
REG_FUNC ( sys_io , cellPadGetRawData ) ; //
2015-02-20 14:58:40 +01:00
REG_FUNC ( sys_io , cellPadGetDataExtra ) ;
REG_FUNC ( sys_io , cellPadSetActDirect ) ;
2015-08-01 03:46:42 +02:00
REG_FUNC ( sys_io , cellPadGetInfo ) ; //
2015-02-20 14:58:40 +01:00
REG_FUNC ( sys_io , cellPadGetInfo2 ) ;
REG_FUNC ( sys_io , cellPadPeriphGetInfo ) ;
2015-08-01 03:46:42 +02:00
REG_FUNC ( sys_io , cellPadPeriphGetData ) ;
2015-02-20 14:58:40 +01:00
REG_FUNC ( sys_io , cellPadSetPortSetting ) ;
2015-08-01 03:46:42 +02:00
REG_FUNC ( sys_io , cellPadInfoPressMode ) ; //
REG_FUNC ( sys_io , cellPadInfoSensorMode ) ; //
REG_FUNC ( sys_io , cellPadSetPressMode ) ; //
REG_FUNC ( sys_io , cellPadSetSensorMode ) ; //
REG_FUNC ( sys_io , cellPadGetCapabilityInfo ) ; //
2015-02-22 09:58:18 +01:00
REG_FUNC ( sys_io , cellPadLddRegisterController ) ;
REG_FUNC ( sys_io , cellPadLddDataInsert ) ;
REG_FUNC ( sys_io , cellPadLddGetPortNo ) ;
REG_FUNC ( sys_io , cellPadLddUnregisterController ) ;
2018-06-23 11:36:16 +02:00
2019-09-29 09:58:21 +02:00
REG_FUNC ( sys_io , cellPadFilterIIRInit ) ;
REG_FUNC ( sys_io , cellPadFilterIIRFilter ) ;
2018-06-23 11:36:16 +02:00
REG_FNID ( sys_io , 0x3733EA3C , sys_io_3733EA3C ) ;
2014-09-03 18:33:30 +02:00
}