mateuszradomski / re-masterkeys

Reverse Engineering of the Cooler Master Masterkeys line of keyboards
10 stars 1 forks source link

Pro S RGB Support #1

Open hansemro opened 2 years ago

hansemro commented 2 years ago

CN2 header:

SEL1 header:

SEL2 header:

So far, very similar to POK3R RGB. I will update with more details as I find them.

Tasks:

hansemro commented 2 years ago

Raspberry Pi 4 : ProS

Rebased openocd-ht32 with latest commits to fix some issues with raspberry pi: https://github.com/hansemro/openocd-ht32/tree/ht32f165x-dev

Build:

git clone -b ht32f165x-dev-v0.12.0-rc2 https://github.com/hansemro/openocd-ht32.git
cd openocd-ht32
./bootstrap
./configure --enable-bcm2835gpio --enable-sysfsgpio
make
sudo make install

openocd.cfg:

adapter driver bcm2835gpio
transport select swd

### for RPi4
bcm2835gpio peripheral_base 0xFE000000
bcm2835gpio speed_coeffs 236181 60

## Pi pin 18 (GPIO24) : SWDIO
adapter gpio swdio 24
## Pi pin 22 (GPIO25) : SWCLK
adapter gpio swclk 25

## Pi pin 12 (GPIO18) : nRST
adapter gpio srst 18

## dont forget pin 9 for Ground

## HT32F1654
set HT32_SRAM_SIZE 0x8000
set HT32_FLASH_SIZE 0x10000

## HT32F52352
#set HT32_SRAM_SIZE 0x8000
#set HT32_FLASH_SIZE 0x20000

source [find target/ht32f165x.cfg]
pi@raspberrypi:~ $ sudo openocd
Open On-Chip Debugger 0.12.0-rc2+dev-00964-g9b86c7e5e (2022-11-03-16:13)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
trst_only separate trst_push_pull

Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 12 kHz
Info : SWD DPIDR 0x2ba01477
Info : [ht32f165x.cpu] Cortex-M3 r2p0 processor detected
Info : [ht32f165x.cpu] target has 6 breakpoints, 4 watchpoints
Info : starting gdb server for ht32f165x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : accepting 'telnet' connection on tcp/4444
Warn : [ht32f165x.cpu] Only resetting the Cortex-M core, use a reset-init event handler to reset any peripherals or configure hardware srst support.
hansemro commented 2 years ago

pro_s_rgb

hansemro commented 2 years ago

Pro S RGB firmware patch: https://github.com/hansemro/re-masterkeys/blob/Pro_S_RGB/binaries/Pro_S_RGB/patch.txt

FW offset 0x3400

    67fa: ff 28           cmp        r0,#0xff
    67fc: 04 d1           bne        0x00006808
    67fe: 60 68           ldr        r0,[r4,#0x4]
    6800: 3c 21           movs       r1,#0x3c
    6802: 31 e0           b          0x00006868
    6804: 00 bf           nop
    6806: 00 bf           nop

EDIT Sept 8, 2022: Fixed and tested firmware patch

hansemro commented 2 years ago

Some USB packet captures:

1: Plugging in keyboard plug-in.zip

2: Firmware upgrade (1.2.2 to 1.2.2) via OEM software fw-upgrade.zip

3: Firmware upgrade from fake version (1.1.9) to 1.2.2 via OEM software: no major difference fw_upgrade_from_1.1.9.zip

hansemro commented 2 years ago

python script to get current firmware version from Pro S: RGB

Dependency: pyusb

get_version.py:

#!/usr/bin/env python3

import usb.core
import usb.util

dev = usb.core.find(idVendor=0x2516, idProduct=0x003c)

if dev is None:
    raise ValueError('CM Pro S not found')
else:
    print("CM Pro S found")

if dev.is_kernel_driver_active(1):
    try:
        dev.detach_kernel_driver(1)
        print("kernel driver detached")
    except usb.core.USBERROR as e:
        print(f"Could not detach kernel driver: {e}")
        exit(1)

try:
    usb.util.claim_interface(dev, 1)
    print("Claimed usb device")
except Exception as e:
    print(f"{e}")
    exit(1)

#ver_req = [ 0x01,0x02,0xdf,0xfc,0x00,0x30,0x00,0x00,0x3d,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0
x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
,0x00,0x00,0x00,0x00 ]
ver_req = [ 0x01,0x02 ]

