Author Topic: Hacking HHKB Professional Classic  (Read 42688 times)

0 Members and 1 Guest are viewing this topic.

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Hacking HHKB Professional Classic
« on: Wed, 06 May 2020, 22:31:03 »
This is a thread to share info and discuss about Hacking HHKB Professional Classic(and Hybrid possibly).

I'll keep this first post updated for useful resources regularly. Post your findings!

Topics I'm for one mainly interested.
- Open source firmware for stock controller
- Firmware update protocol of PFU tool
- Custom controller and its firmware



HHKB Professional Classic PD-KB401W Internals
Let's start with my findings and photos:
https://gist.github.com/tmk/e0f9f49db619413d1cf45e1aecaea52e
https://imgur.com/a/p9dWvM0

More
Quote

HHKB Professional Classic PD-KB401W
===================================
2019-12-14



TODO
----


Photo album
-----------
https://imgur.com/a/p9dWvM0



STM32L072RB
-----------
LQFP64 with 128KB Flash(2-bank)

AN4767  On-the-fly firmware update for dual bank STM32
AN3156  USB DFU protocol used in the STM32 bootloader


4 bytes per word
32 words/128 bytes per page
32 pages/4K byes per sector

Memory:
0x0000 0000 Memory space mapped to Flash(0x0800 0000), System memory(0x1FF0 0000) or SRAM
0x0000 0000 top of stack address
0x0000 0004 start of codes reset handler
0x0008 0000 Memory space mapped to EEPROM(0x0808 0000)

0x0800 0000 Flash 128KB
0x0800 0000 Bank1 Flash 64KB
0x0800 FFFF
0x0801 0000 Bank2 Flash 64KB
0x0801 FFFF
0x0808 0000 EEPROM 6K
0x0808 0000 Bank1 EEPROM 3KB
0x0808 0BFF
0x0808 0C00 Bank2 EEPROM 3KB
0x0808 17FF
0x1FF0 0000 System memory 8K - Bootloader
0x1FF0 1FFF
0x1FF8 0000 Option bytes 32 bytes
0x1FF8 001f
0x1FF8 0020 Factory option byte 96 bytes
0x1FF8 007F
0x2000 0000 SRAM 20K
0x2000 4FFF SRAM    0x2000 20c0/0x2000 20b8
0x4000 0000 Peripherals
0x5000 0000 IOPORT


Keymap format in Flash/EEPROM:
------------------------------
Keymap is comprised of 128 bytes and defines 61 keys in first 64 bytes, followed by 64-byte '0x00'.

