DualSense descriptor

August 3, 2021 ยท View on GitHub

desktop desktop_gamepad 1 desktop_x desktop_y desktop_z desktop_rz desktop_rx desktop_ry 0 255 8 6
<!-- 8-bit Report Sequence ID (increments by 1 between reports) -->
<usage_page>FF00<!-- FF00h, vendor-defined --></usage_page>
<usage>20</usage>
<report_count>1</report_count>
<input>
  <variable/>
</input>

<!-- D-Pad -->
<usage_page>desktop<!-- Generic desktop controls (01h) --></usage_page>
<usage>desktop_hat_switch<!-- Hat switch (39h, dynamic value) --></usage>
<logical_minimum>0</logical_minimum>
<logical_maximum>7</logical_maximum>
<physical_minimum>0</physical_minimum>
<physical_maximum>315</physical_maximum>
<unit>
  <english_rotation>
    <degrees/>
  </english_rotation>
</unit>
<report_size>4</report_size>
<report_count>1</report_count>
<input>
  <variable/>
  <null_state/>
</input>
<unit>
  <none/>
</unit>

<!-- Buttons -->
<!-- S X O T L1 R1 L2 R2 SHR OPT L3 R3 PS TP MIC -->
<usage_page>button<!-- Button (09h) --></usage_page>
<usage_minimum>01</usage_minimum>
<usage_maximum>0F</usage_maximum>
<logical_minimum>0</logical_minimum>
<logical_maximum>1</logical_maximum>
<report_size>1</report_size>
<report_count>15</report_count>
<input>
  <variable/>
</input>

<!-- Padding for buttons (?) -->
<usage_page>FF00<!-- FF00h, vendor-defined --></usage_page>
<usage>21</usage>
<report_count>13</report_count>
<input>
  <variable/>
</input>

<!-- Extended Report -->
<!--
typedef struct {
    union {
        struct {
            int16_t pitch;
            int16_t yaw;
            int16_t roll;
        };
        struct {
            int16_t x;
            int16_t y; // up
            int16_t z;
        };
    };
} ds5_vec3_t;

typedef struct {
    union {
        int16_t raw[6];
        struct {
            ds5_vec3_t gyro;
            ds5_vec3_t accel;
        };
    };
} ds5_imu_t;

typedef struct {
    uint32_t pos[2]; // probably the same as ds4 (i.e. yyyyyyyyyyyyxxxxxxxxxxxxrsssssss, r: released, s: sequence_id). Too lazy to check...
    uint8_t touch_timestamp;
} ds5_touch_t;

typedef struct {
    uint32_t coarse_timestamp; // 1/256 seconds? random value on startup?
    ds5_imu_t imu_data; // TODO calibrations?
    uint32_t fine_timestamp; // 1/3 us increments
    uint8_t TODO1; // seems to change between 8 and 18. Could be battery and charging related.
    ds5_touch_t touchpad_data;
    uint8_t TODO2[7]; // reads 09090000000000
    uint32_t another_fine_timestamp; // 1/3 us increments. Seems to have a delay of couple us compare to fine_timestamp.
    uint8_t TODO3; // 0x28 or 0x17 for me.
    uint8_t state_ext; // optional peripheral state. 0x08: nothing, 0x09: trs 3.5mm connector, 0x0b: trrs 3.5mm connector
    uint8_t TODO4; // padding?
    uint8_t checksum[8]; // custom poly crc64? some sort of MAC?
} ds5_ext_report_t;
-->
<usage_page>FF00<!-- FF00h, vendor-defined --></usage_page>
<usage>22</usage>
<logical_minimum>0</logical_minimum>
<logical_maximum>255</logical_maximum>
<report_size>8</report_size>
<report_count>52</report_count>
<input>
  <variable/>
</input>
<!-- Generic Report End -->

<!-- Feedback Report (Rumble?, LED, etc.) -->
<!--
typedef struct {
    // Screw this I'll leave it to hid-sony maintainer's internal doc S:
    // No he won't implement it. So maybe use DS4Windows docs for now.
    uint8_t type; // TODO. 0x6: vibrating, 0x23: 2step
    uint8_t params[10]; // 0x6: 0: frequency (1-255), 1: off time (1-255). 0x23: 0: step1 resistance (0-15), 1: step2 resistance (0-15)
} ds5_trigger_t;

typedef struct {
    uint16_t flags; // @ 0-1. bitfield fedcba9876543210. 012: rumble emulation (seems that the lowest nibble has to be 0x7 (????????????0111) in order to trigger this), 2: trigger_r, 3: trigger_l, 8: mic_led, a: lightbar, c: player_led
    uint8_t rumble_r; // @ 2
    uint8_t rumble_l; // @ 3
    uint8_t unk3[4]; // @ 4-7
    uint8_t mic_led; // @ 8. 0: off, 1: on, 2: pulse
    uint8_t unk9; // @ 9
    ds5_trigger_t trigger_r;// 10-20
    ds5_trigger_t trigger_l; // 21-31
    uint8_t unk28[11]; // @ 32-42
    uint8_t player_led; // @ 43. 5-bit. LSB is left.
    union {
        uint8_t lightbar_rgb[3];
        struct {
            uint8_t lightbar_r;
            uint8_t lightbar_g;
            uint8_t lightbar_b;
        };
    }; // @ 44-46
} ds5_feedback_t;
-->
<report_id>2</report_id>
<usage>23</usage>
<report_count>47</report_count>
<output>
  <variable/>
</output>

<!-- Get Sensor Calibration -->
<!-- See https://github.com/torvalds/linux/blob/c500bee1c5b2f1d59b1081ac879d73268ab0ff17/drivers/hid/hid-playstation.c#L652-L668 for details -->
<!-- Last 4 bytes are CRC32 (Bluetooth-only, SBZ on USB) -->
<report_id>5</report_id>
<usage>33</usage>
<report_count>40</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>8</report_id>
<usage>34</usage>
<report_count>47</report_count>
<feature>
  <variable/>
</feature>

<!-- Get Pair Info (Device and Host BDADDR) -->
<!--
typedef struct {
    uint8_t device_bdaddr[6]; // Little endian
    uint8_t unk[3]; // seems to be constant. Purpose unknown.
    uint8_t host_bdaddr[6]; // Little endian
    uint32_t crc32_optional;
} ds5_pair_info_t;
-->
<report_id>9</report_id>
<usage>24</usage>
<report_count>19</report_count>
<feature>
  <variable/>
</feature>

<!-- Perform Easy Pair (Set Link Key) -->
<!--
typedef struct {
    uint8_t host_bdaddr[6]; // Little endian
    uint8_t link_key[16];
    uint32_t crc32_optional;
} ds5_pair_info_t;
-->
<report_id>10</report_id>
<usage>25</usage>
<report_count>26</report_count>
<feature>
  <variable/>
</feature>

<!-- Get Controller Revision -->
<!-- Mine has build timestamp 2020-05-19 02:04:33, fw vesion 0x128 (pre-PS5 launch) -->
<!-- PS5 launch bundle: 2020-08-18 06:20:29, fw vesion 0x204 (https://github.com/Ryochan7/DS4Windows/issues/1545#issuecomment-728173979)-->
<!--
typedef struct {
    char timestamp[19];
    uint32_t versions[10]; // versions[6]: firmware version
    uint32_t crc32; // 0 via USB
} ds5_revision_t;
-->
<report_id>32</report_id>
<usage>26</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>33</report_id>
<usage>27</usage>
<report_count>4</report_count>
<feature>
  <variable/>
</feature>

<!-- GET -->
<report_id>34</report_id>
<usage>40</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>128</report_id>
<usage>28</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- GET -->
<report_id>129</report_id>
<usage>29</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>130</report_id>
<usage>2A</usage>
<report_count>9</report_count>
<feature>
  <variable/>
</feature>

<!-- GET -->
<report_id>131</report_id>
<usage>2B</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>132</report_id>
<usage>2C</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- GET (DS5 returned 3 bytes?) -->
<report_id>133</report_id>
<usage>2D</usage>
<report_count>2</report_count>
<feature>
  <variable/>
</feature>

<!-- SET -->
<report_id>160</report_id>
<usage>2E</usage>
<report_count>1</report_count>
<feature>
  <variable/>
</feature>

<!-- GET -->
<report_id>224</report_id>
<usage>2F</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- Authentication Begin -->
<!-- Set Challenge -->
<!--
typedef struct {
    uint8_t request_type; // very wild guesses: 0: exchange certificate? 1: set salt? 2: actual encrypted challenge?
    uint8_t seq;
    uint8_t page;
    uint8_t payload[56];
    uint32_t checksum; // VANILLA zlib crc32
} ds4_auth_req_t;
-->
<report_id>240</report_id>
<usage>30</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- Get Response -->
<!--
typedef struct {
    uint8_t response_type; // corresponding to request type
    uint8_t seq;
    uint8_t page; // 0-3?
    uint8_t payload[56];
    uint32_t checksum; // 0 via USB, unconfirmed via Bluetooth
} ds4_auth_res_t;
-->
<report_id>241</report_id>
<usage>31</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- Get Status -->
<!--
typedef struct {
    uint8_t unk0; // 0?
    uint8_t seq;
    uint8_t status; // 0x10: ready, 0x80: wrong checksum?, 0x51: page out of order?, 0x0: ok?
    uint8_t sbz[8]; // Structure unknown
    uint32_t checksum; // 0 via USB, unconfirmed via Bluetooth
} ds4_auth_res_t;
-->
<report_id>242</report_id>
<usage>32</usage>
<report_count>15</report_count>
<feature>
  <variable/>
</feature>
<!-- Authentication End (?) -->

<!-- SET -->
<report_id>244</report_id>
<usage>35</usage>
<report_count>63</report_count>
<feature>
  <variable/>
</feature>

<!-- GET -->
<report_id>245</report_id>
<usage>36</usage>
<report_count>3</report_count>
<feature>
  <variable/>
</feature>