dev.write(0x04, ver_req)

out = dev.read(0x83, 64)
out = "".join(chr(x) for x in out)
print(f"{out[4:9]}")

usb.util.dispose_resources(dev)

output:

$ python3 get_version.py 
CM Pro S found
kernel driver detached
Claimed usb device
1.2.2
hansemro commented 2 years ago

Additional commands:

Properties:

[0x4,0x0] (BF)

Reset between bootloader/firmware.

[0x4,0x1] (BF)

Reset to bootloader. Observation: replacing 0x1 with any non-zero value seems to behave similarly.

[0x3,N] (BF)

After sending command, keyboard returns device information (firmware address, page size, and version address).

[0x12,0x0] (BF)

After sending command, keyboard returns constant 40+ byte data.

[0x12,0x1] (BF)

After sending command, keyboard returns constant 35+ byte data.

hansemro commented 2 years ago

Analyzing fw-upgrade.pcap from above.

Start writing firmware at 0x3400 in 0x34 byte increments...

       write-unkwn-StartAddres-End.Address-_data...
0000   01 01 2a 4b 00 34 00 00 33 34 00 00 _48 27 00 20
0010   55 35 00 00 61 35 00 00 63 35 00 00 65 35 00 00
0020   67 35 00 00 69 35 00 00 00 00 00 00 00 00 00 00
0030   00 00 00 00 00 00 00 00 6b 35 00 00 6d 35 00 00

0x34 (52,+0x34) bytes written expect next data to be written start with 0000 0000 6f35... next_write_addr: 0x3434

0000   01 01 c9 af 34 34 00 00 67 34 00 00 _00 00 00 00
0010   6f 35 00 00 71 35 00 00 73 35 00 00 73 35 00 00
0020   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00
0030   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00

0x34 (+0x68) bytes written expected next data: 7335 0000 7335 0000 7335 .... next_write_addr: 0x3468

0000   01 01 ae 41 68 34 00 00 9b 34 00 00 _73 35 00 00
0010   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00
0020   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00
0030   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00

0x34 (+0x9c) bytes written next_write_addr: 0x349c

0000   01 01 b2 e2 9c 34 00 00 cf 34 00 00 _73 35 00 00
0010   73 35 00 00 73 35 00 00 00 00 00 00 73 35 00 00
0020   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00
0030   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00

0x34 (+0xd0) bytes written next_write_addr: 0x34d0

0000   01 01 e3 0c d0 34 00 00 03 35 00 00 _73 35 00 00
0010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020   e1 37 00 00 8d 38 00 00 73 35 00 00 73 35 00 00
0030   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00

0x34 (+x01_04) bytes written next_write_addr: 0x3504

0000   01 01 5f 7d 04 35 00 00 37 35 00 00 _73 35 00 00
0010   73 35 00 00 73 35 00 00 73 35 00 00 bd 85 00 00
0020   00 00 00 00 73 35 00 00 73 35 00 00 73 35 00 00
0030   73 35 00 00 73 35 00 00 73 35 00 00 73 35 00 00

0x34 (+x01_38) bytes written next_write_addr: 0x3538

0000   01 01 28 9b 38 35 00 00 6b 35 00 00 _73 35 00 00
0010   00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0020   00 00 00 00 73 35 00 00 07 48 80 47 07 48 80 47
0030   07 48 00 47 fe e7 fe e7 fe e7 fe e7 fe e7 fe e7

Need help figuring out what the two unknown bytes are.

hansemro commented 2 years ago

Finding crc (the 2 unknown bytes above) with https://sourceforge.net/projects/reveng/ for write commands that start with [0x1,0x1]:

