GPD-LinuxControls

GPD LinuxControls

This is a reverse engineered and reference implementation of GPD WinControls, developed and tested on GPD Win Max 2 2023.

[!CAUTION]

This repository is the product of reverse engineering

USB data frames sent to the device will be written directly to the EC ROM. Wrong speculation and implementation during the reverse engineering process may irreversibly destroy your device.

This repository and its contributors do not make any commitments, and all consequences are at the user’s own risk.

GPD WinControls Protocal

Basic Infomation

All request commands should be sent by SET_REPORT, and read the response by GET_REPORT.

  SET_REPORT GET_REPORT
bmRequestType 0x21 0xa1
bRequest 0x09 0x01
wValue 0x0201 0x0101
wIndex 2 2
wLength 33 65

Keyboard-Mouse

Keyboard-Mouse follows HID Usage ID

In addition, there are GPD defined HID Usage ID extensions:

VIBRATE

Dead Zones

In range [-10, 10] ([0xF6, 0x0A])

Back Button Delay

0 1 2 3 4 5 6 7
01a5 R/W MAJOR_SERIAL 5a CHECK_DIGIT 00 MINOR_DIGIT 00
  1. R/W
    • R: 1
    • W: 2
  2. MAJOR_SERIAL
    • R/W = 1: In range [0, 2]
    • R/W = 2: In range [1, 3]
  3. CHECK_DIGIT + Header[2] = 0xFF
  4. MINOR_SERIAL
    • MAJOR_SERIAL = 1
      • R/W = 1: In range [0, 3]
      • R/W = 2: In range [0, 7]
    • Else: 0

R/W = 1

MAJOR_SERIAL = 0

Request

Command: 01a5105aef00000000000000000000000000000000000000000000000000000000

Response
0-8 9 10 11 12 13-63
GPD Mainboard(GamePad) Firmware GPD Extendboard(Keyboard-Mouse) Firmware
01a5105aef000000aa MAJOR_VERSION MINOR_VERSION MAJOR_VERSION MINOR_VERSION 000000000000000000000000000000e40200000000000000000000000000000000000000000000000000000000000000000000

MAJOR_SERIAL = 1

MINOR_SERIAL = 0
Request

Command: 01a5115aee00000000000000000000000000000000000000000000000000000000

Response
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28-49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
Keyboard-Mouse 000000000000ea00eb00ec00ed000000000000000000 Back Button
Directional Pad A Button 00 B Button 00 X Button 00 Y Button 00 Left Stick Right Stick LEFT_1 00 LEFT_2 00 LEFT_3 00 LEFT_4 00 RIGHT_1 00 RIGHT_2 00 RIGHT_3 00
UP 00 DOWN 00 LEFT 00 RIGHT 00 UP 00 DOWN 00 LEFT 00 RIGHT 00 PUSH 00 PUSH 00
MINOR_SERIAL = 1
Request

Command: 01a5115aee00010000000000000000000000000000000000000000000000000000

Response
0 1 2 3-7 8 9 10 11 12-15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32-63
Back Button VIBRATE 0000ff0000 Stick Dead Zones Back Button Delay 2c 01 Back Button Delay 2c 01 0000000000000000000000000000000000000000000000000000000000000000
RIGHT_4 00 LEFT_CENTER LEFT_BORDER RIGHT_CENTER RIGHT_BORDER 00000000 LEFT_1 00 LEFT_2 00 LEFT_3 00 RIGHT_1 00 RIGHT_2 00 RIGHT_3 00
MINOR_SERIAL = 2
Request

Command: 01a5115aee00020000000000000000000000000000000000000000000000000000

Response

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

MINOR_SERIAL = 3
Request

Command: 01a5115aee00030000000000000000000000000000000000000000000000000000

Response

00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

MAJOR_SERIAL = 2

Request

Command: 01a5125aed00000000000000000000000000000000000000000000000000000000

Response
0-7 8-23 24-29 30-63
Header aa031401230000000000000000000000 CHECKSUM 00000000000000000000000000000000000000000000000000000000000000000000
01a5125aed000000

R/W = 2

Write commands usually has no response.

MAJOR_SERIAL = 1

MINOR_SERIAL = 0
0-7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24-32
Header Keyboard-Mouse 000000000000000000
Directional Pad A Button 00 B Button 00 X Button 00 Y Button 00
01a5215ade000000 UP 00 DOWN 00 LEFT 00 RIGHT 00
MINOR_SERIAL = 1
0-7 8 9 10 11 12 13 14 15 16 17 18 19 20-32
Header Keyboard-Mouse 00000000000000000000000000
Left Stick Right Stick
01a5215ade000100 UP 00 DOWN 00 LEFT 00 RIGHT 00 PUSH 00 PUSH 00
MINOR_SERIAL = 2

01a5215ade0002000000ea00eb00ec00ed00000000000000000000000000000000

MINOR_SERIAL = 3
0-7 8-9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24-32
Header 0000 Back Button 000000000000000000
01a5215ade000300 LEFT_1 00 LEFT_2 00 LEFT_3 00 LEFT_4 00 RIGHT_1 00 RIGHT_2 00 RIGHT_3 00
MINOR_SERIAL = 4
0-7 8 9 10 11-15 16 17 18 19 20-32
Header Back Button VIBRATE 0000ff0000 Stick Dead Zones 00000000000000000000000000
01a5215ade0004 RIGHT_4 00 LEFT_CENTER LEFT_BORDER RIGHT_CENTER RIGHT_BORDER
MINOR_SERIAL = 5
0-7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24-32
Header Back Button Delay 2c 01 Back Button Delay 2c 01 000000000000000000
01a5215ade000500 LEFT_1 00 LEFT_2 00 LEFT_3 00 RIGHT_1 00 RIGHT_2 00 RIGHT_3 00
MINOR_SERIAL = 6

01a5215ade00060000000000000000000000000000000000000000000000000000

MINOR_SERIAL = 7

01a5215ade00070000000000000000000000000000000000000000000000000000

MAJOR_SERIAL = 2

Request

01a5225aed00000000000000000000000000000000000000000000000000000000

Response
0-7 8-23 24-29 30-63
Header aa031401230000000000000000000000 CHECKSUM 00000000000000000000000000000000000000000000000000000000000000000000
01a5225aed000000

MAJOR_SERIAL = 3

01a5235adc00000000000000000000000000000000000000000000000000000000

This command will save all config into ROM.