Overview
The PSL1GHT SDK provides comprehensive support for PlayStation 3 controllers through the io/pad.h API. You can read button states, analog stick positions, pressure-sensitive inputs, motion sensors, and control rumble feedback.
Up to 7 controllers can be connected simultaneously (ports 0-6). The PS button is handled by the XMB system.
Initialization
Initialize the pad system before reading controller input:
#include <io/pad.h>
// Initialize with maximum number of controllers
s32 ret = ioPadInit ( 7 );
if (ret != 0 ) {
printf ( "Failed to initialize pad: %d \n " , ret);
}
Maximum number of pads to support (max: 7)
Query connected controllers and their status:
padInfo padinfo;
ioPadGetInfo ( & padinfo );
printf ( "Max pads: %u \n " , padinfo.max);
printf ( "Connected: %u \n " , padinfo.connected);
for ( int i = 0 ; i < MAX_PADS; i ++ ) {
if ( padinfo . status [i]) {
printf ( "Controller %d connected \n " , i);
printf ( " Vendor ID: %04x \n " , padinfo . vendor_id [i]);
printf ( " Product ID: %04x \n " , padinfo . product_id [i]);
}
}
padInfo Structure
Maximum pads allowed to connect
Number of currently connected pads
Bit 0: System intercept flag
Array of vendor IDs for each pad
Array of product IDs for each pad
Connection status (0: disconnected, 1: connected)
Read controller data in your game loop:
padData paddata;
s32 ret = ioPadGetData ( 0 , & paddata ); // Port 0
if (ret == 0 && paddata.len > 0 ) {
// Digital buttons
if ( paddata . BTN_CROSS ) printf ( "X pressed \n " );
if ( paddata . BTN_CIRCLE ) printf ( "O pressed \n " );
if ( paddata . BTN_TRIANGLE ) printf ( "Triangle pressed \n " );
if ( paddata . BTN_SQUARE ) printf ( "Square pressed \n " );
// D-pad
if ( paddata . BTN_UP ) printf ( "Up pressed \n " );
if ( paddata . BTN_DOWN ) printf ( "Down pressed \n " );
if ( paddata . BTN_LEFT ) printf ( "Left pressed \n " );
if ( paddata . BTN_RIGHT ) printf ( "Right pressed \n " );
// Shoulder buttons
if ( paddata . BTN_L1 ) printf ( "L1 pressed \n " );
if ( paddata . BTN_R1 ) printf ( "R1 pressed \n " );
if ( paddata . BTN_L2 ) printf ( "L2 pressed \n " );
if ( paddata . BTN_R2 ) printf ( "R2 pressed \n " );
// Control buttons
if ( paddata . BTN_START ) printf ( "Start pressed \n " );
if ( paddata . BTN_SELECT ) printf ( "Select pressed \n " );
if ( paddata . BTN_L3 ) printf ( "L3 pressed \n " );
if ( paddata . BTN_R3 ) printf ( "R3 pressed \n " );
}
The padData structure is only updated when input changes. If len is 0, there was no new input since the last call.
Constant Button Offset PAD_CTRL_SELECTSelect DIGITAL1[0] PAD_CTRL_L3Left stick click DIGITAL1[1] PAD_CTRL_R3Right stick click DIGITAL1[2] PAD_CTRL_STARTStart DIGITAL1[3] PAD_CTRL_UPD-pad Up DIGITAL1[4] PAD_CTRL_RIGHTD-pad Right DIGITAL1[5] PAD_CTRL_DOWND-pad Down DIGITAL1[6] PAD_CTRL_LEFTD-pad Left DIGITAL1[7] PAD_CTRL_L2L2 trigger DIGITAL2[0] PAD_CTRL_R2R2 trigger DIGITAL2[1] PAD_CTRL_L1L1 shoulder DIGITAL2[2] PAD_CTRL_R1R1 shoulder DIGITAL2[3] PAD_CTRL_TRIANGLETriangle DIGITAL2[4] PAD_CTRL_CIRCLECircle DIGITAL2[5] PAD_CTRL_CROSSCross (X) DIGITAL2[6] PAD_CTRL_SQUARESquare DIGITAL2[7]
Analog Sticks
Read analog stick positions (0x0000 - 0x00FF):
if (paddata.len > 0 ) {
// Left analog stick
u16 left_x = paddata . ANA_L_H ; // Horizontal (0-255)
u16 left_y = paddata . ANA_L_V ; // Vertical (0-255)
// Right analog stick
u16 right_x = paddata . ANA_R_H ; // Horizontal (0-255)
u16 right_y = paddata . ANA_R_V ; // Vertical (0-255)
printf ( "Left stick: ( %d , %d ) \n " , left_x, left_y);
printf ( "Right stick: ( %d , %d ) \n " , right_x, right_y);
}
Analog Stick Values
Center : ~128
Minimum : 0
Maximum : 255
Horizontal: 0 = left, 255 = right
Vertical: 0 = up, 255 = down
Enable and read pressure sensitivity:
// Enable pressure mode
ioPadSetPressMode ( 0 , PAD_PRESS_MODE_ON);
// Read pressure values (0x0000 - 0x00FF)
if (paddata.len > 0 ) {
u16 cross_pressure = paddata . PRE_CROSS ;
u16 circle_pressure = paddata . PRE_CIRCLE ;
u16 triangle_pressure = paddata . PRE_TRIANGLE ;
u16 square_pressure = paddata . PRE_SQUARE ;
u16 l1_pressure = paddata . PRE_L1 ;
u16 r1_pressure = paddata . PRE_R1 ;
u16 l2_pressure = paddata . PRE_L2 ;
u16 r2_pressure = paddata . PRE_R2 ;
// D-pad pressure
u16 up_pressure = paddata . PRE_UP ;
u16 down_pressure = paddata . PRE_DOWN ;
u16 left_pressure = paddata . PRE_LEFT ;
u16 right_pressure = paddata . PRE_RIGHT ;
}
Motion Sensors (SIXAXIS)
Enable and read accelerometer and gyroscope data:
// Enable sensor mode
ioPadSetSensorMode ( 0 , PAD_SENSOR_MODE_ON);
// Read sensor values (0x0000 - 0x03FF)
if (paddata.len > 0 ) {
u16 sensor_x = paddata . SENSOR_X ; // X-axis acceleration
u16 sensor_y = paddata . SENSOR_Y ; // Y-axis acceleration
u16 sensor_z = paddata . SENSOR_Z ; // Z-axis acceleration
u16 sensor_g = paddata . SENSOR_G ; // Gyroscope
printf ( "Motion: X= %d Y= %d Z= %d G= %d \n " ,
sensor_x, sensor_y, sensor_z, sensor_g);
}
Sensor Axes
X : Left/Right tilt
Y : Forward/Backward tilt
Z : Up/Down movement
G : Rotation/gyroscope
Rumble (Vibration)
Control the small and large rumble motors:
padActParam actparam;
// Small motor (on/off only)
actparam.small_motor = 1 ; // 0: OFF, 1: ON
actparam.large_motor = 0 ; // 0-255: speed (0 = OFF)
ioPadSetActDirect ( 0 , & actparam );
usleep ( 500000 ); // Vibrate for 0.5 seconds
// Large motor (variable speed)
actparam.small_motor = 0 ;
actparam.large_motor = 255 ; // Maximum speed
ioPadSetActDirect ( 0 , & actparam );
usleep ( 500000 );
// Stop rumble
actparam.small_motor = 0 ;
actparam.large_motor = 0 ;
ioPadSetActDirect ( 0 , & actparam );
Small motor: 0 = OFF, 1 = ON
Large motor: 0 = OFF, 1-255 = speed (higher = faster)
Controller Capabilities
Check what features a controller supports:
padCapabilityInfo capabilities;
ioPadGetCapabilityInfo ( 0 , & capabilities );
if (capabilities.ps3spec) {
printf ( "PS3-compliant controller \n " );
}
if (capabilities.has_pressure) {
printf ( "Supports pressure-sensitive buttons \n " );
}
if (capabilities.has_sensors) {
printf ( "Supports motion sensors (SIXAXIS) \n " );
}
if (capabilities.has_vibrate) {
printf ( "Supports vibration \n " );
}
if (capabilities.has_hps) {
printf ( "Supports high-precision sticks \n " );
}
XMB Integration
The PS button is intercepted by the XMB system and cannot be read directly by applications. When pressed, it opens the XMB menu overlay.
You cannot read or block the PS button. The system always intercepts it for XMB access.
BD Remote Support
The SDK also supports Blu-ray remote controllers:
if (padinfo. status [i]) {
u32 device_type = padinfo2 . device_type [i];
if (device_type == PAD_TYPE_REMOTE) {
// BD Remote detected
if ( paddata . len > 0 ) {
u16 bd_code = paddata . BTN_BDCODE ;
switch (bd_code) {
case BTN_BD_PLAY:
printf ( "Play pressed \n " );
break ;
case BTN_BD_STOP:
printf ( "Stop pressed \n " );
break ;
// ... more BD remote buttons
}
}
}
}
Cleanup
Shut down the pad system when done:
Complete Example
Here’s a complete controller reading example from samples/input/padtest/:
#include <io/pad.h>
#include <stdio.h>
#include <unistd.h>
int main () {
padInfo padinfo;
padData paddata;
// Initialize
if ( ioPadInit ( 7 ) != 0 ) {
printf ( "Failed to initialize pad \n " );
return 1 ;
}
// Get info
ioPadGetInfo ( & padinfo);
printf ( "Max pads: %u , Connected: %u \n " ,
padinfo . max , padinfo . connected );
// Check each controller
for ( int i = 0 ; i < MAX_PADS; i ++ ) {
if ( padinfo . status [i]) {
printf ( "Controller %d : \n " , i);
printf ( " Vendor: %04x , Product: %04x \n " ,
padinfo . vendor_id [i],
padinfo . product_id [i]);
// Read initial state
ioPadGetData (i, & paddata);
printf ( " Data length: %d \n " , paddata . len );
// Test rumble
padActParam actparam;
actparam . small_motor = 1 ;
actparam . large_motor = 0 ;
ioPadSetActDirect (i, & actparam);
usleep ( 500000 );
actparam . small_motor = 0 ;
actparam . large_motor = 255 ;
ioPadSetActDirect (i, & actparam);
usleep ( 500000 );
// Stop rumble
actparam . small_motor = 0 ;
actparam . large_motor = 0 ;
ioPadSetActDirect (i, & actparam);
}
}
// Cleanup
ioPadEnd ();
return 0 ;
}
API Reference
Initialization Functions
Initialize pad I/O management with max controllers
ioPadGetInfo
s32 ioPadGetInfo(padInfo* info)
Get pad information (old format)
ioPadGetInfo2
s32 ioPadGetInfo2(padInfo2* info)
Get pad information (new format, firmware 3.41+)
ioPadGetCapabilityInfo
s32 ioPadGetCapabilityInfo(u32 port, padCapabilityInfo* capabilities)
Get controller capability information
Data Reading Functions
ioPadGetData
s32 ioPadGetData(u32 port, padData* data)
Get pad data from specified port
Get pad data with device type
ioPadClearBuf
s32 ioPadClearBuf(u32 port)
Clear the pad input buffer
Configuration Functions
ioPadSetPressMode
s32 ioPadSetPressMode(u32 port, u32 mode)
Enable/disable pressure-sensitive mode
ioPadSetSensorMode
s32 ioPadSetSensorMode(u32 port, u32 mode)
Enable/disable motion sensor mode
ioPadSetActDirect
u32 ioPadSetActDirect(u32 port, padActParam* actParam)
Set rumble/vibration parameters
Error Codes
Constant Value Description PAD_OK0 Success PAD_ERROR_FATAL0x80121101 Fatal error PAD_ERROR_INVALID_PARAMETER0x80121102 Invalid parameter PAD_ERROR_ALREADY_INITIALIZED0x80121103 Already initialized PAD_ERROR_NOT_INITIALIZED0x80121104 Not initialized
See Also