$ ./reveng -a 8 -X -w 16 -s \
    003400003334000048270020553500006135000063350000653500006735000069350000000000000000000000000000000000006b3500006d3500004b2a \
    3434000067340000000000006f3500007135000073350000733500007335000073350000733500007335000073350000733500007335000073350000afc9 \
    683400009b3400007335000073350000733500007335000073350000733500007335000073350000733500007335000073350000733500007335000041ae \
    9c340000cf34000073350000733500007335000000000000733500007335000073350000733500007335000073350000733500007335000073350000e2b2 \
    d0340000033500007335000000000000000000000000000000000000e13700008d3800007335000073350000733500007335000073350000733500000ce3 \
    383500006b35000073350000000000000000000000000000000000000000000073350000074880470748804707480047fee7fee7fee7fee7fee7fee79b28
width=16  poly=0x1021  init=0x4184  refin=false  refout=false  xorout=0x0000  check=0x77d5  residue=0x0000  name=(none)
hansemro commented 2 years ago

Testing crc against random flash commands that start with [0x1,0x1]:

#0000   01 01 86 7b 6c 35 00 00 9f 35 00 00 fe e7 fe e7
#0010   fe e7 fe e7 c9 85 00 00 01 72 00 00 81 35 00 00
#0020   df f8 0c d0 00 f0 3c f8 00 48 00 47 21 94 00 00
#0030   48 27 00 20 06 49 07 4a 08 68 50 43 43 f2 39 02
./reveng -w 16 -p 0x1021 -i 0x4184 -c 6c3500009f350000fee7fee7fee7fee7c98500000172000081350000dff80cd000f03cf80048004721940000482700200649074a0868504343f23902
7b68

#0000   01 01 60 c7 04 69 00 00 37 69 00 00 0d 68 05 60
#0010   00 e0 03 60 00 1d 09 1d 52 1e d2 b2 f4 d2 30 bc
#0020   70 47 00 00 10 b5 19 49 60 b1 01 28 0c d0 02 28
#0030   2b d1 35 20 ff f7 90 fc fd f7 7b f8 bd e8 10 40
./reveng -w 16 -p 0x1021 -i 0x4184 -c 04690000376900000d68056000e00360001d091d521ed2b2f4d230bc7047000010b5194960b101280cd002282bd13520fff790fcfdf77bf8bde81040
c760

#0000   01 01 5f a1 28 7f 00 00 5b 7f 00 00 1c 20 14 18
#0010   40 1e a1 70 fb d5 03 48 03 70 10 bd 18 00 00 20
#0020   d0 09 00 20 44 00 00 20 02 4a 01 21 42 f8 20 10
#0030   70 47 00 00 c4 09 00 20 c2 78 81 88 01 23 21 2a
./reveng -w 16 -p 0x1021 -i 0x4184 -c 287f00005b7f00001c201418401ea170fbd50348037010bd18000020d009002044000020024a012142f8201070470000c4090020c27881880123212a
a15f

Looks good so far

hansemro commented 2 years ago

There is a different CRC for flash commands that start with [0x1,0x0]:

./reveng -a 8 -X -w 16 -s \
    548a0000878a00002e00fcf769fc0446c0b2424e424f012807d0022820d0042826d0bde8f041fcf7b9bafcf7b7fac4f3072404eb840006eb8000c068e0e6 \
    888a0000bb8a000080477868002866d004eb440000ebc400284490f84210bde8f041c1f38011493000f074b8fcf79cfac4f30720bde8f041fdf738b8e84e \
    bc8a0000ef8a000078212c480024ba680be01378d82b01d3fe2b04d1782304701c54f0231c54401c521c491ec9b2f0d2012400253868204219d005eb23c5 \
    f08a0000238b0000850006eb8000c0688047786820420dd005eb450000ebc500ba6800f179018030515c1044c1f3801100f03cf82846fff74ffe6d1c88c8
width=16  poly=0x1021  init=0x76b4  refin=false  refout=false  xorout=0x0000  check=0x74a0  residue=0x0000  name=(none)
hansemro commented 2 years ago