This is dump of 256 bytes from eeprom, for example. It define 2 layers for HHKB mode.

    00000000: 00 8a e6 2c e2 8b 01 e5 38 37 36 10 11 05 19 06  ...,....876.....
    00000010: 1b 1d e1 28 34 33 0f 0e 0d 0b 0a 09 07 16 04 e0  ...(43..........
    00000020: 4c 30 2f 13 12 0c 18 1c 17 15 08 1a 14 2b 35 31  L0/..........+51
    00000030: 2e 2d 27 26 25 24 23 22 21 20 1f 1e 29 00 00 00  .-'&%$#"! ..)...
    00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000080: 00 78 e6 2c e2 8b 01 e5 51 4e 4d 10 11 05 19 06  .x.,....QNM.....
    00000090: 1b 1d e1 28 4f 50 4b 4a 0d 0b 0a 09 07 16 04 e0  ...(OPKJ........
    000000a0: 2a 30 52 48 47 46 18 1c 17 15 08 1a 14 2b 4c 49  *0RHGF.......+LI
    000000b0: 45 44 43 42 41 40 3f 3e 3d 3c 3b 3a 29 00 00 00  EDCBA@?>=<;...
    000000c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    000000d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

    0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
    ----------------------------------------------------------------
    ?   RGu RAl spc LAl LGu Fn  RSh /   .   ,   m   n   b   v   c
    x   z   Lsh Ret '   ;   l   k   j   h   g   f   d   s   a   Ctl
    Del ]   [   p   o   i   u   y   t   r   e   w   q   Tab `   \
    =   -   0   9   8   7   6   5   4   3   2   1   Esc ?   ?   ?






Boot Sequence
-------------
The device is configured with BFB2=0, nBOOT1=1 in option bytes and BOOT0 pin is pulled low(BOOT0=0) and it should boot at Bank1 on Flash memory.

With HHKB STM32 standard Dual bank boot sequence is not enabled(BFB2=0), it boots always from Bank1 and firmware on Bank1 checks Bank2 firmware inegrity and execute it somehow probably.
If Bank2 firmware is not valid Bank1 firmware continues to run anyway instead.

Bank1: original firmware and not updated? firmware linked with 0x0800 0000
Bank2: The latest firmware which usually runs and updated by Bank1 firmeware. firmware linked with 0x0801 0000

PFU firmeare is not compatible with STM32 dual-bank boot sequence by System bootloader



RM0376 3.3.2
When the BFB2 bit is set and the boot pins are configured to boot from Flash memory
(BOOT0 = 0 and BOOT1 = x), the device maps the System memory at address 0. Bootloader runs after reset and check Bank2 first and then Bank1.
When Bank2 is valid Bootloader sets UFB in SYSCFG_CFGR1 to map Bank2 at address 0x0800 0000(bank swap) and jump there.
When Bank2 is not valid and Bank1 is valid  Bootloader keeps UFB 0 and jump to Bank1 at 0x0800 0000.
When both banks are not valid Bootloader continues to run for progamming Flash memory.



On-the-fly live update
----------------------
The goal of the live field upgrade is to make the transition to a new code version without
going through the system reset.

Codes in both banks are normally linked to start at address 0x0800 0000: AN4767 3.1.1
By bank swap Bank1 or Bank2 can be mapped at 0x0800 0000 depending on UFB setting.

Concerns about transition of execution from one bank to another: AN4767 4
Both banks have unmodifiable and fixed code section which keeps stack at the lowest as possible to make the transition.
Remember that having identical source code does not implicate that identical binary codes
will be generated. It is better to generate a library to be linked to all future versions, or
preserve an object file, or (perhaps) even carefully edit the resulting binary




Dip Switch
----------
SW1,SW2: Keymap mode

    00 HHK: Henkan and Muhenkan on Gui keys, Disables Volume and Power key, Enables Stop key(Cancel)
    10 WIN: Disables Volume and Power key, Disables Stop key
    01 MAC: Enables Volume and Power key, Disables Stop key
    11 N/A: Inhibited.

SW3: Delete/Backspace
SW4: Left Super/Fn
SW5: Alt/Super
SW6: Power saving(Remote wakeup)


Internals
---------
Switch board:
1.6mm thick PCB
CNL1:   Connector I-PEX CABLINE-VS 30pin, receptacle: 20455-030E-99, https://www.i-pex.com/product/cabline-vs
U1, U2: LW051A TSSOP 16pin, TI SN74LV4051A, http://www.ti.com/lit/ds/symlink/sn74lv4051a.pdf
U3:     Non populated
U4:     AYO7A48 10pin, OPA2373AID, OPAmp, https://www.ti.com/lit/ds/symlink/opa2373.pdf
Q8:     MOSFET switching 21-Signal

Controller board:
2.0mm thick PCB
Z2 STM32L072RBT6 https://www.st.com/resource/en/datasheet/stm32l072rb.pdf
    ADC: AN2668
    Bootloader: AN2606

    Z2.1  VDD
    Z2.2  PC13  (Power Switch for Battery?)
    Z2.3  PC14  (Power Switch TPS2065D for Switch board)
    Z2.4  PC15  (pull down with 10K)
    Z2.5  (Xtal) NP
    Z2.6  (Xtal) NP
    Z2.7  NRST  (to CN3)
    Z2.8  PC0   (pull down with 10K)
    Z2.9  PC1   (pull down with 10K)
    Z2.10 PC2   ?? for JP layout?
    Z2.11 PC3   (pull down with 10K)
    Z2.14 PA0   (pull down with 10K)
    Z2.15 PA1   Signal input
    Z2.16 PA2   (pull down with 10K)

    Z2.17 PA3   (DIPSW-1)
    Z2.18 VSS
    Z2.19 VDD
    Z2.20 PA4   (DIPSW-2)
    Z2.21 PA5   (DIPSW-3)
    Z2.22 PA6   (DIPSW-4)
    Z2.23 PA7   (DIPSW-5)
    Z2.24 PC4   (DIPSW-6)
    Z2.25 PC5   (Push button for Bluetooth)
    Z2.26 PB0   Row drive
    Z2.27 PB1   Row drive
    Z2.28 PB2   Row drive
    Z2.29 PB10  Row drive
    Z2.30 PB11  (Row drive for JP layout?)
    Z2.31 VSS
    Z2.32 VDD

    Z2.33 PB12  COL A
    Z2.34 PB13  COL B
    Z2.35 PB14  COL C
    Z2.36 PB15  U1 ~EN
    Z2.37 PC6   U2 ~EN
    Z2.38 PC7   OPAmp EN
    Z2.39 PC8   Q8.5-gate capacitor discharge
    Z2.40 PC9   ??
    Z2.41 PA8   ~LED1
    Z2.42 PA9   ~LED2
    Z2.43 PA10  ??
    Z2.44 (USB_DM)
    Z2.45 (USB_DP)
    Z2.46 (SWIO  to CN3)
    Z2.47 VSS
    Z2.48 VDD_USB 3.3V from regulator

    Z2.49 SWCLK (to CN3)
    Z2.50 PA15  (to Bluetooth module) pull up with 51K R130
    Z2.51 PC10  (pull down with 10K)
    Z2.52 PC11  (pull down with 10K)
    Z2.53 PC12  (pull down with 10K)
    Z2.54 PD2   (to Bluetooth module) pull down with 51K R83 module reset??
    Z2.55 PB3   (to Bluetooth module) pull up with 51K R127
    Z2.56 PB4   (to Bluetooth module) pull up with 51K R128
    Z2.57 PB5   (to Bluetooth module) pull up with 51K R129
    Z2.58 PB6   (to Bluetooth module) pull up with 51K R131
    Z2.59 PB7   (Battery Voltage Monitor)
    Z2.60 BOOT0 pull down with 10K R6
    Z2.61 PB8   (Battery Voltage Monitor)
    Z2.62 PB9   (Battery Voltage Monitor)
    Z2.63 VSS
    Z2.64 VDD

Z7 V20 1GY, Voltage Regulator 3.3V
Z8 ?? Voltage monitor for Z7?
Z6 2065 SOT-23-5 TI TPS2065D http://www.ti.com/lit/ds/symlink/tps2065d.pdf
R85 0Ohm connects USB Power(3.3V regulated) and Battery Power for USB only Classic
Z15 Not populated. Power switch between USB power and Battery power
CN5 Not populated. Connector for battery
CN3 SWD Z2.7(NRST), Z2.49(SWCLK), Z2.46(SWDIO)
Z3  Reset IC connected to Z2.7(NRST)
Z5  Boost converter for Battery power
Z12 Voltage Monitor to shutdown Z5 when low voltage?
Z17, Z10, Z11 Voltage Monitor for Battery
Z4  Buck converter?

Switch board connector                                                          Controller board connector
1       Row drive                                                               30      Z2.26 PB0
2       U1-4051A.INH(Turns on output with Lo.)                                  29      Z2.36 PB15
3       U1,U2-4051A.B                                                           28      Z2.34 PB13
4       Row drive                                                               27      Z2.27 PB1
5       U1,U2-4051A.C                                                           26      Z2.35 PB14
6       Row drive                                                               25      Z2.28 PB2
7       U1,U2-4051A.A                                                           24      Z2.33 PB12
8       Row drive                                                               23      Z2.29 PB10
9       U2-4051A.INH(Turns on output with Lo.)                                  22      Z2.37 PC6
10      NC? Row for JP layout??                                                 21      Z2.30 PB11(not controlled)
11      ~LED1.Kathode                                                           20      Z2.41 PA8 thr Q6 Digital-Tr
12      ~LED2.Kathode                                                           19      Z2.42 PA9 thr Q2 Digital-Tr
13      Q12.2-gate not populated. ??  Not controlled                            18      Z2.40 PC9
14      U4.5,6(OPAmp EnableA,B)                                                 17      Z2.38 PC7
15      NC?                                                                     16      Z2.43 PA10  with 510K pull-up
16      Q8.5-gate  discharge? before row drive                                  15      Z2.39 PC8
17      NC?(for JP layout?)                                                     14      Z2.10 PC2
18      GND                                                                     13      GND
19,20   AGND                                                                    11,12   AGND=GND
21      Signal from OPAmp                                                       10      Z2.15 PA1
22,23   AGND                                                                    8,9     AGND=GND
24-26   GND                                                                     5-7     GND
27-29   VCC(3.3V)                                                               2-4     Switched by Z6(TPS2065D) Z2.3
30      LED Power(3.3V): through R43, R44 to LED1.Anode, LED2.Anode             1       VCC 3.3V



Scan Key Matrix
===============
Scan matrix takes 4.8ms per 20ms

    for (15 colums)
        for (4 rows)
            Row Drive
            Sense keys


    Matrix on PCB:

            U1                              U2
            Y0  Y3  Y1  Y2  Y4  Y5  Y6  Y7  Y3  Y0  Y1  Y2  Y4  Y6  Y5
            0   1   2   3   4   5   6   7   8   9   a   b   c   d   e
            ------------------------------------------------------------
    PB1     Esc 1   2   3   4   5   6   7   8   9   0   -   =   \   `
    PB2     Tab q   w   e   r   t   g   y   u   i   o   p   [   ]   Del
    PB10    Ctl a   s   d   c   v   b   h   j   k   l   ;   '   Ret Fn
    PB0     LSh LAl z   x   LGu f   spc n   m   ,   .   RGu /   RSh RAl


    Matrix Scan order:
   
            U1                              U2
            Y0  Y1  Y2  Y3  Y4  Y5  Y6  Y7  Y0  Y1  Y2  Y3  Y4  Y5  Y6
            0   2   3   1   4   5   6   7   9   a   b   8   c   e   d
            -----------------------------------------------------------
    PB0     LSh z   x   LAl LGu f   spc n   ,   .   RGu m   /   RAl RSh
    PB1     Esc 2   3   1   4   5   6   7   9   0   -   8   =   `   \
    PB2     Tab w   e   q   r   t   g   y   i   o   p   u   [   Del ]
    PB10    Ctl s   d   a   c   v   b   h   k   l   ;   j   '   Fn  Ret



Col Select
----------
It takes 4.8ms to scan all keys on 4x15 matrix

         |                                                   |20ms
      ___                 _________________ ............. ___                 _____
    U1   |_______________|                                   |_______________|       
          _______________                                     _______________       
    U2___|               |_________________ ............. ___|               |______
         | U1.enable     |2.5ms
                         | U2.enable   |2.3ms
     ____         _______         _________
    C    |_______|       |_______|
     ____     ___     ___     ___     _____
    B    |___|   |___|   |___|   |___|
            _   _   _   _   _   _   _
    A______| |_| |_| |_| |_| |_| |_| |_____
          0 1 2 3 4 5 6 7 0 1 2 3 4 5 6
         | |320us
         |                             |4.8ms


Row Drive
---------
Wave form of drive: https://i.imgur.com/AHe1m27.png
Four rows driven: https://i.imgur.com/paKkbNF.png

             _  3.3V                 _
            | |                     | |
            | |                     | |
            |  \                    |  \
    ROW0____|   \___________________|   \____
            | |20us
            |    |80us
            |                       |320us
                   _                       _
                  | |                     | |
                  | |                     | |
                  |  \                    |  \
    ROW1__________|   \___________________|   \____
                         _                       _
                        | |                     | |
                        | |                     | |
                        |  \                    |  \
    ROW2________________|   \___________________|   \____
                               _                       _
                              | |                     | |
                              | |                     | |
                              |  \                    |  \
    ROW3______________________|   \___________________|   \____

            |        COL0           |        COL1           |   ...             COL14       |
            |                                                                               |4.8ms

A row driven around 4.8ms(320us*15): https://i.imgur.com/Pg2XIUa.png
A row driven for 15 columns and output of OpAmp: https://i.imgur.com/6cQ6uIg.png



Sense key
---------
0. Select a column
1. Enable OpAmp
2. Discharge capcitor
    Sample capacitor C57 retaining voltage of previous key and is dischared?
3. Drive a row
    Signal is amplified and stored in capacitor C57?
4. Sensed by Controller
5. Shutdown OpAmp
6. loop 2-5 for rows



Signal for discarging capacitor: https://i.imgur.com/aRtHkPi.png

           ||    ||    ||    || discharge
           ||    ||    ||    ||
           ||    ||    ||    ||
    Q8.g __||____||____||____||_____
           ||7us


Row drive and output from OpAmp: https://i.imgur.com/I91TQpL.png
Row drive and output from OpAmp: https://i.imgur.com/2g2jq8d.png
Row drive and output from OpAmp: https://i.imgur.com/scxqnAv.png
             _     _     _     _   
            | |   | |   | |   | |   
            | |   | |   | |   | |   
            |  \  |  \  |  \  |  \ 
    ROWn ___|   \_|   \_|   \_|   \_
            | |20us
            |     |80us

             ____  2.3V(depressed)
            |    |
            |    |
            |    | 600mV(normal)
    Sense_--|    |-----------------_ output from OpAmp

    OPAmp_____   ___   ___   ___   _ enable
              | |   | |   | |   | |
              | |   | |   | |   | |
              | |   | |   | |   | |
              |_|   |_|   |_|   |_|  shutdown
              | |22us
                |   |53us





USB info
========

    /var/log/kern.log:
    Dec 14 11:46:49 desk kernel: [774252.335808] usb 3-3.2: new full-speed USB device number 35 using xhci_hcd
    Dec 14 11:46:49 desk kernel: [774252.452770] usb 3-3.2: New USB device found, idVendor=04fe, idProduct=0020
    Dec 14 11:46:49 desk kernel: [774252.452774] usb 3-3.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
    Dec 14 11:46:49 desk kernel: [774252.452776] usb 3-3.2: Product: HHKB-Classic
    Dec 14 11:46:49 desk kernel: [774252.452778] usb 3-3.2: Manufacturer: PFU Limited
    Dec 14 11:46:49 desk kernel: [774252.475927] input: PFU Limited HHKB-Classic as /devices/pci0000:00/0000:00:08.1/0000:38:00.3/usb3/3-3/3-3.2/3-3.2:1.0/0003:04FE:0020.01A4/input/input323
    Dec 14 11:46:49 desk kernel: [774252.536337] hid-generic 0003:04FE:0020.01A4: input,hidraw2: USB HID v1.11 Keyboard [PFU Limited HHKB-Classic] on usb-0000:38:00.3-3.2/input0
    Dec 14 11:46:49 desk kernel: [774252.543236] input: PFU Limited HHKB-Classic as /devices/pci0000:00/0000:00:08.1/0000:38:00.3/usb3/3-3/3-3.2/3-3.2:1.1/0003:04FE:0020.01A5/input/input324
    Dec 14 11:46:49 desk kernel: [774252.600164] hid-generic 0003:04FE:0020.01A5: input,hidraw3: USB HID v1.11 Keyboard [PFU Limited HHKB-Classic] on usb-0000:38:00.3-3.2/input1
    Dec 14 11:46:49 desk kernel: [774252.604075] hid-generic 0003:04FE:0020.01A6: hiddev1,hidraw4: USB HID v1.11 Device [PFU Limited HHKB-Classic] on usb-0000:38:00.3-3.2/input2


USB Intefaces
-------------
0: Boot Keyboard EP1IN(6KRO)
1: NKRO Keyboard and Consumer keys EP2IN
    Reprot ID 1: Consumer Media keys
    Reprot ID 2: NKRO Keyboard(Not used)
    Reprot ID 3: Consumer Application Launch/Control keys(Not used)
2: Vendor specific EP3IN, EP4OUT
    for keymap/firmware update


USB Descriptor
--------------
https://gist.github.com/tmk/5f22878a7ddca01e9174e5d6224395d2




DFU Bootloader
==============
To kick up System bootloader plugin with pulling up BOOT0 pin.

    $ dfu-util -l
    dfu-util 0.9

    Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
    Copyright 2010-2016 Tormod Volden and Stefan Schmidt
    This program is Free Software and has ABSOLUTELY NO WARRANTY
    Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

    Found DFU: [0483:df11] ver=2200, devnum=87, cfg=1, intf=0, path="3-3.2", alt=2, name="@DATA Memory /0x08080000/2*3Ke", serial="164738450000"
    Found DFU: [0483:df11] ver=2200, devnum=87, cfg=1, intf=0, path="3-3.2", alt=1, name="@Option Bytes  /0x1FF80000/01*032 e", serial="164738450000"
    Found DFU: [0483:df11] ver=2200, devnum=87, cfg=1, intf=0, path="3-3.2", alt=0, name="@Internal Flash  /0x08000000/1536*128g", serial="164738450000"



Flash
-----
Get Flash content(128KB) through bootloader.

    $ dfu-util -a 0 -s 0x08000000 -U hhkb-flash.bin


It is comprised of two memory bank.

    First part 64KB
    00000   unknown. Programming interface for update keymap and firmware?
    :   :
    0ffff

    Second part 64KB
    10000   identical to bin part of HHKB401_FW_A426.hfb
    :   :
    1ffff

Firwmware is common for both US and JP layout and has different keymaps for them.
US keymaps is located around 0x0000cd20 while JP is around 0x0000c300.

Version of original firmware
    0x0000 c100     0b 04 01 06     B4.1.6 (bank1)
    0x0001 c150     0a 04 02 06     A4.2.6 (bank2)



EEPROM
------
It seems like keymap is stored in EEPROM. DIP switch key configuration affects on keymap in EEPROM.
It seems to have key sense calibration data in EEPROM also. After EEPROM broken accidentally some keys never been released. Restoring original EEPROM data cured the issue.

keymaps(128 byte per layer):

    0x0000 HHK default
    0x0080 HHK Fn
    0x0100 MAC default
    0x0180 MAC Fn
    0x0200 WIN default
    0x0280 WIN Fn

Other infos:

    0x0300 Keyboard ID and version(A4.2.6)

    00000300: aa aa 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00000310: 50 44 2d 4b 42 34 30 31 57 00 00 00 00 00 00 00  PD-KB401W.......
    00000320: 00 00 00 00 41 30 00 00 43 31 38 4c 30 30 30 32  ....A0..C18L0002
    00000330: 38 39 00 00 00 00 00 00 0a 04 02 06 00 00 00 00  89..............
    00000340: 0b 04 01 06 00 00 00 00 00 00 00 00 00 00 00 00  ................



Get EEPROM content through DFU bootloader.

    $ dfu-util -a 2 -s 0x08080000 -U hhkb-eeprom.bin
    dfu-util 0.9

    Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
    Copyright 2010-2016 Tormod Volden and Stefan Schmidt
    This program is Free Software and has ABSOLUTELY NO WARRANTY
    Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

    Opening DFU capable USB device...
    ID 0483:df11
    Run-time device DFU version 011a
    Claiming USB DFU Interface...
    Setting Alternate Setting #2 ...
    Determining device status: state = dfuIDLE, status = 0
    dfuIDLE, continuing
    DFU mode device DFU version 011a
    Device returned transfer size 2048
    DfuSe interface name: "DATA Memory "
    Limiting upload to end of memory segment, 6144 bytes
    Upload  [=========================] 100%         6144 bytes
    Upload done.


Option Btyes
------------
The Option bytes are automatically loaded during the boot. They are used to set the content of the FLASH_OPTR
and FLASH_WRPROTx registers. RM0376 3.8
32-byte data

    $ dfu-util -a 1 -s 0x1FF80000:32 -U hhkb-opt.bin


    00000000: aa 00 55 ff 70 80 8f 7f 00 00 ff ff 00 00 ff ff  ..U.p...........
    00000010: 00 00 ff ff 00 00 00 00 00 00 00 00 00 00 00 00  ................

FLASH_OPTR: RM0376 3.7.8
    0x8070 00aa
    nBOOT1: 1
    BOR_LEV:0 BOR OFF
    BFB2:   0
    WPRRMOD:0
    RDPROT: 0xAA Protection Level 0

FLASH_WRPROT1: RM0376 3.7.9
    0x0000 0000
FLASH_WRPROT2
    0x---- 0000

    48-bit: flash memroy sector protection configuration up to 192KB(48*4K sector)
    0: sector not protected
    1: sector protected







HHKB Keymap/Firwamre Update
===========================
Keyboard firmware supports the update feature with interface2 ep3 and 4.


Protocol
--------
Host command format: 0xaa,0xaa,cmd(1-byte),0x00,len(1-byte, length of data),data...
Keyboard response format: 0x55,0x55,cmd(1-byte)

command byte:

    01  echo                            AA,AA,01,00,01,00
                                        response:
                                        55,55,01,00

    02  read ID and version             AA,AA,02,00,00
                                        response:
                                        55,55,02,00,00,39,(eeprom data at 0x310) - confirmed.
                                        model name and serial number are picked from eeprom at 0x310 while firmware
                                        version come from firmware code itself.
                                        The last byte at end of data indicates integrity of A(Bank2) and the byte
                                        turns 0x01 when the firmware is broken.

                                        eemprom data:
                                        00000310: 50 44 2d 4b 42 34 30 31 57 00 00 00 00 00 00 00  PD-KB401W.......
                                        00000320: 00 00 00 00 41 30 00 00 43 31 38 4c 30 30 30 32  ....A0..C18L0002
                                        00000330: 38 39 00 00 00 00 00 00 0a 04 02 06 00 00 00 00  89..............
                                        00000340: 0b 04 01 06 00 00 00 00 00                       .........
                                        Note that version info of 0a 04 02 06 and 0b 04 01 06 in eeprom are not used.
                                        It means firmware version 4.2.6 in A(Bank2) and 4.1.6 in B(Bank1).

    05  read DIP Switch                 AA,AA,05,00,00
                                        response:
                                        55,55,05,00,00,0c,DIP1,DIP2,DIP3,DIP4,DIP5,DIP6,00,00,00,00,00,00
                                        (00: OFF, 01: ON) - confirmed.

    06  key config                      AA,AA,06,00,00
                                        response:
                                        55,55,06,00,00,00(HHK) or 55,55,06,00,00,01(MAC) or 55,55,06,00,00,02(WIN)

    87  read keymap(two layers)         AA,AA,87,00,02,(key config:[0|1|2]),(layer:[0|1])
                                        response:
                                        55,55,87,00,41,3a,(eeprom data)
                                        55,55,87,00,82,3a,(eeprom data)
                                        55,55,87,00,c3,0c,(eeprom data)
                                        where keymap size: 128 bytes(0x3a+0x3a+0c)
                                              eeprom data: HHK layer.0 at 0x0000
                                                           HHK layer.1 at 0x0080
                                                           MAC layer.0 at 0x0100
                                                           MAC layer.1 at 0x0180
                                                           WIN layer.0 at 0x0200
                                                           WIN layer.1 at 0x0280

    e0  firmware update start?          e0,00,00
    e1  ??                              e1,00,08,22,00,01,00,aa,d7,00,00
    e2                                  e2,00,len,lsb,msb,data(firmware binary) where lsb and msb is sequence number
    e3  firmware update end?            e3,00,00




HHKB firmware file format .hfb
------------------------------
HHKB401_FW_A426.hfb - Firmware file for PD-KB401 downloaded from PFU site at 2019-12-11

The firmware is identical to 2nd part 64KB of hhkb-flash.bin.

Size: 65570 bytes = 64KB bin file(65536) + pre/postfix 34 bytes

"8f 03" part of Prefix can be located at 0x0370 in eeprom

    Prefix:
    aa d7 8f 03

    Bin(64KB)

    Postfix:
    ff ff ff ff ff ff ff ff ff ff ff ff ff ff 41 48 48 58 30 31 0a 04 02 06 ff ff ff ff ff ff
    .......AHHX01..........


Description below includes vague speculation.

HHKB800_FW_A036.hfb - for Hybrid PD-KB800
    Size: 282672 bytes  276KB(282624) + pre/postfix 48bytes???

    Prefix:
    00000000: 16 c8 ae ad

    Postfix:
    00045020: 41 48 55 58 30 31 0a 00 03 06 ff ff ff ff ff ff  AHUX01..........

    +-----------+
    |   64KB    |   firmware for STM32???
    +-----------+
    |           |
    |   148KB   | 
    |           |
    +-----------+
    |   64KB    | 
    +-----------+

HHKB800_FW_JP_A236.hfb - for Hybrid JP  PD-KB820
    Prefix:
    00000000: 48 ad 05 fc

    Postfix:
    00045020: 41 48 4a 58 30 31 0a 02 03 06 ff ff ff ff ff ff  AHJX01..........




Useful resources:
Remapping the 2019 HHKB Classic by crsayen
https://geekhack.org/index.php?topic=106001.0
« Last Edit: Wed, 06 May 2020, 22:59:43 by hasu »

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Hacking HHKB Professional Classic
« Reply #1 on: Wed, 06 May 2020, 23:00:00 »
Crack open your HHKB and void warranty!


Offline crsayen

  • Posts: 4
Re: Hacking HHKB Professional Classic
« Reply #2 on: Thu, 07 May 2020, 00:28:41 »
Awesome work! I cracked open my board earlier today and started looking at the firmware in ghidra. It looks like you are way ahead of me!

I will be spending some time on this tomorrow.

Thanks for sharing your findings!

Offline crsayen

  • Posts: 4
Re: Hacking HHKB Professional Classic
« Reply #3 on: Thu, 07 May 2020, 07:50:12 »
I have a lot of "source" code for a certain keymapping tool. I am adding some relevant files here.

if anyone wants to see more files, download dotPeek and open the exe.

KeyboardDriver.cs
https://gist.github.com/crsayen/58ad65038e463c13fb9caa566fea2ce2

USBDriver.cs
https://gist.github.com/crsayen/ffea66d1fbfa5d91e929ffdfd4f02d69

KeyboardLibrary.cs
https://gist.github.com/crsayen/e06c3650306a01232521e336e45ca134
« Last Edit: Thu, 07 May 2020, 09:31:41 by crsayen »

Offline Gondolindrim

  • Posts: 686
  • Location: Gondolin
    • My GitHub
Re: Hacking HHKB Professional Classic
« Reply #4 on: Thu, 07 May 2020, 09:03:39 »
I'm curious as to why they went with a dual-bank MCU this time. Honestly I don't think it's needed for this application, but maybe a little bit more hacking into the firmware might tell us

Nice job as always, Hasu
A pessimist will tell you the cup is half empty. An optimist will tell you the cup is half full. An engineer will tell you it's exactly twice the size it needs to be.

Offline Applet

  • Posts: 487
  • Location: Sweden
Re: Hacking HHKB Professional Classic
« Reply #5 on: Thu, 07 May 2020, 09:34:08 »
Very exciting stuff! It would be fantastic if it is possible to run open source software TMK/QMK on the stock controller :D

Thanks for the work hasu!

Offline crsayen

  • Posts: 4
Re: Hacking HHKB Professional Classic
« Reply #6 on: Thu, 07 May 2020, 10:21:33 »
Quote
- Firmware update protocol of PFU tool

Code: [Select]
private async Task<bool> FirmupSend(uint dataNumber, byte[] data)
    {
      KeyboardDriver keyboardDriver1 = this;
      System.Diagnostics.Debug.WriteLine("[FirmupSend] 1");
      dataNumber -= 2U;
      data = ((IEnumerable<byte>) data).Skip<byte>(2).ToArray<byte>();
      System.Diagnostics.Debug.WriteLine("[FirmupSend] 3");
      uint numberOfPacket = (uint) ((int) dataNumber + 57 - 1) / 57U;
      uint completedByteLength = 0;
      for (ushort packetNumber = 0; (uint) packetNumber < numberOfPacket; ++packetNumber)
      {
        KeyboardDriver keyboardDriver = keyboardDriver1;
        System.Diagnostics.Debug.WriteLine(string.Format("[FirmupSend] 4 ({0}", (object) packetNumber));
        uint num1 = (uint) packetNumber * 57U;
        uint num2 = (uint) (((int) packetNumber + 1) * 57);
        if (dataNumber <= num2)
          num2 = dataNumber;
        uint length = num2 - num1;
        byte[] input = new byte[ConstDefinition.BufferSizeUSB];
        input[0] = input[1] = (byte) 170;
        input[2] = (byte) 226;
        input[4] = (byte) (length + 2U);
        byte[] packetNumberByte = keyboardDriver1.toolUtility.ConvertUshortToBytes(packetNumber);
        input[5] = packetNumberByte[0];
        input[6] = packetNumberByte[1];
        for (int index = 0; (long) index < (long) length; ++index)
          input[7 + index] = data[(long) num1 + (long) index];
        byte[] output = new byte[0];
        System.Diagnostics.Debug.WriteLine(string.Format("[FirmupSend] 5 ({0}", (object) packetNumber));
        await Task.Run((Action) (() => output = keyboardDriver.WriteReadCheck(input, new byte[6]
        {
          (byte) 85,
          (byte) 85,
          (byte) 226,
          (byte) 0,
          (byte) 0,
          (byte) 2
        }, "0xE2")));
        System.Diagnostics.Debug.WriteLine(string.Format("[FirmupSend] 6 ({0}", (object) packetNumber));
        if (output == null)
          return false;
        if ((int) output[6] != (int) packetNumberByte[0] || (int) output[7] != (int) packetNumberByte[1])
        {
          System.Diagnostics.Debug.WriteLine(string.Format("Keyboard Communication Error 0xE2 (format error)"));
          System.Diagnostics.Debug.WriteLine(string.Format("receiveData = {0}", (object) BitConverter.ToString(output)));
          return false;
        }
        completedByteLength += length;
        int completedRate = 10 + (int) (completedByteLength * 80U / dataNumber);
        keyboardDriver1.eventAggregator.GetEvent<NortificateFirmupProgressEvent>().Publish(new NortificateFirmupProgressEventEntity(completedRate));
        packetNumberByte = (byte[]) null;
      }
      System.Diagnostics.Debug.WriteLine("[FirmupSend] 7");
      return true;
    }

This looks like it gives a good idea of how the data is sent. Prior to sending firmware data, the tool sends this:

Code: [Select]
private bool FirmupStart(uint firmSize, byte[] crc)
    {
      byte[] input = new byte[ConstDefinition.BufferSizeUSB];
      input[0] = input[1] = (byte) 170;
      input[2] = (byte) 225;
      input[3] = (byte) 0;
      input[4] = (byte) 8;
      byte[] bytes = this.toolUtility.ConvertUintToBytes(firmSize);
      for (int index = 0; index < 4; ++index)
        input[5 + index] = bytes[index];
      input[9] = crc[0];
      input[10] = crc[1];
      return this.WriteReadCheck(input, new byte[6]
      {
        (byte) 85,
        (byte) 85,
        (byte) 225,
        (byte) 0,
        (byte) 0,
        (byte) 0
      }, "0xE1") != null;
    }

and to finish the firmware upload:

Code: [Select]
    private bool FirmupEnd()
    {
      byte[] input = new byte[ConstDefinition.BufferSizeUSB];
      input[0] = input[1] = (byte) 170;
      input[2] = (byte) 227;
      return this.WriteReadCheck(input, new byte[6]
      {
        (byte) 85,
        (byte) 85,
        (byte) 227,
        (byte) 0,
        (byte) 0,
        (byte) 0
      }, "0xE3") != null;
    }

I am looking into whether we can just trick the tool into uploading custom firmware for us.
If not, I will modify it to do so.

Offline vffems2529

  • Posts: 4
Re: Hacking HHKB Professional Classic
« Reply #7 on: Thu, 07 May 2020, 11:32:20 »
Does this mean there is a chance of programmability of these boards (Hybrid/Classic) using VIA?
How can the community help with these efforts?

Offline power_ranger

  • Posts: 1
Re: Hacking HHKB Professional Classic
« Reply #8 on: Sun, 27 December 2020, 13:38:20 »
Really awesome work! So is it possible to port QMK/TMK to the stock controller of Pro Classic?

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Hacking HHKB Professional Classic
« Reply #9 on: Sun, 27 December 2020, 16:57:56 »
Yes

Offline vladimir108

  • Posts: 204
Re: Hacking HHKB Professional Classic
« Reply #10 on: Mon, 11 January 2021, 13:42:34 »
Really awesome work! So is it possible to port QMK/TMK to the stock controller of Pro Classic?

Yes

Amazing! Wow!

Offline tiydal

  • Posts: 58
  • Location: UK
Re: Hacking HHKB Professional Classic
« Reply #11 on: Sat, 20 March 2021, 17:13:48 »
Really awesome work! So is it possible to port QMK/TMK to the stock controller of Pro Classic?

Yes

This is really exciting! Doing great work for the community here.

Offline GoatMaster

  • Formerly Franatic89
  • Posts: 154
  • Location: Germany
Re: Hacking HHKB Professional Classic
« Reply #12 on: Thu, 25 March 2021, 06:09:23 »
Are there any news on this?

Still waiting to buy the HHKB Professional Classic until I can use it with QMK.

Offline liangalv

  • Posts: 35
Re: Hacking HHKB Professional Classic
« Reply #13 on: Thu, 03 June 2021, 17:46:41 »
Has work on the controller been abandoned due to the JSON work around? I’m still looking to get a classic to avoid the battery bump with a bluetooth capable HHKB. (Plus QMK compatibility helps)

Offline Mistah

  • Posts: 65
Re: Hacking HHKB Professional Classic
« Reply #14 on: Tue, 08 June 2021, 08:30:30 »
Is anyone currently working on flashing custom firmware on the existing controller? Interested in helping out, but have had cold feet on actually buying one because my workflow is helplessly dependent on QMK

Offline Duncaen

  • Posts: 3
Re: Hacking HHKB Professional Classic
« Reply #15 on: Sun, 15 January 2023, 15:31:47 »
I think I'm typing this from the first HHKB Professional Classic running qmk. There is still a lot of work to do, but the basics are working.

The current code:
https://github.com/Duncaen/qmk_firmware/tree/hhkb_classic

I'm currently flashing the firmware by shorting BOOT0 to get into the DFU bootloader, which is a bit cumbersome.
I don't think there is a way to make it boot into the dfu bootloader without doing that so I might need to come up with a better solution.
Maybe some flash mode while qmk is running similar to the original firmware, maybe also using the dual bank mechanism.

I'm still trying to find out what the best values to use are for the activation point of the switches is and if it would be better with per key values which I think the original firmware does, the gist from hasu has some info about calibration data in EEPROM.

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Hacking HHKB Professional Classic
« Reply #16 on: Sun, 15 January 2023, 18:32:33 »
Great job!

Let us know if you have any your new find or correction on my note.

Offline Duncaen

  • Posts: 3
Re: Hacking HHKB Professional Classic
« Reply #17 on: Mon, 23 January 2023, 18:24:33 »
Here are the most interesting addresses in the eeprom:

Code: [Select]
0x08080000 u8[128] keymap_hhk_layer_0
0x08080080 u8[128] keymap_hhk_layer_1

0x08080100 u8[128] keymap_mac_layer_0
0x08080180 u8[128] keymap_mac_layer_1

0x08080200 u8[128] keymap_win_layer_0
0x08080280 u8[128] keymap_win_layer_1

0x08080300 u16     keymap_eeprom # 0xAAAA to load keymap from eeprom, otherwise default keymaps from flash are used.

0x08080310 u8[64]  keyboard_info
0x08080350 u16     keyboard_info_eeprom # 0xAAAA to load info from keyboard otherwise data from flash is used.
0x08080360 bool    boot_bank2
0x08080370 u16     bank2_crc16
# crc16(-ccitt?) polynomial=0x1021 initial_value=0xFFFF reverse_input=True reverse_output=True final_xor_value=0x0000

0x08081100 u16[128] actuation_points_0
0x08081200 u16[128] actuation_points_1
# If the first value in actuation_points_1 is zero all calibration is disabled.
# My eeprom only the first value is 1 everything else is 0, actuation_points_0 contains the actual data.
# When sensing a key, the firmware adds both values for a key; actuation_points_0[key]+from actuation_points_0[key]

0x08081330 u8[4] firmware_version_0 # boot
0x08081338 u8[4] firmware_version_1 # bank2


I've been using this dapboot branch https://github.com/Duncaen/dapboot/tree/hhkb as second stage dfu bootloader which works well to flash changes without having to open the keyboard. My qmk branch has a `keyboards/hhkb/classic/dapboot` keyboard with the right ldscript and the right configuration to make lshift+rshift+esc reset into dapboot.


I did waste quite some time with trying to get qmk boot on the "second bank" flashing with the original firmware on bank1, but I was unable to actually get it working because the bank 1 firmware changes the clocks which for some reason makes chibios unable to initialize and without a debugger I'm not really able to see what is actually going wrong.


The firmware files basically just have a 2 crc16 at the beginning of the file, the first one is checked by the keymap tool and include the trailing 0xFF and the "compatible model" things that are easy to follow thanks to the decompiled keymap tool.
The second crc16 is just for the firmware binary and is what the keyboard checks after finishing the firmware update and then is written to the eeprom, this checksum is being checked each boot and it will not switch to bank2 if it doesn't match.


There also seems to be some hidden key combination in the original firmware, not sure if this is documented somewhere and/or actually works, holding `fn+rshift+v` should after some time send the firmware version and then some bytes from ram I don't really know what they are.
« Last Edit: Mon, 23 January 2023, 18:26:21 by Duncaen »

Offline yamamech

  • Posts: 5
Re: Hacking HHKB Professional Classic
« Reply #18 on: Fri, 17 February 2023, 12:10:51 »
I'm currently flashing the firmware by shorting BOOT0 to get into the DFU bootloader, which is a bit cumbersome.
I'm currently trying to flash your firmware to my PD-KB401, but I can't figure out how to get the board into recovery mode as there doesn't seem to be any labels for a BOOT0 pin to get it into recovery mode. Is it by any chance that I'd be right in assuming it's labelled PSW2 on the board with the USB C port on it?

EDIT:
I looked up the pinout and saw that BOOT0 is on pin 60, if this is the right pin for the bootloader, what pin should I short it with / what should I use on the other end to short it?
« Last Edit: Fri, 17 February 2023, 12:33:57 by yamamech »

Offline Duncaen

  • Posts: 3
Re: Hacking HHKB Professional Classic
« Reply #19 on: Fri, 17 February 2023, 16:26:27 »
I'm currently flashing the firmware by shorting BOOT0 to get into the DFU bootloader, which is a bit cumbersome.
I'm currently trying to flash your firmware to my PD-KB401, but I can't figure out how to get the board into recovery mode as there doesn't seem to be any labels for a BOOT0 pin to get it into recovery mode. Is it by any chance that I'd be right in assuming it's labelled PSW2 on the board with the USB C port on it?

EDIT:
I looked up the pinout and saw that BOOT0 is on pin 60, if this is the right pin for the bootloader, what pin should I short it with / what should I use on the other end to short it?

R6 and R85 as seen on this picture from hasu https://i.imgur.com/oTwQLPg.jpeg. I just used a jumper wire without soldering, I plugged the usb cable half in, positioned the jumper wire so that they press against the right side of R6 and R85 with one hand and then plugged in usb with the other hand, this takes some tries to get right the first time, if the keyboard boots into the dfu bootloader the led will be orange.

Edit: Make sure you make backups of the flash and eeprom with dfu, I would also be interested in looking at you eeprom to compare the actuation points.
« Last Edit: Fri, 17 February 2023, 16:45:57 by Duncaen »

Offline yamamech

  • Posts: 5
Re: Hacking HHKB Professional Classic
« Reply #20 on: Sat, 18 February 2023, 18:37:26 »
I'm currently flashing the firmware by shorting BOOT0 to get into the DFU bootloader, which is a bit cumbersome.
I'm currently trying to flash your firmware to my PD-KB401, but I can't figure out how to get the board into recovery mode as there doesn't seem to be any labels for a BOOT0 pin to get it into recovery mode. Is it by any chance that I'd be right in assuming it's labelled PSW2 on the board with the USB C port on it?

EDIT:
I looked up the pinout and saw that BOOT0 is on pin 60, if this is the right pin for the bootloader, what pin should I short it with / what should I use on the other end to short it?

R6 and R85 as seen on this picture from hasu https://i.imgur.com/oTwQLPg.jpeg. I just used a jumper wire without soldering, I plugged the usb cable half in, positioned the jumper wire so that they press against the right side of R6 and R85 with one hand and then plugged in usb with the other hand, this takes some tries to get right the first time, if the keyboard boots into the dfu bootloader the led will be orange.

Edit: Make sure you make backups of the flash and eeprom with dfu, I would also be interested in looking at you eeprom to compare the actuation points.

Unfortunately, in trying to get the board to use your QMK firmware, it's been flashed and now can't enter the bootloader (no orange light and won't appear with in dfu-buddy or dfu-util, and for some reason when I ran dfu-util to dump the firmware, it just dumped an empty file so my HHKB has now been rendered useless... Hopefully with it being less than 2 weeks old I can refund it from Amazon and get a new one...

Edit: Guess the jumper I was using must've mislodged itself a little bit, I managed to get it back into DFU mode but I unfortunately still have no way to restore the original firmware in lieu of QMK not working
Edit 2: I just realised in my original post I said my board was the PD-KB401, but it's actually the PD-KB401W, I don't think that'd have caused any issues but on the off chance it has I don't suppose you've got any advice do you?
Edit 3: I tried flashing this using dfu to no avail https://origin.pfultd.com/downloads/hhkb/HHKB410_FW_A429.hfb
« Last Edit: Sat, 18 February 2023, 19:15:22 by yamamech »

Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Hacking HHKB Professional Classic
« Reply #21 on: Sat, 18 February 2023, 19:41:51 »
Item return is not fair for Amazon or saler in this situ. Warranty is void when you peel its seal and open case... I know you are joking.

You can download official firmware image from PFU site.  Flashing it onto both bank1 and 2 'may' work. If not you need original bank1 image but it is not available publicly unfortunately.
(EDIT: you can get binary image from hfb file: dd bs=1 skip=4 count=65536 if=HHKB410_FW_A429.hfb > firm.bin )

You should have made backup images and retain safely before removing flash memory, anyway.


« Last Edit: Sun, 19 February 2023, 00:35:30 by hasu »

Offline yamamech

  • Posts: 5
Re: Hacking HHKB Professional Classic
« Reply #22 on: Sun, 19 February 2023, 07:51:16 »
Unfortunately after running the dd command to extract the firmware, flashing it onto the board using dfu-util -d 0483:df11 -a 0 -s 0x08000000 -D firm.bin or dfu-util -d 0483:df11 -a 0 -s 0x08000000:leave -D firm.bin did not restore functionality to the board. Unfortunately I'm at a complete loss as to what I can do to fix it as the firmware file seems to be the correct one for the board. Running dfu-util -l returns the following (now, cannot confirm what it said before I flashed anything as I didn't make a backup of the output out of stupidity.
Found DFU: [0483:df11] ver=2200, devnum=9, cfg=1, intf=0, path="4-2.2", alt=2, name="@DATA Memory /0x08080000/2*3Ke", serial="154730420000"
Found DFU: [0483:df11] ver=2200, devnum=9, cfg=1, intf=0, path="4-2.2", alt=1, name="@Option Bytes  /0x1FF80000/01*032 e", serial="154730420000"
Found DFU: [0483:df11] ver=2200, devnum=9, cfg=1, intf=0, path="4-2.2", alt=0, name="@Internal Flash  /0x08000000/1536*128g", serial="154730420000"


Interestingly though, when running dfu-util -d 0483:df11 -a 0 -s 0x08000000 -U boardfirm.bin to get the firmware running on the board, it seems to error out at 64% consistently, and then reset the board out of DFU mode with the following output.
Opening DFU capable USB device...
Device ID 0483:df11
Device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Interface #0 ...
Determining device status...
DFU state(2) = dfuIDLE, status(0) = No error condition is present
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash  "
Non-valid multiplier 'g', interpreted as type identifier instead
Limiting upload to end of memory segment, 196608 bytes
Upload  [================         ]  64%       126976 bytesdfuse_upload: libusb_control_transfer returned -9 (LIBUSB_ERROR_PIPE)


Offline hasu

  • Thread Starter
  • Posts: 3471
  • Location: Tokyo, Japan
  • @tmk
    • tmk keyboard firmware project
Re: Hacking HHKB Professional Classic
« Reply #23 on: Sun, 19 February 2023, 08:35:20 »
I think the firmware from PFU was built for Bank2(0x0801_0000) and it may not work on Bank1.

Note that you will need to use command like this to flash onto Bank2. (I didn't confirm this on mine, though.)

    $ dfu-util -a 0 -s 0x08010000 -D firm.bin

This is md5sum of firm.bin just for reference.

    $ md5sum firm.bin                                                                                                       
    ea90ed357441693940be241bb34468ae  firm.bin



And this is my outputs from dfu-util. So your DFU bootloader seems to work normally.

Code: [Select]
$ dfu-util -l
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [0483:df11] ver=2200, devnum=35, cfg=1, intf=0, path="5-1", alt=2, name="@DATA Memory /0x08080000/2*3Ke", serial="164738450000"
Found DFU: [0483:df11] ver=2200, devnum=35, cfg=1, intf=0, path="5-1", alt=1, name="@Option Bytes  /0x1FF80000/01*032 e", serial="164738450000"
Found DFU: [0483:df11] ver=2200, devnum=35, cfg=1, intf=0, path="5-1", alt=0, name="@Internal Flash  /0x08000000/1536*128g", serial="164738450000"



$ dfu-util -a 0 -s 0x08000000 -U hhkb_flash.bin
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Opening DFU capable USB device...
ID 0483:df11
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash  "
dfu-util: Non-valid multiplier 'g', interpreted as type identifier instead
Limiting upload to end of memory segment, 196608 bytes
Upload  [================         ]  64%       126976 bytesdfu-util: dfuse_upload: libusb_control_msg returned -4

$ ls -l hhkb_flash.bin
-rw-rw-r-- 1 noname noname 131072 Feb 19 23:00 hhkb_flash.bin

Offline yamamech

  • Posts: 5
Re: Hacking HHKB Professional Classic
« Reply #24 on: Sun, 19 February 2023, 08:51:10 »
Flashing it to bank2 worked and restored functionality to the board! Thank you so much for the help. I'm gonna continue to try to get QMK working however I've made sure to make backups of all three of the DFU's that list finds.

Offline yamamech

  • Posts: 5
Re: Hacking HHKB Professional Classic
« Reply #25 on: Sun, 19 February 2023, 12:43:39 »
Following in the steps of Duncaen, I'm typing this on what could possibly be the second HHKB running QMK! I'm running dapboot as my bootloader provided by Duncaen, and am running a QMK firmware with some userspace code from QMK.

Offline joric

  • Posts: 136
Re: Hacking HHKB Professional Classic
« Reply #26 on: Sun, 07 January 2024, 10:05:30 »
Someone did HHKB classic conversion apparently. Looks like they never managed to solder Bt module to the existing spot so it's just the entirely new controller board https://item.taobao.com/item.htm?spm=a21n57.1.0.0.578f523csL2FmJ&id=715088039960&ns=1&abbucket=9#detail

305407-0