A PS3 VSH plugin (PRX) that lets you use Xbox 360 / XInput controllers on a PS3 with a webMAN-compatible CFW. Each USB controller is registered as a virtual ("LDD") pad through syscall 574, so games see it as a regular PS3 controller — including pressure-sensitive buttons and the PS button.
This plugin has no in-game menu. Some forks add a select+start+square menu; this codebase intentionally does not. All feedback is given through on-screen notifications.
Built in (wired XInput / XTYPE_XBOX360):
- Microsoft Xbox 360 wired pad (
045e:028e) and the many third-party pads and arcade sticks that clone it (including most generic "Xbox 360 compatible" pads and 2.4GHz receivers such as the GameSir T4 Pro/G3w and the 8BitDo USB Wireless Adapters 1/2 in X mode) - Logitech Gamepad F310 (
046d:c21d), F510 (046d:c21e), F710 (046d:c21f) and Chillstream (046d:c242) - 8BitDo pads and USB adapters in X mode: Ultimate Wireless / Pro 2
wired (
2dc8:3106), Ultimate Wireless BT dongle (2dc8:3109), Ultimate 2C 2.4GHz dongle (2dc8:301c,2dc8:310a), Ultimate 2 2.4GHz dongle (2dc8:310b), SN30 Pro (2dc8:6001) - GameSir T4 Kaleid (
3537:1004) and Nova 2 Lite (3537:100f) - PDP / Pelican: Afterglow (
0e6f:0113,0e6f:0213,0e6f:f900,12ab:0301), Rock Candy (0e6f:011f,24c6:fafe), PL-3601 TSZ (0e6f:0201), Logic3 (0e6f:0301,0e6f:0401), PDP Xbox 360 Controller (0e6f:0501) - PowerA: MINI PROEX (
24c6:5300), Pro EX (24c6:530a,24c6:531a), Mini Pro Elite (15e4:3f00), Airflo (15e4:3f0a), FUS1ON Tournament (24c6:5397) - Razer: Onza TE / Classic (
1689:fd00,1689:fd01), Sabertooth (1532:0037,1689:fe00,24c6:5d04), Atrox Arcade Stick (24c6:5000) - Hori: Fighting Stick EX2 (
0f0d:000d), Real Arcade Pro.EX (0f0d:0016), Real Arcade Pro VX (0f0d:001b), VX-SA (24c6:5501), EX 2 with Turbo (24c6:5500), Fighting Edge (24c6:5503) - Mad Catz: wired 360 pads (
0738:4716,0738:4738,1bad:f016), MicroCon (0738:4736), SFIV FightPad (0738:4728,1bad:f028), SFIV FightStick SE / TE (0738:4718,1bad:f038), JOYTECH NEO SE (0738:beef) - Thrustmaster GP XID (
044f:b326) and GPX (24c6:5b02) - Nacon GC-100XF (
11c9:55f0), BigBen XBOX 360 Controller (146b:0601), Joytech Neo-Se Take2 (162e:beef), Gamestop (1bad:f901), Tron (1bad:f903) - Music-game hardware: Harmonix Rock Band Drumkit (
1bad:0003), Harmonix Xbox 360 Controller (1bad:f900), RedOctane Guitar Hero X-plorer (1430:4748) and RedOctane Controller (1430:f801)
The authoritative list is the xpad_info[] table in
src/main.c; the IDs mirror the Linux xpad driver's
device table for wired Xbox 360 protocol devices.
Built in (Microsoft 4-pad wireless receiver / XTYPE_XBOX360W):
- Xbox 360 Wireless Receiver (
045e:0291,045e:0719) — up to 4 pads per receiver, with pad ports only being claimed when a controller actually pairs.
Additional controllers can be added without recompiling via
xpad_devices.txt (see below).
Not supported: Xbox One / GIP protocol devices (e.g. GameSir G7 SE, 8BitDo dongles in Xbox One mode), original Xbox pads, DualShock passthrough, and 8BitDo Switch mode (Nintendo protocol — use X mode instead; Switch mode fails detection or disconnects randomly by design, not by bug).
- Copy
xpad.sprxto/dev_hdd0/plugins/. - Add it to your boot plugins file (e.g.
/dev_hdd0/boot_plugins.txt):/dev_hdd0/plugins/xpad.sprx - Optionally copy
xpad_devices.txtto/dev_hdd0/plugins/and add your own controllers to it. - For experimental rumble, also copy
xpad_game.sprxto/dev_hdd0/plugins/. Do not add it to the boot plugins list — it is loaded into a game's process, not at boot. Load it into a running game through webMAN MOD's "Game Plugins" page (seegame/readme.md). Automatic injection via PS3MAPI is off by default and opt-in: create an (empty) file/dev_hdd0/plugins/xpad_auto_inject.txtto enable it. On some CFWs the PS3MAPI module-load syscall hangs inside the lv2 loader, and once that happens the console freezes on starting anything until reboot — do not enable it unless manual injection already works reliably for you. - Reboot. About ten seconds after reaching the XMB you should see
"XPAD Loaded!". If USB initialization failed you will see an error
notification instead of silence — it now includes the error code in hex
and the VID:PID it failed on. The plugin waits ~10 s for the USB
subsystem to come up and, if USBD reports it is still initializing
(
0x80110001), retries registration for up to ~30 s more, so on a slow/cold boot the "XPAD Loaded!" message may appear a little later.
When a controller is recognized you get a notification with its name, VID:PID and assigned port; you also get one when it disconnects.
0x80110006 (decimal -2146369530) is CELL_USBD_ERROR_LDD_ALREADY_REGISTERED:
a driver with the same identity is already registered — typically another
plugin claiming the same device IDs, or a leftover registration from a
previous (crashed or reloaded) plugin instance. Older builds mistook this
for "USB not ready", retried the whole registration pass — which then
always failed with the same code, because everything that had registered
successfully the first time now conflicted with itself — and gave up with
USB init failed (-2146369530) even though the controller had already
been detected. Current builds treat a conflicting device ID as
non-fatal: the entry is skipped, everything else registers, and the plugin
loads normally.
0x801100FF is returned by cellUsbdRegisterExtraLdd() when cellUsbd's
internal LDD table is full. That table is a small, fixed size shared by
every plugin on the system — retail consoles have been observed to accept
only about 22 registrations — and the plugin's built-in device list is
longer than that. Hitting the limit is therefore expected and not fatal:
every controller that registered before the table filled keeps working and
the plugin stays active; it simply cannot claim any further VID/PIDs.
Because of this budget, the device table is ordered deliberately. The
controllers people actually use — the standard Xbox 360 pad, the Logitech
wired pads, and the modern 8BitDo / GameSir 2.4GHz dongles — are listed
first so they always register. The long tail of legacy arcade sticks,
guitars and clones follows and is what gets dropped if the table fills up.
The debug log records a LDD table full, low-priority device IDs skipped
line with the count when this happens. (Earlier builds treated this error
as fatal and rolled the whole registration back, leaving the plugin
inactive even though the pad you cared about had already registered.)
User entries from xpad_devices.txt register after the built-ins, so if
the table is already full they will be dropped too. If your controller is
in the skipped tail, free up slots first — unload other plugins that
register USB drivers — so there is room for it.
The plugin writes a timestamped log of everything it does to
/dev_hdd0/plugins/xpad.log: device registration results,
probe/attach/detach events with the interface and endpoints chosen,
SET_CONFIGURATION/SET_INTERFACE completion codes, the first input report
from each pad, any USB transfer errors, and — every ~2 s — which game/app
process it loads xpad_game.sprx into for rumble (logged before the load
call, so if a launch freezes the console the last line names the process
that was being injected). Every on-screen notification also appears in the
log.
The log is rotated, not truncated, on each boot, so a freeze followed by a reboot no longer wipes the evidence:
xpad.log— the current bootxpad.log.1— the previous bootxpad.log.2— the boot before that
The two .1/.2 files are the most recent old logs; anything older is
discarded. If your console freezes when starting a game, reboot, then read
xpad.log.1 (or .2) — the last lines there show what the plugin was doing
at the moment it locked up.
If you report a problem, please attach these files (grab them with a file manager like webMAN MOD, or over FTP). Timestamps are seconds since the plugin started, so "detected, then disconnected 5 s later" is directly visible in it.
The plugin reads /dev_hdd0/plugins/xpad_devices.txt at startup. One line
per device:
VID, PID, NAME, XTYPE
0x2dc8, 0x310c, My 8BitDo pad, XTYPE_XBOX360
#starts a comment; blank lines and stray spaces/quotes are tolerated; names may contain commas.- Duplicates of built-in devices are skipped silently; other problems (bad values, duplicate lines, unsupported types) produce a notification naming the line, and a summary is shown after boot.
The XBOX360 vs XBOX360W rule: XTYPE_XBOX360W selects the Microsoft
4-pad wireless receiver protocol (connect events, different report
layout). Third-party 2.4GHz dongles — 8BitDo, GameSir and friends — always
speak the plain wired XInput protocol, even though the pad itself is
wireless, so they must be XTYPE_XBOX360. Classifying a dongle as
XBOX360W yields exactly the classic symptoms: pad never registers, or
"disconnects out of nowhere". The parser enforces this: a non-Microsoft
VID marked XBOX360W is registered as wired with a warning. A pad whose
wired and dongle modes share one VID/PID (e.g. 8BitDo Ultimate,
2dc8:3106) needs only one line.
- Plug the pad into the PS3: if any registered driver matches, the attach
notification shows
NAME (VID:PID). - Otherwise: Windows Device Manager → controller → Details → Hardware IDs
(
VID_2DC8&PID_310C), orlsusbon Linux.
Standard XInput-to-DualShock mapping (A=Cross, B=Circle, X=Square, Y=Triangle, triggers = L2/R2 with analog pressure, sticks 1:1).
The Xbox Guide button acts as the PS/Home button — both report parsers
set CELL_PAD_CTRL_LDD_PS, which is the documented mechanism for virtual
pads to raise the PS button. Single press opens the XMB; long-press
behavior (quit-game menu) is untested on the LDD path.
The controller LED shows the assigned port (1–4). With more than four pads, two controllers will share an LED pattern — there are only four.
-
Rumble is implemented but not yet hardware-verified.
cellPadSetActDirectdata sent by games is not delivered to LDD (virtual) pads by the OS, so the VSH driver alone has no channel to receive actuator values. Rumble therefore uses the two-plugin design OsirisX's later PS3xPAD releases shipped (see TODO §8):xpad.sprx(this driver, in VSH) owns the USB pads, sends the USB rumble commands, and creates a named lv2 event queue for actuator values;xpad_game.sprx(ingame/, loaded into the game's process) hookscellPadSetActDirect, maps the game's motor values and forwards them to the driver over that queue.
Both are written and share one IPC contract (
src/xpad_rumble.h). The low-level pieces (USB packets, the game-side hook) still need validation on real hardware, so treat rumble as experimental. Seegame/readme.mdfor how to load the game plugin. The recommended way to load it is manually through webMAN MOD's "Game Plugins" page once the game is running. The VSH driver can also injectxpad_game.sprxautomatically via PS3MAPI a few seconds after a game starts, but this is opt-in and off by default (create an empty/dev_hdd0/plugins/xpad_auto_inject.txtto enable it): on some CFWs the PS3MAPILOAD_PROC_MODULEsyscall hangs inside the lv2 loader even against a fully-settled game, and a wedged loader blocks every subsequent process launch, so the console freezes on starting anything until reboot. The settle delay and the dedicated injection thread reduce the blast radius (input keeps working) but cannot prevent that kernel-side wedge, hence the opt-in. Auto-injection needsxpad_game.sprxpresent in/dev_hdd0/plugins/and a CFW with PS3MAPI (Cobra/Mamba; webMAN MOD). -
Motion sensors report neutral values.
-
2.4GHz dongles stay enumerated when the pad powers off, so a sleeping pad keeps its PS3 port until the dongle is unplugged.
-
Up to 7 controllers (
CELL_PAD_MAX_PORT_NUM) total.
The plugin is built with the official Sony PS3 SDK (Cell SDK) — not PSL1GHT.
The Makefile uses the SDK's own build system
($(CELL_SDK)/samples/mk/sdk.makedef.mk) and the GCC PPU toolchain
(ppu-lv2-gcc & co.; CELL_BUILD_TOOLS = GCC is already set, so the SNC
compiler is not needed). Signing the PRX into a loadable .sprx is done
with scetool.
-
Sony PS3 SDK (Cell SDK), version 3.55 or later, installed with:
- the GCC PPU toolchain (
ppu-lv2-gcc,ppu-lv2-ld,ppu-lv2-strip, …) — in some SDK installers this is an optional component, so make sure it's selected; - the samples directory (the Makefile includes
samples/mk/).
The SDK is Sony-proprietary and cannot be redistributed here; you must obtain it yourself.
- the GCC PPU toolchain (
-
GNU Make — included with the SDK's host tools on Windows (Cygwin-based), or your distro's
makeon Linux. -
scetool with its
data/keys directory populated (the required encryption keys are not bundled with scetool and must be supplied separately).
-
Install the SDK to a path without spaces, e.g.
C:\usr\local\cellon Windows or/usr/local/cellon Linux. -
Set the
CELL_SDKenvironment variable to the SDK root (the Sony installer normally does this for you):# Windows (cmd) set CELL_SDK=C:/usr/local/cell # Linux / Cygwin export CELL_SDK=/usr/local/cellNote the forward slashes on Windows — the SDK makefiles expect them.
-
Add the toolchain and host tools to your PATH:
# Windows (cmd) set PATH=%CELL_SDK%\host-win32\ppu\bin;%CELL_SDK%\host-win32\bin;%PATH% # Linux export PATH=$CELL_SDK/host-linux/ppu/bin:$CELL_SDK/host-linux/bin:$PATH -
Verify the toolchain is reachable:
ppu-lv2-gcc --version -
Install scetool and put it on your PATH too. Place the key files in its
data/directory (next to the scetool binary). Runscetoolwith no arguments to confirm it starts and lists its keys. -
Build:
cd src makeThis compiles
libc.candmain.c, linksxpad.prx, strips it, and invokes scetool to sign it intoxpad.sprx(the scetool flags in the Makefile produce a CFW-loadable SPRX for firmware 3.55+). -
Grab the output. You should now have in
src/:xpad.prx— the raw, unsigned PRX (not directly usable);xpad.sprx— the signed plugin. This is the file you copy to/dev_hdd0/plugins/(see Installation).
-
Rebuilding: run
make cleanfirst if you change headers or Makefile flags, thenmakeagain.
The game-process plugin builds the same way with its own Makefile:
cd game
make
This produces game/xpad_game.sprx. It links only -lio_stub (plus the
shared src/libc.c) and reuses the same scetool signing as the VSH plugin.
Copy xpad_game.sprx to /dev_hdd0/plugins/. See
game/readme.md for how it is loaded and its current
status.
sdk.makedef.mk: No such file or directory—CELL_SDKis unset or points to the wrong directory, or the SDK was installed without thesamples/component.ppu-lv2-gcc: command not found— the GCC PPU toolchain is not on your PATH (step 3), or the SDK was installed with only the SNC compiler; re-run the installer and add the GCC toolchain.scetool: command not found, or scetool errors about missing keys — scetool isn't on your PATH, or itsdata/keys directory is missing or incomplete. Note that in this casexpad.prxstill builds; only the signing step fails.- Random makefile errors on Windows — usually a space in the SDK path or
a non-SDK
makeearlier in the PATH shadowing the Cygwin one.
- Report structures from Colin Munro's Xbox360Controller driver for macOS.
- Device IDs from the Linux
xpaddriver. getNIDfunc/notification technique from webMAN-MOD.