Seems like [0x1,0x2] which is used for reading also has its own crc and follows similar syntax as writing. However, the read command is only used for getting firmware version at a fixed address range, which makes it difficult to narrow down crc.

By making assumptions, we can reduce possibilities:

$ ./reveng -w 16 -p 0x1021 -s 003000003d30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fcdf
./reveng: warning: you have only given 1 sample
./reveng: warning: to reduce false positives, give 4 or more samples
./reveng: no models found
./reveng: warning: you have only given 1 sample
./reveng: warning: to reduce false positives, give 4 or more samples
width=16  poly=0x1021  init=0x18d4  refin=false  refout=false  xorout=0x0000  check=0x724a  residue=0x0000  name=(none)
width=16  poly=0x1021  init=0x2bfa  refin=true  refout=true  xorout=0x0000  check=0x4c77  residue=0x0000  name=(none)

pok3rtool seems to do crc correctly. No need to investigate further

hansemro commented 2 years ago

~Protocol is nearly the same as the one descibed in proto_pok3r instead of proto_cykb.~

Correction: Pro S RGB seems to implement/borrow functions in pok3r and cykb protocols. For example, [0x3,0x0] from pok3r protocol works to retrieve fw/ver addresses and [0x12,0x20] from cykb protocol works to retrieve version string (like [0x1,0x2]).

hansemro commented 2 years ago

Good and bad news: erase command works for clearing version and firmware data....

