Skip to content

Add 53xc family driver (confirmed working for USB PID 0x533c) - #76

Closed
daemonhorn wants to merge 1 commit into
goodix-fp-linux-dev:masterfrom
daemonhorn:add-53xc-533c-support
Closed

Add 53xc family driver (confirmed working for USB PID 0x533c)#76
daemonhorn wants to merge 1 commit into
goodix-fp-linux-dev:masterfrom
daemonhorn:add-53xc-533c-support

Conversation

@daemonhorn

Copy link
Copy Markdown

Summary

Adds driver_53xc.py + run_533c.py for the Goodix "53xc" GTLS sensor
family (USB PIDs 0x530c/0x533c/0x538c), reverse-engineered from the
closed libfprint-tod-goodix-53xc blob shipped for Ubuntu/Canonical OEM
images, cross-checked against a live USB capture of that blob's own
traffic against real hardware.

Confirmed working end-to-end against real 0x533c hardware:
nop → reset → PSK check → TLS-PSK handshake → upload_config_mcu → mcu_switch_to_fdt_mode → write_sensor_register → mcu_get_image, decoding
to a real, non-degenerate 108x88 image (no finger present -- this is the
sensor's calibration/"clear" read, same as the 53xd driver's clear-0.pgm
step).

References/reopens #31 ("Device 27c6:538c compatibility?", closed
wontfix) -- 0x538c and 0x530c share the same firmware/command set in
the same .so per static analysis (five other named DEVICE_CONFIG
templates exist alongside the "MilanFn" one used here), but their PSK/
config constants weren't extracted or tested against real hardware, so
this PR only claims support for 0x533c.

What's new vs. the existing model drivers

This chip reuses the repo's existing wire protocol (goodix.py) as-is --
only the model-specific constants are new, plus one real protocol quirk:
reset, mcu_switch_to_fdt_mode, write_sensor_register, and
mcu_get_image's ACK do not arrive in the fixed [ack][data] order every
other model in this repo assumes -- this firmware was observed sending
both orders and sometimes duplicate packets. driver_53xc.py adds small
tolerant_* wrapper functions that classify each USB read by its decoded
command rather than assumed position, used only for those four commands;
everything else (nop, preset_psk_read, read_sensor_register,
read_otp, upload_config_mcu, ...) goes through the existing
goodix.Device methods unmodified. goodix.py itself is untouched.

Also notable (documented as comments in the driver, not exercised by
default):

  • This unit's PSK was already correctly provisioned to all-zero from the
    factory (confirmed via a live vendor-driver capture that never calls
    COMMAND_PRESET_PSK_WRITE_R) -- so PSK writing isn't implemented here.
    If it's needed for another unit: this chip's COMMAND_PRESET_PSK_WRITE_R
    success convention is inverted relative to every other model in this
    repo (message[0] == 0x01 means success, not 0x00).
  • SENSOR_WIDTH/SENSOR_HEIGHT (108x88) were not found as a firmware
    constant via static analysis. They're strongly corroborated from the
    live capture instead -- reshaping the decoded pixel data at each of 12
    plausible width/height factorizations, only width=108 produces a
    coherent 2D shape (a rounded vignette matching a capacitive sensor's
    physical active area); every other candidate is pure banding with no 2D
    structure. This also exactly matches driver_53x5.py's own
    SENSOR_WIDTH/SENSOR_HEIGHT, suggesting this sensor family may share
    that physical die. Flagged in-code as "likely, not certain."

Full write-up, static analysis, and the TLS/openssl debugging history
(including why openssl s_server needs -ign_eof here) is at
https://github.com/daemonhorn/goodix-533c-re -- happy to fold any of that
into this repo's own documentation if maintainers would find it useful
rather than just linking out.

Test plan

  • Ran run_533c.py against real 27c6:533c hardware; completes
    without exceptions and writes clear-0.pgm.
  • Verified the decoded image is non-degenerate (structured 2D shape,
    not blank/noise) across multiple repeated runs.
  • Not tested: PSK writing, 0x530c/0x538c, finger-present capture
    (only the no-touch calibration read was exercised).

Reverse-engineered from the closed libfprint-tod blob shipped for
Ubuntu/Canonical OEM images (libfprint-2-tod1-goodix, "53xc" TOD
module), plus a live USB capture of that blob's own traffic against
real 0x533c hardware. Reuses this repo's existing wire protocol
(goodix.py) entirely -- only the model-specific constants (PSK,
DEVICE_CONFIG, sensor dimensions) and three protocol-quirk workarounds
are new.

This chip doesn't reply with a fixed [ack][data] pair for reset,
mcu_switch_to_fdt_mode, write_sensor_register, or mcu_get_image's ack
-- responses were observed in both orders and sometimes duplicated.
tolerant_* helpers classify each read by decoded command instead of
assuming position, used only for those commands; everything else goes
through the existing Device methods unmodified.

Confirmed against real hardware for PID 0x533c only (produces a real,
non-degenerate 108x88 image via run_533c.py). 0x530c/0x538c share the
same firmware/command set per the same .so but weren't tested -- the
five other named DEVICE_CONFIG templates found alongside "MilanFn" in
that binary are documented but unused here.

PSK writing is intentionally not implemented: this unit's PSK was
already correctly provisioned from the factory, and its
COMMAND_PRESET_PSK_WRITE_R success convention was found to be inverted
relative to every other model in this repo (documented in the driver
as a note for anyone implementing it later).

Full methodology and static-analysis findings:
https://github.com/daemonhorn/goodix-533c-re

Closes/references goodix-fp-linux-dev#31.
daemonhorn added a commit to daemonhorn/goodix-533c-re that referenced this pull request Aug 22, 2026
Submodule now tracks daemonhorn/goodix-fp-dump's add-53xc-533c-support
branch, carrying driver_53xc.py + run_533c.py -- a cleaned-up,
consolidated version of this session's capture_full_milanfn.py, built
to mirror the existing driver_53xd.py/driver_53x5.py conventions.
Verified against real hardware again after the rewrite (fixed one
regression: firmware_version()/check_psk() must not be called before
this chip's first reset, same ordering-quirk root cause discovered
earlier for other commands).

Opened goodix-fp-linux-dev/goodix-fp-dump#76
and commented on issue #31 with a pointer to it. Updated README/NOTES
to reflect the finished result instead of the original open-questions
framing.
@daemonhorn

Copy link
Copy Markdown
Author

Closing this in favor of the existing, more complete work already open for this device: #75 (stacked on #72 and #73).

I found this driver independently before searching PRs and only discovered the overlap after opening this one. #75 does everything this PR does and more -- it derives TLS session keys and decrypts application data in-process (no dependency on how openssl s_server frames its stdout, which cost me a fair amount of debugging time in my own repo), captures DEVICE_CONFIG live from vendor traffic rather than patching a static template, self-calibrates the FDT threshold instead of hardcoding it, and gets an actual finger-present capture with visible ridge detail -- mine only ever produced the no-finger calibration frame. #72's library-level ACK-tolerance fix is also a cleaner solution than the local per-driver workaround I used.

Sorry for the noise -- didn't mean to duplicate effort. I've left a comment on #75 with a couple of findings from my own static analysis + live-capture work that might still be useful there (independent confirmation of PSK/sensor-size on a second physical unit, and a PSK-write ACK-convention quirk). Full writeup at https://github.com/daemonhorn/goodix-533c-re if useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant