Reference Tables

Quick reference for writing padctl device configs.

Type Mapping

Common HID representationpadctl type
unsigned byte"u8"
signed byte"i8"
16-bit unsigned, little-endian"u16le"
16-bit signed, little-endian"i16le"
16-bit unsigned, big-endian"u16be"
16-bit signed, big-endian"i16be"
single bit (boolean)button_group entry
multi-bit enum (e.g. hat switch)button_group per variant or hat field

Axis Transform

Raw typeTransform needed
u8 centered at 0x80scale(-32768, 32767)
i8 centered at 0scale(-32768, 32767)
i16le centered at 0none (already full range)
u8 trigger (0-255)none

Linux Input Event Codes

padctl buttonLinux codeNotes
ABTN_SOUTHCross on PlayStation
BBTN_EASTCircle on PlayStation
XBTN_WESTSquare on PlayStation
YBTN_NORTHTriangle on PlayStation
LBBTN_TLL1
RBBTN_TRR1
SelectBTN_SELECTShare/Create/View
StartBTN_STARTOptions/Menu
HomeBTN_MODEPS/Xbox/Guide
LSBTN_THUMBLL3 (stick click)
RSBTN_THUMBRR3 (stick click)
M1-M4BTN_TRIGGER_HAPPY1-4Back paddles / extra buttons

MSB0 to LSB0 Bit Conversion

Some HID documentation and driver source code number bits in MSB0 order (bit 0 = most-significant bit). padctl button_group indices use LSB0 (bit 0 = least-significant bit).

Single byte:

lsb_bit = 7 - msb_bit          (msb_bit in 0..=7)

Multi-byte group (source window of N bytes):

lsb_bit = (msb_bit / 8) * 8 + (7 - (msb_bit % 8))

Example — a 2-byte button field starting at offset 0:

ButtonMSB0 bitbytebit-in-byteLSB0 index
DPadRight0077
DPadLeft1066
DPadDown2055
DPadUp3044
L34033
R35022
Btn66011
Btn77000
A81715
B91614
X101513
Y111412
LB121311
RB131210
LT14119
RT15108

Common Pitfalls

  • MSB0 vs LSB0 bit order — many HID reference drivers use MSB0 bit numbering. Copying bit indices directly without converting will cause buttons to trigger on wrong inputs. Always apply the conversion formula.
  • Padding bytes — if the report is larger than the sum of declared fields, the extra bytes are padding. Do not declare fields for those offsets.
  • Multiple report IDs on one interface — each report ID needs its own [[report]] block with a [report.match] section. Without match, padctl tries to parse every incoming buffer with every report definition.
  • Split / non-contiguous fields — some devices store a single logical value across non-adjacent bytes (e.g., gyro_y with low byte at offset 18 and high byte at offset 20). padctl does not support split fields; these require a WASM plugin or a firmware mode that provides a contiguous layout.
  • Endianness of multi-byte scalars — when referencing driver source code, check whether multi-byte fields are little-endian or big-endian. The default in many packed-struct frameworks is big-endian. Use "i16be" / "u16be" for big-endian fields.
  • Analog stick center value — devices use either u8 (center = 0x80) or i8 (center = 0). Both benefit from transform = "scale(-32768, 32767)" to fill the full axis range expected by uinput.