In my attempt to write firmware with flash erase step (in my fork of pok3rtool: https://github.com/hansemro/pok3rtool/tree/cooler-master-dev), I noticed that cooler master can no longer be detected over USB and can not function as a HID device.

I was able to set version successfully, but it seems firmware region could not be written to.

hansemro commented 2 years ago

Shorting SEL2 to boot into bootloader mode allows the keyboard to be detected, but not with cooler master VID/PID/IPID.

ID 2516:003c Cooler Master Technology Inc. MASTERKEYS PRO S <- firmware mode
ID 2516:003d Cooler Master Technology Inc. USB-HID IAP <- bootloader mode
ID 04d9:8010 Holtek Semiconductor, Inc. <- SEL2 short mode

Not sure what can be done to reprogram firmware without erasing bootloader...

EDIT: For less confusion: bootloader mode actually refers to IAP firmware that lies at 0x0, and SEL2 short mode refers to bootrom/bootloader at 0x1f000000.

hansemro commented 2 years ago

Modified SVD with some changes to fix overlapping peripheral regions: HT32F1653_54.svd.zip

SVD Source: https://web.archive.org/web/20220827045212/https://mcu.holtek.com.tw/pack/Holtek.HT32_DFP.1.0.41.pack

hansemro commented 1 year ago

Fixed firmware writing with my fork of pok3rtool with https://github.com/hansemro/pok3rtool/commit/11b822daccf6230801e9e4c1574e27bc54f884a1, managed to dump flash from another Pro S RGB, and recovered my previously dead board with stock bootloader!

Flashing patched firmware (from 1.2.2):

$ pok3rtool_cm -t prosrgb flash 1.2.3 ProSRGB_fw_patched.bin --ok                                                                                
Opened MasterKeys Pro S RGB                                                                                                                                                
Update Firmware: ProSRGB_fw_patched.bin                                                                                                                                    
Reset to Bootloader                                                                                                                                                        
Current Version: 1.2.2                                                                                                                                                     
Clear Version                                                                                                                                                              
Erase...                                                                                                                                                                   
Write...                                                                                                                                                                   
Check...                                                                                                                                                                   
Flashed succesfully                                                                                                                                                        
Clear Version                                                                                                                                                              
Writing Version: 1.2.3                                                                                                                                                     
Reset to Firmware                                                                                                                                                          
true
$ pok3rtool_cm -t prosrgb dump flash.dump                                                                                                        
WARNING: THIS TOOL IS RELATIVELY UNTESTED, AND HAS A VERY REAL RISK OF CORRUPTING YOUR KEYBOARD, MAKING IT UNUSABLE WITHOUT EXPENSIVE DEVELOPMENT TOOLS. PROCEED AT YOUR OW
N RISK.                                                                                                                                                                    
Type "OK" to continue:                                                                                                                                                     
OK                                                                                                                                                                         
Proceeding...                                                                                                                                                              
Opened MasterKeys Pro S RGB                                                                                                                                                
Dump Flash                                                                                                                                                                 
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%                                                                                                            
Out: flash.dump, 65520 bytes
$ xxd flash.dump | head -n 5
00000000: 480d 0020 1901 0000 2501 0000 2501 0000  H.. ....%...%...
00000010: 2501 0000 2501 0000 2501 0000 0000 0000  %...%...%.......
00000020: dff8 0cd0 00f0 30f8 0048 0047 8924 0000  ......0..H.G.$..
00000030: 480d 0020 0168 8d46 4168 0847 4115 0000  H.. .h.FAh.GA...
00000040: 40ea 0103 9b07 03d0 09e0 08c9 121f 08c0  @...............
hansemro commented 1 year ago

Added initial schematic drawing after a few days of tracing: https://github.com/hansemro/re-masterkeys/commit/35a5ebbd49aea75002c9e5f61e1f66275bda403c

hansemro commented 1 year ago

Added initial QMK support (key switch and USB support only): https://github.com/hansemro/qmk_firmware/tree/prosrgb_dev

hansemro commented 1 year ago

MBIA043 RE notes:

These results were discovered from firmware disassembly and testing in QMK.

QMK test branch: https://github.com/hansemro/qmk_firmware/tree/prosrgb_mbia043_testing2 QMK (soon)PR branch: https://github.com/hansemro/qmk_firmware/tree/prosrgb_mbia043_dev

Instructions

Instructions are determined by the number of DCLK rising edges while LE is asserted.

For instructions that read data from shift register, the falling edge of LE must occur shortly after the final data entry gets shifted.

Data Latch: 1 DCLK rising edge

Moves data from shift register to buffer.

Overall Latch: 2 DCLK rising edges

Moves data in buffers to comparators.

(Undocumented) Read Configuration: 4 DCLK rising edges

Moves 10-bit configuration data to shift register.

Configuration:

  MSB     ...     LSB
0b0_0_0_0_0_0_0_0_1_0 (default)
  | | | | | | | | | `-> counter disable (when 1)
  | | | | | | | | `-> unk1
  | | | | | | | `-> unk2
  | | | | | | `-> unk3
  | | | | | `-> unk4 (not saved)
  | | | | `-> unk5 (not saved)
  | | | `-> unk6 (not saved)
  | | `-> unk7 (not saved)
  | `-> unk8
  `-> unk9 (not saved)

(Undocumented) Enable Write Configuration: 18 DCLK rising edges

Enables Write Configuration instruction (if it is the next instruction).

Used by v122 firmware.

(Undocumented) Write Configuration: 8 DCLK rising edges

Moves data from shift register to (undocumented) configuration register.

Used by v122 firmware to configure each MBIA IC to 0b0000001100.

Routines

Shifting data

On every rising edge of DCLK, the shift-register shifts in data from SDI and out of SDO. This includes cases when LE is asserted high (to call an instruction using data in the shift-register).

v122 mbia_shift_data: https://github.com/hansemro/pok3r_re_firmware/blob/8346ba6d6a77e60094a02dcac3b5c8559cb7bf75/disassemble/cmprosrgb/v122/cmprosrgb_v122.txt#L13111-L13145

Sending an instruction

Set LE high until the requisite number of DCLK rising edges has been met, then set LE low. Whatever data is in the shift-register on the final DCLK edge is used for the instruction (and not a DCLK cycle later).

v122 mbia_send_instruction: https://github.com/hansemro/pok3r_re_firmware/blob/8346ba6d6a77e60094a02dcac3b5c8559cb7bf75/disassemble/cmprosrgb/v122/cmprosrgb_v122.txt#L13075-L13108

Setting grayscale values

A grayscale value for each channel must be set (starting from channel 16/OUT15) when updating comparator values. For each channel, a (10-bit) grayscale data is shifted in with LE asserted only for the last bit (Data Latch). After latching data for the final channel, send Overall Latch command.

Note that cascading MBIAs essentially become an extended shift-register, so the same general steps above apply to this case but with N * 10-bit data to shift for each channel.

v122 mbia_shift_RGB_from_sram (writes RGB data to buffers for single row): https://github.com/hansemro/pok3r_re_firmware/blob/8346ba6d6a77e60094a02dcac3b5c8559cb7bf75/disassemble/cmprosrgb/v122/cmprosrgb_v122.txt#L8413-L8490

v122 bftm1_intr (commits buffers to comparators): https://github.com/hansemro/pok3r_re_firmware/blob/8346ba6d6a77e60094a02dcac3b5c8559cb7bf75/disassemble/cmprosrgb/v122/cmprosrgb_v122.txt#L657-L708

Timing

For MBIA043 at 3.3V, DCLK has maximum allowed frequency of 25 MHz, so use the appropriate number of NOP delays to operate below this limit. (e.g. For ARM core running at 72 MHz, 3 NOPs are required to run at/below 24 MHz).

hansemro commented 1 year ago

Dimming test (shortened cycle length to reduce video length) with QMK.

https://user-images.githubusercontent.com/40348686/195756326-3854ea60-c413-4904-a0f4-0d8b56e75f63

hansemro commented 1 year ago

Per-key lighting on QMK:

https://user-images.githubusercontent.com/40348686/196301393-073a03fa-a6db-4df2-932d-af04cba0297b.mp4

hansemro commented 1 year ago

Keyboard (with QMK) hardfaults after enabling Flash Memory Security Protection bit (OB_PP[0]).

hansemro commented 1 year ago

Added a new openocd branch to enable security bits (which will be used to debug lockup when security is enabled): https://github.com/hansemro/openocd-ht32/tree/ht32f165x-security-test

> # unlocked keyboard
> halt; ht32f165x check_security 0 
[ht32f165x.cpu] halted due to debug-request, current mode: Handler External Interrupt(41)
xPSR: 0x21000039 pc: 0x00000108 msp: 0x20000d18
ht32f165x probe: 128 pages, 0x400 bytes, 0x20000 total
ht32f165x opt byte: ffffffff ffffffff ffffffff ffffffff ffffffff
ht32f165x CPSR: 0xffffffff
ht32f165x OB_CP: 0xffffffff
ht32f165x OB_CK: 0xffffffff
ht32f165x opt byte: ffffffff ffffffff ffffffff ffffffff ffffffff
ht32f165x check_security complete

# relocking keyboard
> halt; ht32f165x enable_security 0
[ht32f165x.cpu] halted due to debug-request, current mode: Handler External Interrupt(41)
xPSR: 0x01000039 pc: 0x00000134 msp: 0x20000d28
ht32f165x probe: 128 pages, 0x400 bytes, 0x20000 total
ht32f165x opt byte: ffffffff ffffffff ffffffff ffffffff ffffffff
ht32f165x programming word 0x0000 @ 0x1ff00000
ht32f165x programming word 0xffffffff @ 0x1ff00004
ht32f165x programming word 0xffffffff @ 0x1ff00008
ht32f165x programming word 0xffffffff @ 0x1ff0000c
ht32f165x programming word 0xfffffffe @ 0x1ff00010
ht32f165x programming word 0xfffffffb @ 0x1ff00020
ht32f165x Security will be set on reset
ht32f165x enable security complete

# confirming keyboard is locked after reset (unplug & plug usb)
> ht32f165x check_security 0
ht32f165x probe: 128 pages, 0x400 bytes, 0x20000 total
ht32f165x opt byte: 0000 ffffffff ffffffff ffffffff fffffffc
ht32f165x CPSR: 0xfffffffc
ht32f165x OB_CP: 0x0000
ht32f165x OB_CK: 0x0000
ht32f165x opt byte: 0000 ffffffff ffffffff ffffffff fffffffc
ht32f165x check_security complete
hansemro commented 1 year ago

While keyboard is locked, things you can do in openocd:

Some things you cannot do while locked: