Skip to content
This repository has been archived by the owner on Apr 19, 2024. It is now read-only.

Commit

Permalink
Merge pull request #22 from zllovesuki/wmi_notify
Browse files Browse the repository at this point in the history
notify wmi via hid keycode; fix #16
  • Loading branch information
zllovesuki authored Aug 20, 2020
2 parents d3da3a3 + 49250bc commit 1fa04e7
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 68 deletions.
48 changes: 18 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ROGManager: A Replacement For Armoury Crate (mostly)
# ROGManager: An open source replacement for Asus Optimization/Armoury Crate

![Test and Build](https://github.com/zllovesuki/ROGManager/workflows/Test%20and%20Build/badge.svg) ![Build Release](https://github.com/zllovesuki/ROGManager/workflows/Build%20Release/badge.svg)

Expand All @@ -8,40 +8,20 @@ Your warranty is now void. Proceed at your own risk.

## Current Status

After some reverse engineering, ROGManager now reads from hid directly instead of Asus Optimization. However, for now we still need AO for adjusting screen brightness and implementing all the hardware control.
Follow project status on [Sprint Board](https://github.com/zllovesuki/ROGManager/projects/1)

After some reverse engineering, ROGManager now (mostly) replaces Asus Optimization's functionalities. Only unimplemented (yet) functionalities are:
1. Toggle mute/unmute microphone
2. Toggle enable/disable TouchPad
3. Keyboard brightness adjustment (it is in the pipeline)
4. On-screen display

## Requirements

ROGManager requires "Asus Optimization" to be running as a Service, since "Asus Optimization" loads the `atkwmiacpi64.sys` driver and interpret ACPI events as key presses, and exposes a `\\.\ATKACPI` device to be used. You do not need any other softwares from Asus running to use ROGManager; you can safely uninstall them from your system. However, some softwares are installed as Windows driver, and you should disable them in Services:
ROGManager requires "Asus Optimization" to be installed _but does not require AO to be running_. We only need Asus Optimization (the driver) to be installed so Windows will load `atkwmiacpi64.sys`, and exposes a `\\.\ATKACPI` device to be used. You do not need any other softwares from Asus (e.g. Armoury Crate and its cousins, etc) running to use ROGManager; you can safely uninstall them from your system. However, some softwares (e.g. Asus Optimization) are installed as Windows Services, and you should disable them in Services:

![Running Services](images/services.png)

![Running Processes](images/processes.png)

The OSD functionality is provided by `AsusOSD.exe`, which should also be under "Asus Optimization."

```
PS C:\Windows\System32\DriverStore\FileRepository\asussci2.inf_amd64_b12b0d488bd75133\ASUSOptimization> dir
Directory: C:\Windows\System32\DriverStore\FileRepository\asussci2.inf_amd64_b12b0d488bd75133\ASUSOptimization
Mode LastWriteTime Length Name
---- ------------- ------ ----
------ 7/28/2020 02:41 3684 ASUS Optimization 36D18D69AFC3.xml
------ 7/28/2020 02:52 218024 AsusHotkeyExec.exe
------ 7/28/2020 02:52 273832 AsusOptimization.exe
------ 7/28/2020 02:53 262056 AsusOptimizationStartupTask.exe
------ 7/28/2020 02:53 117160 AsusOSD.exe
------ 7/28/2020 02:53 844200 AsusSplendid.exe
------ 7/28/2020 02:53 177576 AsusWiFiRangeboost.exe
------ 7/28/2020 02:53 184744 AsusWiFiSmartConnect.exe
------ 7/28/2020 02:53 44680 atkwmiacpi64.sys
------ 7/28/2020 02:53 236952 CCTAdjust.dll
------ 7/28/2020 02:53 204184 VideoEnhance_v406_20180511_x64.dll
```

Recommend running ROGManager.exe on startup in Task Scheduler.

## Remapping the ROG Key
Expand Down Expand Up @@ -76,4 +56,12 @@ The key combo has a time delay. If you press the combo X times, it will apply th

## Developing

Use `.\run.ps1` as it does not compile using CGo.
Use `.\run.ps1`.

## References:

- https://github.com/torvalds/linux/blob/master/drivers/platform/x86/asus-wmi.c
- https://github.com/torvalds/linux/blob/master/drivers/platform/x86/asus-nb-wmi.c
- https://github.com/torvalds/linux/blob/master/drivers/hid/hid-asus.c
- https://github.com/flukejones/rog-core/blob/master/kernel-patch/0001-HID-asus-add-support-for-ASUS-N-Key-keyboard-v5.8.patch
- [Reverse Engineering](./reverse_eng.md)
42 changes: 40 additions & 2 deletions controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ type controller struct {
debounceCh map[uint32]keyedDebounce
keyCodeCh chan uint32
wmiCh chan uint32

keyCtrl *atkacpi.ATKControl
}

func NewController(conf Config) (Controller, error) {
Expand Down Expand Up @@ -88,13 +90,18 @@ func (c *controller) notify(n notification) error {
func (c *controller) initialize(haltCtx context.Context) {
devices, err := atkacpi.NewHidListener(haltCtx, c.keyCodeCh)
if err != nil {
log.Fatalln(err)
log.Fatalln("error initializing hidListener", err)
}
log.Printf("hid devices: %+v\n", devices)

err = atkacpi.NewWMIListener(haltCtx, c.wmiCh)
if err != nil {
log.Fatalln(err)
log.Fatalln("error initializing wmiListener", err)
}

c.keyCtrl, err = atkacpi.NewAtkControl(atkacpi.WriteControlCode)
if err != nil {
log.Fatalln("error initializing atk control for keyboard emulation", err)
}

// TODO: revisit this
Expand All @@ -121,6 +128,8 @@ func (c *controller) handleWMI(haltCtx context.Context) {
log.Println("wmi: On battery")
case 123:
log.Println("wmi: Power input changed")
default:
log.Printf("wmi: Unknown %d\n", wmi)
}
case <-haltCtx.Done():
log.Println("Exiting handleWMI")
Expand All @@ -129,10 +138,39 @@ func (c *controller) handleWMI(haltCtx context.Context) {
}
}

func keyEmulation(ctrl *atkacpi.ATKControl, keyCode uint32) {
switch keyCode {
/*
TODO: Unimplemented (yet):
107, // touchpad toggle
124, // mute/unmute microphone
*/
case
16, // screen brightness down
32, // screen brightness up
108, // sleep
136, // RF kill toggle
0: // noop
log.Printf("Forwarding %d to ATKACPI\n", keyCode)

inputBuf := make([]byte, atkacpi.KeyPressControlBufferLength)
copy(inputBuf, atkacpi.KeyPressControlBuffer)
inputBuf[atkacpi.KeyPressControlByteIndex] = byte(keyCode)

_, err := ctrl.Write(inputBuf)
if err != nil {
log.Fatalln("error sending key code to ATKACPI", err)
}
}
}

func (c *controller) handleKeyPress(haltCtx context.Context) {
for {
select {
case keyCode := <-c.keyCodeCh:
// also forward some special key combo to the ATK interface
go keyEmulation(c.keyCtrl, keyCode)

switch keyCode {
case 56:
log.Println("hid: ROG Key Pressed (debounced)")
Expand Down
Binary file removed images/processes.png
Binary file not shown.
Binary file modified images/services.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 0 additions & 35 deletions key/key.go

This file was deleted.

146 changes: 145 additions & 1 deletion reverse_eng.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,105 @@
|----------------------|-----------------------------------------------------|---------------------------|--------------|----------------|---------------|---------------|------------|
| Battery Charge Limit | `[44 45 56 53 08 00 00 00 57 00 12 00 %x 00 00 00]` | Battery Charge Percentage | 16 | First byte = 1 | 1024 | 1024 | NULL |

### USB Protocol

On my machine, the keyboard(s) show up as a few things:
```
Following filter control devices are available:
1 \\.\USBPcap1
\??\USB#ROOT_HUB30#5&90ded96&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
2 \\.\USBPcap2
\??\USB#ROOT_HUB30#5&11614a76&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
[Port 3] USB Composite Device
USB Input Device
HID Keyboard Device
USB Input Device
HID Keyboard Device
USB Input Device
HID-compliant vendor-defined device
HID-compliant consumer control device
HID-compliant vendor-defined device
HID-compliant vendor-defined device
3 \\.\USBPcap3
\??\USB#ROOT_HUB30#5&3462ecd3&0&0#{f18a0e88-c30c-11d0-8815-00a0c906bed8}
[Port 3] Goodix fingerprint
[Port 4] Intel(R) Wireless Bluetooth(R)
IBtUsb_Filter_00
```
Running USBPcap in Wireshark on USBPcap2 yields a few interesting observations...

Endpoint 0, 1, and 2 are all unintersting. However, on Endpoint 3 (IN):

Pressing the ROG Key:
```
0000 1b 00 10 50 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 06 00 00 00 5a 38 00 00 00
0020 00
```

Pressing the Fn+F5 Key:
```
0000 1b 00 10 50 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 06 00 00 00 5a ec 00 00 00
0020 00
```

Pressing the Fn+Down Key:
```
0000 1b 00 e0 55 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 06 00 00 00 5a c5 00 00 00
0020 00
```

I think you may have notice a pattern. `[5a %x]` where x matches exactly our special Fn Combo.

For normal keys, they look like this:

Pressing the Backspace:
```
0000 1b 00 10 50 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 20 00 00 00 5d 01 00 00 2a
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00
```

Pressing the Spacebar:
```
0000 1b 00 10 50 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 20 00 00 00 5d 01 00 00 2c
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00
```

You can see that `0x2a` and `0x2c` matches exactly the keycodes for Backspace and Spacebar, respectively.

The 23th byte indicates how large the buffer will be. 32 is normal key press, and 6 is special key combo.

It also seems that 1st byte in the returned buffer indicates what this is. `0x5a`: special combo, `0x5d`: normal key code

For sanity check, what happened when we do `Ctrl+Spacebar`?
```
0000 1b 00 e0 55 52 19 8f a8 ff ff 00 00 00 00 09 00
0010 01 02 00 01 00 83 01 20 00 00 00 5d 01 01 00 2c
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00
```

Yep, we can see the LCTRL modifier.

In addition, when the brightness is increased with Fn+Up, something sends some data over the HID interface (Endpoint 0) instead of raw USB:
```
0000 1c 00 10 00 58 28 8f a8 ff ff 00 00 00 00 1b 00
0010 00 02 00 01 00 00 02 48 00 00 00 00 21 09 5a 03
0020 02 00 40 00 5a ba c5 c4 01 00 00 00 00 00 00 00
0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0060 00 00 00 00
```

You may've recognized the `[5a ba c5 c4 ...]` buffer (see below). That's the one setting the brightness.

### Keyboard

ROG Key Pressed
Expand All @@ -18,4 +117,49 @@ ROG Key Pressed
6 ULONG IoControlCode 2237448 2237448
# Type Name Pre-Call Value Post-Call Value
9 PVOID OutputBuffer 0x000000bcc0afe15c 0x000000bcc0afe15c
`[38 00 00 00]`
`[38 00 00 00]`


### Keyboard backlight
```
Caption : HID-compliant vendor-defined device
Description : HID-compliant vendor-defined device
InstallDate :
Name : HID-compliant vendor-defined device
Status : OK
Availability :
ConfigManagerErrorCode : CM_PROB_NONE
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
DeviceID : HID\VID_0B05&PID_1866&MI_02&COL01\8&1E16C781&0&0000
ErrorCleared :
ErrorDescription :
LastErrorCode :
PNPDeviceID : HID\VID_0B05&PID_1866&MI_02&COL01\8&1E16C781&0&0000
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : RACHEL-G14
ClassGuid : {745a17a0-74d3-11d0-b6fe-00a0c90f57da}
CompatibleID :
HardwareID : {HID\VID_0B05&PID_1866&REV_0002&MI_02&Col01, HID\VID_0B05&PID_1866&MI_02&Col01, HID\VID_0B05&UP:FF31_U:0076,
HID_DEVICE_UP:FF31_U:0076...}
Manufacturer : (Standard system devices)
PNPClass : HIDClass
Present : True
Service :
PSComputerName :
Class : HIDClass
FriendlyName : HID-compliant vendor-defined device
InstanceId : HID\VID_0B05&PID_1866&MI_02&COL01\8&1E16C781&0&0000
Problem : CM_PROB_NONE
ProblemDescription :
```

# Type Name Pre-Call Value Post-Call Value
6 ULONG IoControlCode 721297 721297
# Type Name Pre-Call Value Post-Call Value
7 PVOID InputBuffer 0x000001b7763041d0 0x000001b7763041d0
`[0x5a, 0xba, 0xc5, 0xc4, %x, ...]` len(64) padded with 0x00
%x: 00 backlight off, 01 02 03 different levels

0 comments on commit 1fa04e7

Please sign in to comment.