└── README.md /README.md: -------------------------------------------------------------------------------- 1 | Xbox One Controller Protocol 2 | ============================ 3 | 4 | 5 | This information is result of brute force reverse engineering of XBox One Controller protocol. This is done by sending lots of different packets to the controller and observing results. This document lists some known packets and what they do. There is also a list of packets that controller can send back to computer. This document is incomplete and contains errors. 6 | 7 | Each packet begins with single byte that tells what type of packet it is. I will call this byte packet type. This code is 5 bits long, so there are maximum of 32 different packet types. First 3 bits are dummy, so they don't matter at all. 8 | 9 | The controller rumble effects are really complex. Some packets that don't play the same effect every time. Also delays between some packets can alter the played effect. 10 | 11 | **Packet notation** 12 | 13 | D means dummy bit, that doesn't have any effect. Some packets are listed as C++ source code. 14 | 15 | **Rumble naming:** 16 | 17 | lT = left trigger 18 | rT = right trigger 19 | L = left motor 20 | R = right motor 21 | 22 | Different packet types + examples 23 | ================================= 24 | 25 | 0x04: Start controller (no input) 26 | --------------------------------- 27 | > BIN: DDD0 0100 DD1D D000 28 | 29 | > HEX: 0x04 0x20 30 | 31 | Starts controller's light but controller will not start sending any input events. 32 | 33 | 34 | 0x05: Start controller (with input) 35 | ----------------------------------- 36 | > HEX: 0x05 0x20 0x00 0x01 0x00 37 | 38 | As stated on [Issue #3](https://github.com/quantus/xbox-one-controller-protocol/issues/3) the newer versions of Xbox One controllers require this longer start command. 39 | 40 | **Old info**: 41 | > BIN: DDD0 0101 DD1D D000 42 | 43 | > HEX: 0x05 0x20 44 | 45 | Starts controller's light and controller starts sending input events. 46 | 47 | 0x09: Activate rumble 48 | --------------------- 49 | 50 | buffer[0] = 0x09; 51 | buffer[1] = 0x08; // 0x20 bit and all bits of 0x07 prevents rumble effect. 52 | buffer[2] = 0x00; // This may have something to do with how many times effect is played 53 | buffer[3] = 0x??; // Substructure (what substructure rest of this packet has) 54 | 55 | 56 | If you send too long packet, overflown data is ignored. If you send too short packet, missing values are considered as 0. 57 | 58 | Buffer[3] defines what the rest of this packets is: 59 | 60 | **Continous rumble effect** 61 | 62 | buffer[3] = 0x08; // Substructure (what substructure rest of this packet has) 63 | buffer[4] = 0x00; // Mode 64 | buffer[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R) 65 | buffer[6] = 0x04; // lT force 66 | buffer[7] = 0x04; // rT force 67 | buffer[8] = 0x20; // L force 68 | buffer[9] = 0x20; // R force 69 | buffer[10] = 0x80; // Length of pulse 70 | buffer[11] = 0x00; // Period between pulses 71 | buffer[12] = 0xEB; // Number of pulses 72 | 73 | **Single rumble effect** 74 | 75 | buffer[3] = 0x09; // Substructure (what substructure rest of this packet has) 76 | buffer[4] = 0x00; // Mode 77 | buffer[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R) 78 | buffer[6] = 0x04; // lT force 79 | buffer[7] = 0x04; // rT force 80 | buffer[8] = 0x20; // L force 81 | buffer[9] = 0x20; // R force 82 | buffer[10] = 0x80; // Length of pulse 83 | 84 | **Play effect** 85 | 86 | buffer[3] = 0x04; // Substructure (what substructure rest of this packet has) 87 | buffer[4] = 0x00; // Mode 88 | buffer[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R) 89 | buffer[6] = 0x04; // lT force ? 90 | buffer[7] = 0x04; // rT force ? 91 | 92 | **Short rumble packet** 93 | 94 | buffer[3] = 0x02; // Substructure (what substructure rest of this packet has) 95 | buffer[4] = 0x00; // Mode 96 | buffer[5] = 0x0f; // Rumble mask (what motors are activated) (0000 lT rT L R) ? 97 | buffer[6] = 0x04; // lT force ? 98 | buffer[7] = 0x04; // rT force ? 99 | 100 | 101 | **List of different modes** 102 | 103 | - 0x00: Normal 104 | - 0x20: Normal, but sometimes prevents rest of 0x00 mode effects 105 | - 0x40: Triggerhell (= Pressing trigger starts rumbling all motors fast. I assume there is way to upload some pattern here, but don't know how.) 106 | - 0x41: Trigger effect (if substructure = 4?) (= Pressing trigger causes single rumble effect)(if buffer[6] >= 0x0b this rumble effect can be played multiple times. if buffer[6] > 0x4F this doesn't work) 107 | - 0x42: Fast + short rumble once 108 | 109 | 110 | 0x07: Load rumble effect 111 | ------------------------ 112 | 113 | buffer[0] = 0x07, 114 | buffer[1] = 0x85, // Atleast one of 0x07 bits must be on 115 | buffer[2] = 0xa0, // Dummy ? 116 | buffer[3] = 0x20, // L force 117 | buffer[4] = 0x20, // R force 118 | buffer[5] = 0x30, // length 119 | buffer[6] = 0x20, // period 120 | buffer[7] = 0x02, // Effect extra play count (0x02 means that effect is played 1+2 times) 121 | buffer[8] = 0x00, // Dummy ? 122 | 123 | 0x01, 0x06: Crash controller 124 | ---------------------------- 125 | 126 | **0x01 Crashes when:** 127 | 128 | bool is_1_packet_kill(uint8_t buffer[]) 129 | { 130 | return 131 | ( 132 | ((buffer[1] & 0x27) == 0x20) && 133 | (buffer[4] == 0x00) && 134 | (buffer[9] > 1 || (buffer[10] & 0x0F)) 135 | ) || ( 136 | (buffer[1] & 0x20) && 137 | (buffer[4] == 0x00) && 138 | (buffer[5] == 0x04) && 139 | (buffer[9] > 1 || (buffer[10] & 0x0F)) 140 | ); 141 | } 142 | 143 | Simple crash packet (that I use to reset my controller): 144 | 145 | 0x01, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0E 146 | 147 | **0x06 crash packet example** 148 | 149 | 0x06, 0x20, 0x0, 0x10, 0x0, 0x08, 0x0, 0x0, 0x38 150 | 151 | **Another 0x06 crash packet example** 152 | 153 | 0x06, 0x20, 0x0, 0x02, 0x0, 0x1 (if 0x02 is replaced with 0x06 it renders controller immune of this packet) 154 | 155 | 156 | Different packets that controller sends back 157 | ============================================ 158 | 159 | 0x20: Button data 160 | ----------------- 161 | Sent everytime controller input values change. 162 | Following code is from taken from [Chrome web browser](https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/gamepad/xbox_data_fetcher_mac.cc). 163 | 164 | struct XboxOneButtonData { 165 | uint8_t type; 166 | uint8_t const_0; 167 | uint16_t id; 168 | 169 | bool sync : 1; 170 | bool dummy1 : 1; // Always 0. 171 | bool start : 1; 172 | bool back : 1; 173 | 174 | bool a : 1; 175 | bool b : 1; 176 | bool x : 1; 177 | bool y : 1; 178 | 179 | bool dpad_up : 1; 180 | bool dpad_down : 1; 181 | bool dpad_left : 1; 182 | bool dpad_right : 1; 183 | 184 | bool bumper_left : 1; 185 | bool bumper_right : 1; 186 | bool stick_left_click : 1; 187 | bool stick_right_click : 1; 188 | 189 | uint16_t trigger_left; 190 | uint16_t trigger_right; 191 | 192 | int16_t stick_left_x; 193 | int16_t stick_left_y; 194 | int16_t stick_right_x; 195 | int16_t stick_right_y; 196 | }; 197 | 198 | 0x03: Heartbeat 199 | --------------- 200 | struct XboxOneHeartbeatData{ 201 | uint8_t type; 202 | uint8_t const_20; 203 | uint16_t id; 204 | 205 | uint8_t dummy_const_80; 206 | uint8_t first_after_controller; 207 | uint8_t dummy1; 208 | uint8_t dummy2; 209 | }; 210 | 211 | 0x07: Guide button status 212 | ------------------------- 213 | Sent when guide button status changes. 214 | 215 | struct XboxOneGuideData{ 216 | uint8_t type; 217 | uint8_t const_20; 218 | uint16_t id; 219 | 220 | uint8_t down; 221 | uint8_t dummy_const_5b; 222 | }; 223 | 224 | 0x01: Invalid Op data ? 225 | ----------------------- 226 | Sent when you send something multiple start packets or something. 227 | query + query2 variables contain first 2 bytes of invalid packet? 228 | 229 | struct XboxOneInvalidOpData{ 230 | uint8_t type; 231 | uint8_t const_20; 232 | uint16_t const_ff_09; 233 | 234 | uint8_t const_0; 235 | uint8_t query; 236 | uint8_t query2; 237 | uint16_t dummy; 238 | uint32_t dummy_; 239 | }; 240 | 241 | 0x02: Waiting connection 242 | ------------------------ 243 | Sent periodically when controller is connected but not started. 244 | 245 | struct XboxOneWaitingConnectionData{ 246 | uint8_t type; 247 | uint8_t const_20; 248 | uint16_t id; 249 | 250 | uint8_t dummy[28]; 251 | }; 252 | 253 | 0x00: Unknown 254 | ------------- 255 | This is received if you send this 256 | 257 | { 258 | 0x1, 0x1, 0x0, 0xbe, 0x10, 0x10, 0x21, 0x80, 0x80, 0x0, 0x10, 0xc0, 259 | 0x0, 0x8, 0x61, 0x4, 0x0, 0x48, 0x0, 0x90, 0x1, 0x0, 0x20, 0x0, 260 | 0x80, 0x60, 0x0, 0x0, 0x2, 0x0, 0x8, 0x8, 0x0, 0x28, 0x20, 0x10, 261 | 0x0, 0x4, 0x8c, 0x0, 0x10, 0x31, 0x94, 0x4, 0x22, 0x80, 0x0, 0x8, 262 | 0x8, 0x10, 0x0, 263 | } 264 | 265 | or this packet 266 | 267 | { 268 | 0x0, 0xc0, 0x0, 0x20, 0x0, 0xbe, 0x1, 0x8a, 0x49, 0x1, 0x0, 0x0, 269 | 0x40, 0x0, 0x2, 0x33, 0x0, 0x8, 0x40, 0x8, 0x0, 0x0, 0x4, 0x8, 270 | 0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x50, 271 | 0x81, 0x0, 0x0, 0x26, 0x0, 0x2, 0x0, 0xa4, 0x4c, 0x0, 0x48, 0x40, 272 | 0x0, 0x0, 0x14, 273 | } 274 | 275 | 0x04: Unknown 276 | ------------- 277 | struct XboxOneUnknown4Data{ 278 | uint8_t type; 279 | 280 | uint8_t unknown[0x3F]; 281 | }; 282 | 283 | If received packet is longer, it contains some other packet after this one. There might also be smaller packet with this same type. 284 | 285 | This is received if you send this 286 | 287 | { 288 | 0x1, 0xa8, 0x0, 0xbe, 0x0, 0x0, 0x10, 0x40, 0x0, 0x0, 0x0, 0x64, 289 | 0x1, 0x0, 0x4, 0x10, 0x2, 0x4, 0x0, 0x8, 0x4, 0x80, 0x40, 0x4d, 290 | 0x14, 0x4, 0x0, 0x2, 0x10, 0x0, 0x12, 0x80, 0x42, 0x0, 0x69, 0x0, 291 | 0x4, 0x40, 0x0, 0x0, 0x5, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa, 0x49, 292 | 0x1, 0x20, 0x0, 293 | } 294 | 295 | 296 | 0x06: Unknown 297 | ------------- 298 | struct XboxOneUnknown6Data{ 299 | uint8_t type; 300 | uint8_t const_30; 301 | uint16_t id; 302 | 303 | uint8_t const_0; 304 | uint8_t dummy[5]; 305 | }; 306 | 307 | 308 | License 309 | ======= 310 | 311 | You are free to use information and code in this document in any way you want, as long as you don't hold me responsible for anything. 312 | --------------------------------------------------------------------------------