Skip to main content

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);
}
max
u32
Maximum number of pads to support (max: 7)

Getting Controller Information

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

max
u32
Maximum pads allowed to connect
connected
u32
Number of currently connected pads
info
u32
Bit 0: System intercept flag
vendor_id
u16[127]
Array of vendor IDs for each pad
product_id
u16[127]
Array of product IDs for each pad
status
u8[127]
Connection status (0: disconnected, 1: connected)

Reading Button Input

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.

Button Mappings

Digital Button Masks

ConstantButtonOffset
PAD_CTRL_SELECTSelectDIGITAL1[0]
PAD_CTRL_L3Left stick clickDIGITAL1[1]
PAD_CTRL_R3Right stick clickDIGITAL1[2]
PAD_CTRL_STARTStartDIGITAL1[3]
PAD_CTRL_UPD-pad UpDIGITAL1[4]
PAD_CTRL_RIGHTD-pad RightDIGITAL1[5]
PAD_CTRL_DOWND-pad DownDIGITAL1[6]
PAD_CTRL_LEFTD-pad LeftDIGITAL1[7]
PAD_CTRL_L2L2 triggerDIGITAL2[0]
PAD_CTRL_R2R2 triggerDIGITAL2[1]
PAD_CTRL_L1L1 shoulderDIGITAL2[2]
PAD_CTRL_R1R1 shoulderDIGITAL2[3]
PAD_CTRL_TRIANGLETriangleDIGITAL2[4]
PAD_CTRL_CIRCLECircleDIGITAL2[5]
PAD_CTRL_CROSSCross (X)DIGITAL2[6]
PAD_CTRL_SQUARESquareDIGITAL2[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

Pressure-Sensitive Buttons

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
u8
Small motor: 0 = OFF, 1 = ON
large_motor
u8
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:
ioPadEnd();

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

ioPadInit
s32 ioPadInit(u32 max)
Initialize pad I/O management with max controllers
ioPadEnd
s32 ioPadEnd()
End pad I/O management

Information Functions

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
ioPadGetDataExtra
s32 ioPadGetDataExtra(u32 port, u32* type, padData* data)
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

ConstantValueDescription
PAD_OK0Success
PAD_ERROR_FATAL0x80121101Fatal error
PAD_ERROR_INVALID_PARAMETER0x80121102Invalid parameter
PAD_ERROR_ALREADY_INITIALIZED0x80121103Already initialized
PAD_ERROR_NOT_INITIALIZED0x80121104Not initialized

See Also

Build docs developers (and LLMs) love