Xbox Elite Wireless Controller Series 2 — report descriptor, as captured 2026-08-09.

HOW THIS WAS TAKEN
  box        .173, Windows 11 26200, German locale
  pad        Xbox Elite Wireless Controller Series 2, VID 045E PID 0B22, HID rev 0x0521,
             BD_ADDR 686CE647F191, paired and connected over BLUETOOTH LOW ENERGY (HID-over-GATT).
             Windows enumerates it as BTHLEDEVICE\{00001812-...}, NOT classic BTHENUM.
  command    hid-descriptor-dump --vid 045E --pid 0B22 --name XBOX_ELITE2_RDESC
  tool       tools/hid-descriptor-dump (this directory)

⚠️ WHAT THIS IS AND IS NOT — READ BEFORE COPYING BYTES OUT OF IT.
Windows exposes no API returning a device's literal report-descriptor bytes: the HID class driver
keeps only the parsed form, so hidapi RECONSTRUCTS a descriptor from HidD_GetPreparsedData. The
reconstruction is faithful in STRUCTURE, ITEM ORDER and every field's BIT OFFSET; the byte encoding
is not the wire encoding. Measured proof, from the same run against the DualSense on the same box:
its real descriptor is 273 bytes and the reconstruction came back 467, because the reconstructor
re-states global items (Logical Min/Max, Report Size) before every report instead of letting them
persist. Same layout, different bytes.
⇒ DIFF THE LAYOUT TABLE, NOT THE RAW BYTES. A byte-exact capture needs Linux
  /sys/class/hidraw/hidrawN/device/report_descriptor.

⚠️ UNVERIFIED: whether this equals the pad's NATIVE report map. `xinputhid` is attached as an
UpperFilter on this pad's BLE transport node (DevicePropertyFlags=0x1 "BusDevice"), and the shape
below — one combined 16-bit `Z` trigger axis, 16 buttons, no report id, no OUTPUT collection — is
the classic legacy/DirectInput view rather than the two-separate-triggers layout documented for
Xbox pads over classic Bluetooth. The absence of ANY output collection is the tell: a real Xbox BT
pad does accept rumble output reports, and this view offers nowhere to send them. Cross-check on
Linux hidraw before treating this as the native map.


================================================================================================
COLLECTION 1/2  —  045E:0B22  usage_page 0x0001 (Generic Desktop) usage 0x0005
  manufacturer : Microsoft
  product      : Xbox Wireless Controller
  serial       : 686ce647f191
  release      : 0x0521
  interface    : -1
  path         : \\?\HID#{00001812-0000-1000-8000-00805f9b34fb}&Dev&VID_045e&PID_0b22&REV_0521&686ce647f191&Col01&IG_00#c&7384879&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
================================================================================================

-- RAW (117 bytes) --
  0000  05 01 09 05 A1 01 09 00 A1 00 09 30 09 31 15 00
  0010  25 FF 35 00 45 FF 75 10 95 02 81 02 C0 09 00 A1
  0020  00 09 33 09 34 15 00 25 FF 75 10 95 02 81 02 C0
  0030  09 00 A1 00 09 32 15 00 25 FF 75 10 95 01 81 02
  0040  C0 05 09 19 01 29 10 15 00 25 01 75 01 95 10 45
  0050  00 81 02 05 01 09 39 15 01 25 08 35 00 46 3B 10
  0060  65 0E 75 04 95 01 81 42 75 04 95 01 81 03 75 08
  0070  95 02 81 03 C0

