Playstation 2 (Dual Shock) controller protocol notes

There are many sources for information on the basics of the
Playstation controller protocol. There is frustratingly little,
however, in the way of comprehensive documentation for the
controller's full command set.

This document is a rather loose collection of reverse-engineering
notes, documenting a larger subset of the PS2 and Dual Shock
protocols than I've seen elsewhere. The reader should already be
familiar with the basics of the Playstation controller protocol.

This document has three primary sources:

Publicly available documents such as Playstation.txt

Traces from a homebrew PS2 controller/memory port sniffer

Interactively experimenting with a controller connected
to both the above port sniffer and an arbitrary packet
generator.

Since the Playstation always transmits and receives simultaneously,
this document uses TX/RX notation, where "TX" is the hexidecimal
command byte being transmitted to the controller and "RX" is the
hexadecimal response byte. A "|" character is often used to separate
the header from a command's payload, but it has no electrical
significance.

The byte 0x5A seems to be used as padding in several situations.
Besides end-of-header, it seems to be sent by the PS2 when the
controller (via the low nybble of the second response byte) indicates
it has more data to reply with, but the PS2 has no more parameter
data to send.

Device modes:

0x4: Digital
0x7: Dual shock
0xF: Escape

Note that the command byte and the mode/length byte are transferred
simultaneously. This means that the length of the reply cannot directly
depend on the command you just sent! This is probably the reason why
all escape-mode commands are the same length: the reply length can be
calculated using only the current mode, without any need to know which
command is being replied to.

This means that the data dependencies between the command and the reply
are quite small. The controller needs to process the command byte by the
time the first command-specific reply byte is sent, and it needs to
validate each byte in the header just enough to know whether that byte
gets to be ACK'ed. There are no sub-byte data dependencies, and there is
an entire byte of slack between the command and the command-specific
data.

Packet reference:

0x40 Initialize pressure sensor

Only ACK'ed when the controller is in escape mode (0xF)

01/ff 40/f3 00/5a | 00/00 02/00 00/02 00/00 00/00 00/5a

This command sets up parameters for a single pressure-sensitive
button. Note that it is not required in order to use pressure
sensitive buttons, and that this command by itself will not
enable them. You still need to use command 0x4f to add them
to the controller's results packet.

Command data:

Button number (0x00 - 0x0b, in the same order that
the buttons are listed in the response packet)

This command reads some unknown identifier or status block.
The block is 10 bytes long, and has a constant value on
every controller and operating mode I've tested:

00 00 04 00 00
00 00 07 00 10

0x4d Specify polling command format

Only ACK'ed when the controller is in escape mode (0xF)

01/ff 4d/f3 00/5a | 00/00 01/01 ff/ff ff/ff ff/ff ff/ff

This command sets up a mapping between bytes in each
controller poll (Command 0x42) and the controller's actuator
channels. Each data byte in this command dictates the meaning
of the corresponding data byte in command 0x42.

For the Dual Shock controller, this command can specify
the following actuator channels:

00: Small vibration motor, with no speed control.

If this channel is set to 0xFF, the small motor
turns on. Any other value turns it off.

01: Larger vibration motor, with 8-bit variable speed.

ff: Disabled

The example packet above is typical for a Dual Shock
controller.

This command's response packet is the previous actuator
mapping. By default all channels are disabled, so when
this command is run immediately after switching into
DualShock mode it will return all 0xFF.

0x4f Specify polling result format

Only ACK'ed when the controller is in escape mode (0xF)

01/ff 4f/f3 00/5a | ff/00 ff/00 03/00 00/00 00/00 00/5a

Command data:

Bitfield indicating which bytes in the response packet
should be included. This lets the host instruct the
controller to include more or less data than it would
by default. This command is used to enable pressure-
sensitive buttons, and it can be used to disable any of
the default response bytes.