Why? The Brother provided Linux drivers have parts that are compiled for i386 and have no source code. Although there is an open source Brother Printer driver, it is not optimized for cheap printers with their small cache. It fails part way into a print on large images or busy pages.
So, how do we port the closed-source driver to another architecture? There are several methods:
- Run i386 code on ARM through an emulator. It works, but testing on RPi 4, the emulation layer overhead made printing terribly slow.
- Reverse engineer, recreate and recompile the code for ARM. This has only been done for rawtobr3 as far as I know. There is also an original source available for
brcupsconfig4
, but other necessary part are missing. - Scavange and collect Brother's own ARM code into the full ARM install package. This is the approach taken here.
Run the oh_brother.zsh
script with the model of the printer that you have, like this ./oh_brother.zsh HL-4570CDW
If this script fails, you need to do the steps manually. Read below:
Many Brother printers are designed for LPR and lack support for common page description languages (PDF, PCL, etc). They require a CUPS wrapper to translate the print options to their native protocol.
There are at least four Brother provided pre-compiled x86 32-bit binaries. Specifically:
/usr/local/Brother/Printer/HL2270DW/cupswrapper/brcupsconfig4
- wrapper that calls onbrprintconflsr3
to set up/usr/share/Brother/inf
on every print to pass the current options./usr/local/Brother/Printer/HL2270DW/lpd/rawtobr3
- converter for the job to a raster format. Seems to be model-agnostic. Called by/opt/brother/Printers/BrGenPrintML2/lpd/lpdfilter
/usr/local/Brother/Printer/HL2270DW/inf/brprintconflsr3
- translates job options to Brother format. Seems to be backward compatible. Called by/opt/brother/Printers/BrGenPrintML2/cupswrapper/lpdwrapper
frombrgenprintml2pdrv-4.0.0-1.i386.deb
which is itself in theopt/brother/Printers/BrGenPrintML2/cupswrapper/brother-BrGenPrintML2-cups-en.ppd
/usr/local/Brother/Printer/HL2270DW/inf/braddprinter
- adds alphanumeric printer model name to/usr/share/Brother/inf/brPrintList
upon installation. This can be safely ignored.
Below is an example of how to create ARM packages for Brother HL2270DW, but it should work for other printers, both on ARM64 and ARM32 RPis. Substitute the proper packages for your printer. To find these packages:
- Head out to the Brother website and grab the native i386 Linux deb pacakges. Or
- Use
tools/web_brother.sh
from a Brother copyist orcurl http://www.brother.com/pub/bsc/linux/infs/<uppercasedmodelhere>
and then grab these packages from http://www.brother.com/pub/bsc/linux/packages/. Or - Run the linux-brprinter-installer with
set -e
injected to see all the URLs that its probing before it confirming the installation.
Oh, yeah and next time just buy a printer that has Driverless printing or IPP Everywhere
Note: if you just want to install the precompiled packages grab them from this repo and run
sudo apt install psutils cups; sudo dpkg -i hl2270dwlpr-2.1.0-1.armhf.deb cupswrapperHL2270DW-2.0.4-2.armhf.deb
. Steps below show how to re-create them.
We'll be grabbing 2 native arm32 executables and compile one other. All the steps can be done on RPi or on x86 Doing it on x86 will require cross-compilation of brcupsconfig
for armhf.
Get the original i386 LPR driver, unpack the files and the control information
wget https://download.brother.com/welcome/dlf005893/hl2270dwlpr-2.1.0-1.i386.deb
dpkg -x hl2270dwlpr-2.1.0-1.i386.deb hl2270dwlpr-2.1.0-1.armhf.extracted
dpkg-deb -e hl2270dwlpr-2.1.0-1.i386.deb hl2270dwlpr-2.1.0-1.armhf.extracted/DEBIAN
sed -i 's/Architecture: i386/Architecture: armhf/' hl2270dwlpr-2.1.0-1.armhf.extracted/DEBIAN/control
echo true > hl2270dwlpr-2.1.0-1.armhf.extracted/usr/local/Brother/Printer/HL2270DW/inf/braddprinter
Grab the Brother ARM drivers from a generic armhf archive they provide and copy the ARM code into the unpacked folders. Note that HL2270 does not use brprintconflsr3
.
wget http://download.brother.com/welcome/dlf103361/brgenprintml2pdrv-4.0.0-1.armhf.deb
dpkg -x brgenprintml2pdrv-4.0.0-1.armhf.deb brgenprintml2pdrv-4.0.0-1.armhf.extracted
# cp brgenprintml2pdrv-4.0.0-1.armhf.extracted/opt/brother/Printers/BrGenPrintML2/lpd/armv7l/brprintconflsr3 hl2270dwlpr-2.1.0-1.armhf.extracted/usr/local/Brother/Printer/HL2270DW/lpd
cp brgenprintml2pdrv-4.0.0-1.armhf.extracted/opt/brother/Printers/BrGenPrintML2/lpd/armv7l/rawtobr3 hl2270dwlpr-2.1.0-1.armhf.extracted/usr/local/Brother/Printer/HL2270DW/lpd
Now repackage it
cd hl2270dwlpr-2.1.0-1.armhf.extracted
find . -type f ! -regex '.*.hg.*' ! -regex '.*?debian-binary.*' ! -regex '.*?DEBIAN.*' -printf '%P ' | xargs md5sum > DEBIAN/md5sums
cd ..
chmod 755 hl2270dwlpr-2.1.0-1.armhf.extracted/DEBIAN/p* hl2270dwlpr-2.1.0-1.armhf.extracted/usr/local/Brother/Printer/HL2270DW/inf/* hl2270dwlpr-2.1.0-1.armhf.extracted/usr/local/Brother/Printer/HL2270DW/lpd/*
dpkg-deb -b hl2270dwlpr-2.1.0-1.armhf.extracted hl2270dwlpr-2.1.0-1.armhf.deb
Grab and extract the brcupsconfig4
sources
wget https://download.brother.com/welcome/dlf006733/brhl2270dwcups_src-2.0.4-2.tar.gz
tar zxvf brhl2270dwcups_src-2.0.4-2.tar.gz
cd brhl2270dwcups_src-2.0.4-2
Compile brcupsconfig4
gcc brcupsconfig3/brcupsconfig.c -o brcupsconfig4
If you are running these steps on the arm64 platform do cross complilation by first getting arm-linux-gnueabihf-gcc-9
via sudo apt install gcc-9-arm-linux-gnueabihf
and then running arm-linux-gnueabihf-gcc-9 brcupsconfig3/brcupsconfig.c -o brcupsconfig4
Grab the original i386 CUPS wrapper and unpack it
wget https://download.brother.com/welcome/dlf005895/cupswrapperHL2270DW-2.0.4-2.i386.deb
dpkg -x cupswrapperHL2270DW-2.0.4-2.i386.deb cupswrapperHL2270DW-2.0.4-2.armhf.extracted
dpkg-deb -e cupswrapperHL2270DW-2.0.4-2.i386.deb cupswrapperHL2270DW-2.0.4-2.armhf.extracted/DEBIAN
sed -i 's/Architecture: i386/Architecture: armhf/' cupswrapperHL2270DW-2.0.4-2.armhf.extracted/DEBIAN/control
Copy the compiled code into the unpacked folder
cp brhl2270dwcups_src-2.0.4-2/brcupsconfig4 cupswrapperHL2270DW-2.0.4-2.armhf.extracted/usr/local/Brother/Printer/HL2270DW/cupswrapper
Repack it
cd cupswrapperHL2270DW-2.0.4-2.armhf.extracted
find . -type f ! -regex '.*.hg.*' ! -regex '.*?debian-binary.*' ! -regex '.*?DEBIAN.*' -printf '%P ' | xargs md5sum > DEBIAN/md5sums
cd ..
chmod 755 cupswrapperHL2270DW-2.0.4-2.armhf.extracted/DEBIAN/p* cupswrapperHL2270DW-2.0.4-2.armhf.extracted/usr/local/Brother/Printer/HL2270DW/cupswrapper/*
dpkg-deb -b cupswrapperHL2270DW-2.0.4-2.armhf.extracted cupswrapperHL2270DW-2.0.4-2.armhf.deb
Note: if you are using RPi4 64 bit OS (
AARCH64
akaARM64
) you need to installlibc6:armhf
. No need to do it onARM32
akaAARCH32
akaarmhf
akaarmv7l
sudo dpkg --add-architecture armhf
sudo apt update
sudo apt install libc6:armhf
Install prereqs and install the drivers
sudo apt install psutils cups
sudo dpkg -i hl2270dwlpr-2.1.0-1.armhf.deb cupswrapperHL2270DW-2.0.4-2.armhf.deb
You may need to install other runtime dependencies such as a2ps, glibc-32bit, ghostscript
In case you're missing the printer defeniton you can extract it from the cupswrapper for from a Windows driver distribution using the official brother method
Top extract extract the filter and the PPD file directly from the cupswrapper run this:
sed -e '0,/cat <<!ENDOFWFILTER! >/d' -e '/^!ENDOFWFILTER!/,$d' './cupswrapperHL2270DW-2.0.4' -e 's|\\||g' > ./brlpdwrapperHL2270DW
sed -e '0,/cat <<ENDOFPPDFILE >/d' -e '/^ENDOFPPDFILE/,$d' './cupswrapperHL2270DW-2.0.4' > ./HL2270DW.ppd
Either use the driver installer, which is just a bash script that downloads the debs, or download the debs manually and install
curl -o - https://download.brother.com/welcome/dlf006893/linux-brprinter-installer-2.2.2-1.gz | gunzip > linux-brprinter-installer-2.2.2-1
echo -e "HL2270-DW\ny\nn" | sudo bash linux-brprinter-installer-2.2.2-1
(HL2270-DW as "model name", then y to continue, "no" for "Will you specify the DeviceURI?" choose "No" for USB connection or "Yes" for network connection.
or manually download debs and configure them.