Debian ARM and Brother DCP195C with CUPS

Solution 1:

Short: You have to extract the ppd file from the linux driver

long:

FIRST

  • Goto Brothers Driver website and search for DCP195: http://support.brother.com
  • Download the Linux deb Version of "CUPSwrapper printer driver (deb package)"
  • Open the deb-File with a compression tool and follow the path down to "dcp195ccupswrapper-1.1.3-1.i386/opt/brother/Printers/dcp195c/cupswrapper"
  • Extract the "brother_dcp195c_printer_en.ppd" file

SECOND

  • Open the cups web-interface via https://192.168.1.2:631/admin [replace the ip with pi's]
  • Click "Add Printer" Select "Brother DCP-195C (Brother DCP-195C)" and press "continue"
  • Edit the upcoming informations if neccessary, check "share printer" and press "continue"
  • In "Or provide a PPD-File" browse to the extracted "brother_dcp195c_printer_en.ppd" file and upload it Follow the next steps...done

After that, the printer was available, but with an error: "File "/usr/lib/cups/filter/brlpdwrapperdcp195c" not available" Because i installed the driver on my Ubuntu Laptop i could simply copy the file from my Laptop at /usr/lib/cups/filter/ to the pi

After this, my laptop could find the printer

Solution 2:

You can get the i386 driver working on the Raspberry Pi through emulation, even though it has a different instruction set. It's very slow and takes minutes until the printout arrives, but it works.

I found the hint on this forum post: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=15526&start=25#p708038

Step 1: Install the driver as instructed on the Brother documentation

You should have a directory such as /opt/brother/Printers/dcp195c/lpd with the filter binary brdcp195cfilter. This binary is called by the filterdcp195c shell script right next to it in the same directory.

I believe they offer an installation script now, but I did it without. There are instructions somewhere what needs to be preinstalled.

Step 2: Get the i386 emulation working

This is following the steps at https://wiki.debian.org/QemuUserEmulation

At the end of step 2, you should be able to run i386 binaries just like regular binaries. In ps ax, they will show

Install Qemu

Install the packages qemu, binfmt-support and qemu-user-static.

Run update-binfmts --display to see which binary formats are supported. They should be automatically enabled on Raspbian and Debian.

Install x86 support libraries

On Raspbian, add a line like this to your /etc/apt/sources.list:

## Debian i386
deb [arch=i386] http://http.debian.net/debian stable main contrib non-free

Another Debian repository will also do.

The Raspbian repository doesn't have x86 binaries, so add an [arch=armhf] line to your existing lines starting with deb. The lines starting with deb-src can be kept as-is.

Tell Raspbian that you want a multiarch system with i386 packages, and get the i386 libc. For the update step to work, you'll need to import and trust the Debian GPG keys for package management.

sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install libc6:i386

At this point, you should be able to execute the brdcp195cfilter binary which comes with the driver:

$ ./brdcp195cfilter 
ERROR: ld.so: object '/usr/lib/arm-linux-gnueabihf/libarmmem.so' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
Error: invalid option !!

If you see this output, it worked. The Error: invalid option !! line is brdcp195cfilter complaining that you should have passed arguments.

Optional: Remove the ld.so error message

Raspbian uses /etc/ld.so.preload to preload the libarmmem library into all processes. The library replaces some expensive memory routines with faster routines written in ARM assembly, but is not strictly necessary to run Raspbian.

It's safe to ignore the warning, but also safe to remove or comment out that line from /etc/ld.so.preload. The warning will show up in CUPS error logs if not disabled.

Step 3: Get this working with CUPS

You should have a CUPS installation from following the instructions from the Brother website.

Flaky USB connection

On my Raspberry, the dmesg log was alternating quickly between these lines at some point:

[58981.586842] usblp0: removed
[59222.794260] usblp 1-1.3:1.0: usblp0: USB Bidirectional printer dev 8 if 0 alt 0 proto 2 vid 0x04F9 pid 0x0222