-- ITEMS --
0x05, 0x01,                            // Usage Page (Generic Desktop)
0x09, 0x05,                            // Usage (Game Pad)
0xA1, 0x01,                            // Collection (Application)
0x09, 0x00,                            //   Usage (0x00)
0xA1, 0x00,                            //   Collection (Physical)
0x09, 0x30,                            //     Usage (X)
0x09, 0x31,                            //     Usage (Y)
0x15, 0x00,                            //     Logical Minimum (0)
0x25, 0xFF,                            //     Logical Maximum (-1 — unsigned reading: 255)
0x35, 0x00,                            //     Physical Minimum (0)
0x45, 0xFF,                            //     Physical Maximum (-1)
0x75, 0x10,                            //     Report Size (16)
0x95, 0x02,                            //     Report Count (2)
0x81, 0x02,                            //     Input (Data,Var,Abs)
0xC0,                                  //   End Collection
0x09, 0x00,                            //   Usage (0x00)
0xA1, 0x00,                            //   Collection (Physical)
0x09, 0x33,                            //     Usage (Rx)
0x09, 0x34,                            //     Usage (Ry)
0x15, 0x00,                            //     Logical Minimum (0)
0x25, 0xFF,                            //     Logical Maximum (-1 — unsigned reading: 255)
0x75, 0x10,                            //     Report Size (16)
0x95, 0x02,                            //     Report Count (2)
0x81, 0x02,                            //     Input (Data,Var,Abs)
0xC0,                                  //   End Collection
0x09, 0x00,                            //   Usage (0x00)
0xA1, 0x00,                            //   Collection (Physical)
0x09, 0x32,                            //     Usage (Z)
0x15, 0x00,                            //     Logical Minimum (0)
0x25, 0xFF,                            //     Logical Maximum (-1 — unsigned reading: 255)
0x75, 0x10,                            //     Report Size (16)
0x95, 0x01,                            //     Report Count (1)
0x81, 0x02,                            //     Input (Data,Var,Abs)
0xC0,                                  //   End Collection
0x05, 0x09,                            //   Usage Page (Button)
0x19, 0x01,                            //   Usage Minimum (1)
0x29, 0x10,                            //   Usage Maximum (16)
0x15, 0x00,                            //   Logical Minimum (0)
0x25, 0x01,                            //   Logical Maximum (1)
0x75, 0x01,                            //   Report Size (1)
0x95, 0x10,                            //   Report Count (16)
0x45, 0x00,                            //   Physical Maximum (0)
0x81, 0x02,                            //   Input (Data,Var,Abs)
0x05, 0x01,                            //   Usage Page (Generic Desktop)
0x09, 0x39,                            //   Usage (Hat switch)
0x15, 0x01,                            //   Logical Minimum (1)
0x25, 0x08,                            //   Logical Maximum (8)
0x35, 0x00,                            //   Physical Minimum (0)
0x46, 0x3B, 0x10,                      //   Physical Maximum (4155)
0x65, 0x0E,                            //   Unit (0xE)
0x75, 0x04,                            //   Report Size (4)
0x95, 0x01,                            //   Report Count (1)
0x81, 0x42,                            //   Input (Data,Var,Abs,Null State)
0x75, 0x04,                            //   Report Size (4)
0x95, 0x01,                            //   Report Count (1)
0x81, 0x03,                            //   Input (Cnst,Var,Abs)
0x75, 0x08,                            //   Report Size (8)
0x95, 0x02,                            //   Report Count (2)
0x81, 0x03,                            //   Input (Cnst,Var,Abs)
0xC0,                                  // End Collection

-- LAYOUT --

  Input report 0x00 — 120 bits, 15 bytes on the wire (unnumbered)
    byte.bit     size×cnt  usage                      logical range        flags
    0.0          16×2      X, Y                       0..-1                Data,Var,Abs
    4.0          16×2      Rx, Ry                     0..-1                Data,Var,Abs
    8.0          16×1      Z                          0..-1                Data,Var,Abs
    10.0         1×16      Button 1..16               0..1                 Data,Var,Abs
    12.0         4×1       Hat switch                 1..8                 Data,Var,Abs,Null State
    12.4         4×1       — (padding)                1..8                 Cnst,Var,Abs
    13.0         8×2       — (padding)                1..8                 Cnst,Var,Abs

-- SUMMARY --
  INPUT    items: 7
  OUTPUT   items: 0   <-- NONE
  FEATURE  items: 0   <-- NONE
  structure: OK

-- RUST --
#[rustfmt::skip]
static XBOX_ELITE2_RDESC_COL01: [u8; 117] = [
    0x05, 0x01, 0x09, 0x05, 0xA1, 0x01, 0x09, 0x00, 0xA1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x15, 0x00, 
    0x25, 0xFF, 0x35, 0x00, 0x45, 0xFF, 0x75, 0x10, 0x95, 0x02, 0x81, 0x02, 0xC0, 0x09, 0x00, 0xA1, 
    0x00, 0x09, 0x33, 0x09, 0x34, 0x15, 0x00, 0x25, 0xFF, 0x75, 0x10, 0x95, 0x02, 0x81, 0x02, 0xC0, 
    0x09, 0x00, 0xA1, 0x00, 0x09, 0x32, 0x15, 0x00, 0x25, 0xFF, 0x75, 0x10, 0x95, 0x01, 0x81, 0x02, 
    0xC0, 0x05, 0x09, 0x19, 0x01, 0x29, 0x10, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x10, 0x45, 
    0x00, 0x81, 0x02, 0x05, 0x01, 0x09, 0x39, 0x15, 0x01, 0x25, 0x08, 0x35, 0x00, 0x46, 0x3B, 0x10, 
    0x65, 0x0E, 0x75, 0x04, 0x95, 0x01, 0x81, 0x42, 0x75, 0x04, 0x95, 0x01, 0x81, 0x03, 0x75, 0x08, 
    0x95, 0x02, 0x81, 0x03, 0xC0, 
];

================================================================================================
COLLECTION 2/2  —  045E:0B22  usage_page 0x0001 (Generic Desktop) usage 0x0006
  manufacturer : Microsoft
  product      : Xbox Wireless Controller
  serial       : 686ce647f191
  release      : 0x0521
  interface    : -1
  path         : \\?\HID#{00001812-0000-1000-8000-00805f9b34fb}&Dev&VID_045e&PID_0b22&REV_0521&686ce647f191&Col02&IG_00#c&7384879&0&0001#{4d1e55b2-f16f-11cf-88cb-001111000030}\KBD
================================================================================================

-- RAW (45 bytes) --
  0000  05 01 09 06 A1 01 85 05 05 07 19 E0 29 E7 15 00
  0010  25 01 75 01 95 08 81 02 75 08 95 01 81 03 19 00
  0020  29 65 15 00 25 65 75 08 95 06 81 00 C0

-- ITEMS --
0x05, 0x01,                            // Usage Page (Generic Desktop)
0x09, 0x06,                            // Usage (Keyboard)
0xA1, 0x01,                            // Collection (Application)
0x85, 0x05,                            //   Report ID (5)
0x05, 0x07,                            //   Usage Page (Keyboard/Keypad)
0x19, 0xE0,                            //   Usage Minimum (224)
0x29, 0xE7,                            //   Usage Maximum (231)
0x15, 0x00,                            //   Logical Minimum (0)
0x25, 0x01,                            //   Logical Maximum (1)
0x75, 0x01,                            //   Report Size (1)
0x95, 0x08,                            //   Report Count (8)
0x81, 0x02,                            //   Input (Data,Var,Abs)
0x75, 0x08,                            //   Report Size (8)
0x95, 0x01,                            //   Report Count (1)
0x81, 0x03,                            //   Input (Cnst,Var,Abs)
0x19, 0x00,                            //   Usage Minimum (0)
0x29, 0x65,                            //   Usage Maximum (101)
0x15, 0x00,                            //   Logical Minimum (0)
0x25, 0x65,                            //   Logical Maximum (101)
0x75, 0x08,                            //   Report Size (8)
0x95, 0x06,                            //   Report Count (6)
0x81, 0x00,                            //   Input (Data,Arr,Abs)
0xC0,                                  // End Collection

-- LAYOUT --

  Input report 0x05 — 64 bits, 9 bytes on the wire (id included)
    byte.bit     size×cnt  usage                      logical range        flags
    1.0          1×8       Keyboard/Keypad 224..231   0..1                 Data,Var,Abs
    2.0          8×1       — (padding)                0..1                 Cnst,Var,Abs
    3.0          8×6       Keyboard/Keypad 0..101     0..101               Data,Arr,Abs

-- SUMMARY --
  INPUT    items: 3
  OUTPUT   items: 0   <-- NONE
  FEATURE  items: 0   <-- NONE
  structure: OK

-- RUST --
#[rustfmt::skip]
static XBOX_ELITE2_RDESC_COL02: [u8; 45] = [
    0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x85, 0x05, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 
    0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x75, 0x08, 0x95, 0x01, 0x81, 0x03, 0x19, 0x00, 
    0x29, 0x65, 0x15, 0x00, 0x25, 0x65, 0x75, 0x08, 0x95, 0x06, 0x81, 0x00, 0xC0, 
];
