Repository navigation
Releases: hwisu/DCP-T420W
Release list
v1.3.4 — scan dimensions, cancellation and complete raster jobs
Scanned PDFs now retain their physical page dimensions, interrupted native scans release their jobs, and truncated raster headers fail the print job instead of silently dropping later pages.
- Size image-generated PDFs from the reported platen dimensions in both scanner clients. Preserve physical dimensions through cropping, rotation, grayscale, and lineart conversion, independently of the DPI request that this firmware ignores.
- Handle Ctrl+C and SIGTERM in the native scanner, cancel the pending transfer, and attempt job deletion before exiting with status 130 or 143.
- Distinguish clean end-of-file from incomplete or invalid page headers in CUPS, compressed CUPS, PWG, and AirPrint URF streams. Keep buffered streaming and libcups pixel conversion.
- Include the previously unreleased scanner capability validation, distinct multi-page output names, and macOS SDK/build improvements.
Validation: all 29 offline tests passed, including macOS PDF/CUPS/PWG/URF pipelines, all advertised paper sizes, PDF dimensions, interrupted scan cleanup, and malformed input. All 12 raster tests also passed with AddressSanitizer and UndefinedBehaviorSanitizer; Clang static analysis, PPD validation, and shell syntax checks passed. Extracted installer binaries match the tested files byte-for-byte and contain arm64 and x86_64 slices targeting macOS 11.
The installer remains unsigned. No system installation, physical printing/scanning, or macOS 11 runtime test was performed for this release.
Install from Terminal:
sudo installer -pkg DCP-T420W-1.3.4.pkg -target /The accompanying .sha256 file verifies the installer download.
v1.3.3 — raster limits and correct page accounting
This release validates raster data against the DCP-T420W's supported media and resolutions before converting each page, and fixes double-counted completed sheets in macOS CUPS.
- Reject unsupported resolutions, out-of-range media, oversized pixel bands, invalid image offsets, excessive row padding, conflicting PPD settings, and unexpected per-page copy multipliers.
- Preserve valid Apple PWG and AirPrint URF input, including whole-point media rounding and URF's omitted copy field. Use Brother's India Legal media keyword.
- Handle canceled input and closed output pipes cleanly. Let Apple's renderer account for PDF/image pages and count direct raster jobs in the final filter.
- Keep previous packages and diagnostic artifacts when building a new installer.
Validation: 22 offline regression tests, including every advertised media size through both CUPS and PWG rendering; 1/10/11-copy jobs; AirPrint URF; cancellation; broken pipes; malformed input; and loopback scanner tests. AddressSanitizer/UndefinedBehaviorSanitizer raster tests and Clang static analysis passed. Package contents match the tested universal arm64/x86_64 binaries, with macOS 11 as the deployment target.
No physical printing, scanning, or thermal testing was performed for this release. These fixes do not establish the cause of a printer odor or certify hardware safety. The installer remains unsigned.
v1.3.2 — toolchain refresh and AirPrint record hardening
A maintenance release: the code is restructured for the current Xcode 27 / Swift 6.4 toolchain, with one small robustness fix. Printing and scanning behave the same as in 1.3.1.
Changes:
brairprintrefuses a Bonjour TXT value longer than 255 bytes instead of silently truncating its length prefix. A very long hostname or queue name could previously produce a malformed AirPrint record.brscanis built in Swift 6 language mode. This fixes a data race in its HTTP helper, where the URLSession callback wrote to variables owned by the waiting thread.rastertobrotheris split into option loading, page layout, header construction and pixel-copy functions. The deprecated CUPS PPD API is confined to one function, so other deprecation warnings are no longer hidden build-wide.- The Python scanner client and test tools now close files and HTTP responses.
build-pkg.shbuildsbrscanthrough its Makefile instead of duplicating the compiler commands.
Validation:
- 11 offline tests passed against the binaries extracted from this installer.
- The raster filter's output and log were byte-identical to 1.3.1 across 8 option combinations, including borderless, envelope, photo media and RGB-to-grey conversion.
brscanoutput was identical to 1.3.1 in 83 mode/crop/rotate/format combinations. The AirPrint TXT record was byte-identical. - AddressSanitizer and UndefinedBehaviorSanitizer passed for the raster tests. Both C components compile with no warnings under
-Wall -Wextra -Wpedantic. - All three packaged binaries contain arm64 and x86_64 slices with a macOS 11 minimum. The Intel builds ran under Rosetta.
- No system installation or physical print/scan was performed.
The package remains unsigned. If Gatekeeper blocks opening it, install from the command line:
sudo installer -pkg DCP-T420W-1.3.2.pkg -target /SHA-256 of DCP-T420W-1.3.2.pkg:
2f31537b5b747e952587232649870dfbda953370ce4620127345cd38db64dd6f
v1.3.1 — reliable scanning and macOS compatibility
Fixes scan failures that could be reported as successful partial scans, rejects invalid input before starting a job, and aligns the C binaries with the installer's macOS 11 minimum.
Changes:
- Validate raster imaging bounds and media dimensions before converting them to integers; clamp offsets without unsigned overflow.
- Validate scanner options before discovery or scanning, and clamp large crop dimensions before converting them to pixels.
- Resolve relative and percent-encoded eSCL job URLs while retaining the scanner address used by the client.
- Report page-transfer failures and attempt to delete the scanner job on both success and failure, in the Swift and Python clients.
- Build rastertobrother and brairprint with a macOS 11 deployment target. Previous C binaries carried a macOS 26 minimum despite the installer accepting macOS 11.
- Add repeatable offline scanner, raster and PDF pipeline regression tests.
Validation:
- 11 offline tests passed against binaries extracted from the installer, including loopback eSCL success/failure cases and macOS PDF conversion for Eco, Normal, High Quality, borderless, odd-only and even-only printing.
- AddressSanitizer, UndefinedBehaviorSanitizer and float-cast-overflow checks passed for the raster tests; Clang static analysis reported no findings in either C component.
- PPD generation/validation, installer script syntax and package XML checks passed.
- All three packaged binaries contain arm64 and x86_64 slices with a macOS 11 minimum. Intel scanner and advertiser help commands also ran under Rosetta.
- No system installation or physical print/scan was performed. Runtime validation used the current Mac; macOS 11 itself was not tested.
The package remains unsigned. Install using the existing command-line route if Gatekeeper blocks opening it:
sudo installer -pkg DCP-T420W-1.3.1.pkg -target /SHA-256 of DCP-T420W-1.3.1.pkg:
80a50fb92fcc076c23d4e124a13681bf32f4335522aeebc1e44b6ee6cfdb8126
v1.3.0 — clearer print options and reliable upgrades
This release makes the macOS print controls easier to find and ensures existing printer queues receive the updated option model.
- Rename print-quality labels to Eco, Normal, and High Quality (에코, 표준, 고화질)
- Keep Color and Grayscale (컬러, 흑백) exposed through Printer Features
- Document Preview’s built-in All/Odd/Even sheet selection and where each control lives
- Refresh the private CUPS queue PPD when upgrading an existing installation
- Fix the PWG test decoder so it counts repeated raster rows and multi-page streams correctly
Verified locally: Eco/Grayscale emits 300 dpi sgray_8; High Quality/Color emits 600 dpi srgb_8; a 3-page PDF produces 2 pages for odd-only and 1 page for even-only. The package contains universal arm64 and x86_64 binaries.
The installer is unsigned. Use right-click → Open, or install it from Terminal as documented in the README.
SHA-256: 18d5454c4abbf3c31ff22d4e4780f85d6b319e2c47e10aef10bbebbd9831f6f8
v1.2.1 — safer raster and AirPrint input handling
Maintenance release that hardens the C print components.
- Validate incoming raster color format, dimensions, and line sizes before processing
- Reject truncated raster lines instead of consuming partial data
- Guard raster size calculations against integer overflow
- Validate AirPrint
--portvalues and use the selected port for CUPS readiness checks - Handle DNS-SD socket acquisition failures
- Remove the unused math header
The installer is unsigned. Use right-click → Open, or install it from Terminal as documented in the README.
SHA-256: e1d410547e9c4e1846dac4db7a663d3d3426acd957fdfe7f9b5f15fdaa3a2310
v1.2.0 — print from an iPhone
Adds the missing piece for printing from an iPhone or iPad, as an optional, off-by-default part of the installer.
Why it was needed
Turning on macOS printer sharing is not enough. cupsd registers a shared queue as plain _ipp._tcp with no URF key in its TXT record, while AirPrint clients browse the _universal subtype and ignore anything without URF. The result is an iPhone reporting "No AirPrint Printers Found" right next to a perfectly working shared printer. Declaring *cupsUrfSupported in the PPD does not fix it either — the queue's own PPD copy carries the attribute and the TXT record still comes out bare. Both findings are written up in PITFALLS.md §1.16 and §1.17.
What is new
brairprint— a small daemon that publishes a second Bonjour record for the same queue, carrying the subtype and TXT keys AirPrint wants. It proxies nothing: it registers a name and then sleeps. Jobs land in the ordinary CUPS queue and take the ordinary filter chain.- An
image/urfedge in the PPD, for when iOS sends Apple Raster rather than PDF. No new filter code was needed —cupsRasterOpen()detects theUNIRASTsync word, sorastertobrotherreads both formats through the same calls. - A tick box in the installer, off by default.
Verified end to end: printed from an iPhone.
Please read before ticking the sharing box
It opens your printer to everyone on your local network, with no password — that is how macOS printer sharing works. On a home network the worst case is wasted paper, but the setting follows the machine onto every network it later joins, so leave it off on a laptop that visits cafe, hotel or shared office Wi-Fi. Nothing is exposed to the internet unless your router forwards port 631, and the Mac has to stay awake for phones to print.
Reversible at any time:
sudo launchctl bootout system/com.hwisu.dcp-t420w.airprint
sudo cupsctl --no-share-printersInstall
The package is unsigned, so right-click → Open, or:
sudo installer -pkg DCP-T420W-1.2.0.pkg -target /Sharing is off unless you tick it; installing from the command line skips the tick box, and README.md has the -applyChoiceChangesXML recipe for enabling it non-interactively.
v1.1.1 — readable installer panes in dark mode
A cosmetic fix to the installer. The driver itself is unchanged — the
payload is byte-identical to v1.1.0, so there is no need to reinstall unless
you want the readable installer panes.
What was wrong
The installer's welcome and summary screens gave code blocks a light
background but never set a text colour. In light mode that looked fine. In
dark mode macOS overrides the body text colour to white and leaves the
background alone, so every command rendered as white text on a near-white
block — invisible, while the prose around it read normally.
The fix
Inheriting, rather than hard-coding a second colour:
:root { color-scheme: light dark; }
code, pre {
background: rgba(127, 127, 127, 0.18); /* neutral, works on either */
color: inherit; /* always the visible colour */
}A translucent grey reads on both backgrounds, and color: inherit means the
code can never contrast worse than the body text around it.
Verified by rendering both panes with qlmanage, which uses WebKit like the
installer does, against a simulated light host and a simulated dark host. The
old CSS reproduces the bug under the same harness, which is what makes the
test worth trusting.
Documented
PITFALLS.md gains
3.5, with the rule this generalises to — any element you give a background
must also be given a colour — and the recipe for checking installer panes
without building a package at all:
qlmanage -t -s 900 -o . conclusion.html # writes conclusion.html.pngInstall
Download DCP-T420W-1.1.1.pkg below. It is unsigned, so right-click → Open,
or:
sudo installer -pkg DCP-T420W-1.1.1.pkg -target /v1.1.0 — installer package, and a dependency-free scanner client
A double-clickable installer, and a scanner client with no runtime dependencies
at all.
Install
Download DCP-T420W-1.1.0.pkg below and open it. It installs the print
filter, the PPD and brscan, then finds your printer over Bonjour and creates a
queue called Brother_DCP_T420W.
The package is unsigned — signing an installer requires a paid Apple
Developer ID Installer certificate. Gatekeeper will refuse a plain
double-click, so either right-click the.pkg→ Open, or run:sudo installer -pkg DCP-T420W-1.1.0.pkg -target /
Everything inside is a universal binary (arm64 + x86_64). No Python, no SANE,
no ICA plugin, no background agents.
What changed
A real installer
packaging/build-pkg.sh produces the .pkg: pkgbuild for the payload,
productbuild for the UI, and a postinstall script that creates the print
queue. The postinstall is deliberately tolerant — if the printer is switched
off, the driver still installs and tells you to add it by hand, rather than
failing the whole installation.
The scanner client is now Swift
eSCL is only HTTP and XML, so the first version was Python driving sips. On
macOS, Swift wins because everything the tool needs is already in the OS:
Bonjour for discovery, URLSession for transport, and ImageIO/CoreGraphics for
crop, rotate, greyscale, thresholding and PDF output.
Same scan, same options:
| Python + sips | Swift + CoreGraphics | |
|---|---|---|
| wall clock | 24.7 s | 12.0 s |
| lineart PDF | 276 KB | 77 KB |
| dependencies | python3, sips |
none |
macOS does ship /usr/bin/python3 (3.9.6, and brscan.py still runs on it),
but on a Mac without Command Line Tools it is a stub that prompts to install
them — not something an installer should depend on.
scanner/brscan.py remains as the portable implementation; eSCL is not
macOS-specific and it is useful on Linux.
Documentation
The README now explains why each language is used where it is — C for the
filter because the CUPS raster API is a C library and one A4 page at 600 dpi is
a 104 MB raster to walk; Swift for the scanner; Python and shell for build
tooling that never ships. Rust is discussed as the credible alternative for the
filter.
PITFALLS.md gains
Part 3, on packaging:
lsbomshows a._twin for every file in the package. They are AppleDouble
encodings ofcom.apple.provenance, an xattr macOS will not let you remove,
and they are not installed as files —installermerges them back into
extended attributes. Verified withpkgutil --expand-full. Do not spend an
afternoon on it, as this project nearly did.- An "Apple Development" certificate cannot sign an installer package.
- A postinstall that exits non-zero fails the whole install even though the
payload is already on disk.
Also in this release
brother-dcp-t420w-1.1.0-source.tar.gz if you would rather build from source:
sudo ./install.sh # printing
sudo make -C scanner install # brscanv1.0.0 — printing and scanning for the Brother DCP-T420W
Printing and scanning for the Brother DCP-T420W on modern macOS, with no
Brother software, no SANE, and no ICA plugin. Built and verified on macOS 26.5
(Apple Silicon) against real hardware.
Why this exists
The DCP-T420W is Mopria 2.0 certified but not an AirPrint device. It
advertises image/pwg-raster and answers Bonjour, but it has no
urf-supported attribute — and URF is what macOS looks for before it will
drive a printer as AirPrint. So the printer shows up in Add Printer and macOS
has no model to attach to it. Its native language, HBP, is undocumented.
PWG Raster is the way in: fully specified, and the printer already speaks it.
Printing
rastertobrother— a CUPS raster → PWG Raster filter. It labels pages
with the IPP keywords the printer actually publishes (iso_a4_210x297mm,
stationery) instead of the PPD choice names macOS's one-step path emits
(A4.Borderless,Stationery), and pads a rendered band out to full bleed
if it ever arrives inset. Universal binary, arm64 + x86_64.- A generated PPD — every media size, margin and quality mode is derived
from the printer's own IPP attributes rather than hand-typed. 24 page sizes
including borderless photo variants, 4 media types, draft/normal/best, colour
and greyscale, ink levels over IPP. install.sh/uninstall.sh— installs the filter and PPD, discovers
the printer over Bonjour, creates the queue.
Scanning
brscan— a standalone eSCL (AirScan / Mopria Scan) client. No install,
no root, no dependencies beyond what macOS ships.
brscan # full platen, colour, PDF
brscan --mode lineart --rotate 180 --out doc.pdf
brscan --crop a6 --mode gray --out photo.jpg
brscan --raw # exactly what the scanner sentThe scanner ignores every setting you send it
Worth stating up front, because it shapes the whole tool. The DCP-T420W
accepts an eSCL scan job and then disregards the request body. It returns
201 Created even for a body of this is not xml at all, and always scans the
same way: full platen, colour, JPEG, fixed size.
| Requested | Received |
|---|---|
Grayscale8 |
3-channel colour |
application/pdf |
JPEG, Content-Type: image/jpeg |
ScanRegion A6 with MustHonor="true" |
full platen |
| 100 / 300 / 600 dpi | same fixed 1680 × 2195 every time |
Element order, MustHonor, eSCL version and Content-Type make no difference.
So brscan sends a correct request anyway (harmless, and sibling models may
honour it) and applies mode, crop, rotation and format locally with sips.
Install
Download and unpack the tarball below, then:
sudo ./install.sh # printing
sudo install -m 0755 scanner/brscan /usr/local/bin/brscan # scanningThe tarball ships the filter prebuilt, so Xcode is not required. To build from
source instead: make -C filter.
Read this if something looks wrong
PITFALLS.md
documents the firmware and CUPS behaviour this driver works around, each item
marked with whether it was verified on hardware or inferred. Highlights:
*cupsFilter2lines are edges intoprinter/<queue>, not a pipeline —
declaring a second one silently bypasses your filter.cgpdftorasterignores*ImageableAreaand renders full-bleed, so stock
rastertopwgaborts with "Bad bottom/left/top margin".cupsRasterWriteHeader2()normalisescupsInteger[]in PWG mode, so
ImageBox*andPrintQualitycannot be set through it.- Scanner pixels are not square (~198 dpi across, ~188 down).
- Envelopes take a 12 mm top/bottom margin, cut sheet 3 mm.
Verified, not assumed
The filter's output was decoded back to an image before any ink was used —
A4/600 dpi gives 4961 × 7016 srgb_8 with every row well-formed; draft
greyscale gives 2480 × 3508 sgray_8; forced monochrome converts with correct
Rec. 601 luma. The stream was then printed over IPP
(job-completed-successfully) and the printed sheet scanned back in to confirm
colour, greys, fine lines and text survived the round trip.