What fixed it for me was to go to localhost:631 (the CUPS web interface) and modify the printer in the "Printers" section so that it uses the CUPS-recognized USB device rather than the usb://dev/usb/lp0 device.

Let the printer receive data at a normal speed

brdcp195cfilter is a step in the printing process which receives a huge input bitmap, and converts it to something which later gets piped to the printer device. I measured an input size of ~90MB for a simple "Hello world" message on the top of the page.

The emulation on the Raspberry is not quick enough to keep up with feeding the printer with data. The printing works, but I heard unhealthy noises from the printer motors being active while waiting for data.

To fix this, install the utility sponge from the moreutils package and edit filterdcp195c so that the output of $BRCONV $BRCONV_OP (a.k.a. brdcp195cfilter) is piped though sponge. There should be three lines within the "PostScript", "PDF" and "*" cases at the end of the file, ending in ... | $BRCONV $BRCONV_OP | sponge.

What this does is to gobble up all output from the long-running converter process and only send it to the printer all-at-once when the converter is done. That way, it takes longer until the printing starts, but the printer is receiving its data at a normal pace.

(sponge stores the data it buffers in a temporary directory, so you're not limited by the Raspberry Pi's RAM)

Solution 3:

Günther's answer was very helpful. This is partially a follow-up with my own experience and info.

I didn't see any problems with kernel modules; this was probably fixed in the last six years.

I tested this first on a Raspberry Pi 3. This prints slowly (~3 minutes per page) but I rarely use the printer, so that's acceptable.

To avoid the ld.so error message, you can remove the raspi-copies-and-fills package.

I found it necessary to install Debian's libc6:i386 and libc6:armhf, because these packages require an exact version match, and the Raspbian version contains e.g. +rpi1. Debian's armhf packages seem to work properly on Raspberry Pi 3; I believe they should work on Raspberry Pi 2 (armv7) and later, and the new Raspberry Pi Zero 2 W, but not on Raspberry Pi 1 or Zero/W (armv6). Note, anyone mixing distributions should look at man apt_preferences.

I wanted to use a Raspberry Pi Zero W as my print server. This is even slower (~5 minutes per page) and cannot use Debian's armhf packages. After a lot of reading and trial-and-error, I managed to build a Raspbian libc6:i386 "bootstrap" package from source.

Obtaining source code is easy:

apt-get source glibc
cd glibc-N.NN

It turns out that the next step is to choose build profiles.

https://wiki.debian.org/BuildProfileSpec

  • cross because we're cross-compiling
  • stage2 because we need to bootstrap glibc
  • nobiarch avoids building amd64/x32 packages
  • nocheck eliminates a build dependency

I thought it should be possible to install build-dependencies as follows:

sudo apt-get -a i386 --build-profiles=cross,stage2,nobiarch,nocheck build-dep glibc

However, that failed due to some unavailable packages, such as perl:i386. Maybe I'm doing something wrong? Seems likely, due to my very limited understanding of Debian packaging. I did this instead:

sudo apt-get build-dep glibc

Then check debian/control to see which version of gcc is required, and:

sudo apt install dpkg-cross gcc-10-i686-linux-gnu g++-10-i686-linux-gnu 

This is often equivalent to installing crossbuild-essential-i386.

We can now build.

dpkg-buildpackage --no-sign -b -a i386 --build-profiles=cross,stage2,nobiarch,nocheck -d

Notes:

  • The build process takes a very long time on a single-core armv6 Raspberry Pi. I recommend using a faster Raspberry Pi to build packages.
  • This "bootstrap" package was sufficient for my needs. I don't know whether it might have some functional limitations.
  • When I tried to install my libc6:i386 package, it conflicted with the existing changelog.Debian.gz file provided by Raspbian libc6:armhf. I renamed the existing file, and the package installed correctly.