On the real XG Mobile, the MCU is an ITE chip which is a similar design to the Embedded Controller on the Ally. It is responsible for the following:
- Toggling the connector signals.
- Communicating with the host's EC over I2C.
- Communicating with the Windows over USB HID.
In order to save costs and reduce complexity, our MCU is a STM32 which implements 1 and 2 but not 3. Since the main reason to communicate with Windows is to control fans (not available here) and to pass in serial and model information (can be done with software), we do not implement 3 which requires a USB PHY on the MCU.
The I2C/SMBus pins from the connector is hooked up to the host's EC. The MCU communicates with the EC through this I2C bus (in addition to the status pins). The importance of the I2C bus is that upon reboot, a successful handshake must take place or the host will throw a splash image indicating the XG Mobile has been disconnected (see the code for more details).
These are the commands supported by the real XG Mobile MCU:
Command (Byte 0) | Byte 1 | Byte 2 | Remaining | Direction | Description |
---|---|---|---|---|---|
0xA0 | Register Number | Length | Data | Host to Device | Write Register |
0xA1 | - | - | 0xD2, 0xDA, 0xDB, or 0xDC | Device to Host | Get event? |
0xA2 | - | - | 0x01 or 0x02 | Device to Host | Session status? |
0xA3 | - | - | 0x01 | Device to Host | Heartbeat? |
These are the registers:
- Host send:
A0 07 01 01
- Host send:
A0 01 01 00
- Host send:
A0 0A 01 04
- MCU asserts IRQ
- Host send:
A1
, MCU respond:DC
, deasserts IRQ - Host send:
A2
, MCU respond:02
- Host send:
A0 08 01 01
- Host send:
A0 08 01 01
- Host send:
A0 09 01 00
- Host send:
A0 09 01 01
- Host send:
A0 09 01 01
- Host send:
A3
, MCU respond:01
(repeat ad infinitum every second)
- Host send:
A0 07 01 01
- Host send:
A0 01 01 00
- Host send:
A0 0A 01 01
- MCU asserts IRQ
- Host send:
A1
, MCU respond:DC
, deasserts IRQ - Host send:
A2
, MCU respond:02
Press A to continue
- Host send:
A0 08 01 01
- MCU asserts PWROK
- Host de-asserts RST
- Host send:
A0 09 01 00
- Host send:
A0 09 01 01
- Host send:
A0 09 01 01
- Host send:
A0 0A 01 02
(only sometimes?) - Host send:
A3
, MCU respond:01
(repeat ad infinitum every second)
- Host send:
A0 07 01 01
- Host send:
A0 01 01 00
- MCU asserts IRQ
- Host send:
A1
, MCU respond:DC
, deasserts IRQ - Host send:
A2
, MCU respond:02
- Host send:
A0 0A 01 04
XGM connect popup appears, user must click connect
- Host send:
A0 08 01 01
- MCU asserts PWROK
- Host de-asserts RST
- Host send:
A0 09 01 01
- Host send:
A3
, MCU respond:01
(repeat ad infinitum every second)
- Host send:
A0 08 01 00
- Host stops sending
A3
after 2 more seconds
- Host send:
A0 08 01 01
- Host send:
A3
, MCU respond:01
(repeat ad infinitum every second)
- Host send:
A0 0D 01 01
- Host send:
A0 09 01 00
- Host send:
A0 09 01 00
- Host send:
A0 01 01 05
- MCU asserts IRQ
- Host send:
A1
, MCU respond:DC
, deasserts IRQ - Host send:
A2
, MCU respond:01
This information was gained by sniffing the I2C bus with a logic analyzer and also by reverse engineering the EC firmware. The EC for the ROG Ally can be found here and the MCU firmware for the 2021 XG Mobile can be found here. The ROG Ally has two chips a main controller and a secondary controller. Along with the XG Mobile's MCU, all three chips are different variants of ITE's embedded controller.
For reverse engineering the firmware, Google's Chromebook EC firmware is a good source of reference because it contains support code for a different model of ITE chip that uses the same ISA and has a similar memory layout. For disassembly, you need to build Ghidra with NDS32 support.