Up until a couple of years ago, we had HP Color LaserJet CP1215, a regular USB printer. It was also supported on Linux with the foo2hp
drivers (part of the printer-driver-foo2zjs
package on Debian).
I do not remember the exact reason why we changed it. I think it was broken, each toner cost around 80€ (it had four: CYMK) and maybe some other reasons.
We switched to an HP Envy 6000, an ink-jet printer. It works, but the documents do not look sharp when printed with it, and its cartridges do not last long. So, we also bought a cheap HP Laser 107a to print in black and white.
It works fine for us, but it has a slightly annoying problem for me: officially, it is supported on Linux only with proprietary drivers. And not only are they proprietary, but they do not work at all on my system.
foo2qpdl
I do not print often: usually only for bureaucratic stuff that I do begrudgingly and with urgency. So, I decided not to fight with printers (the eternal battle of informatics 😄️). Instead, I prepare PDFs on my Linux computer, run an HTTP server with Python, and go to the other floor to print them on another computer on Windows.
However, while preparing this article, I decided to search again to be sure not to write inaccurate information. Sadly, I found the same information I had already read more than one year ago. Still, I decided to see if this could lead to new results.
A thread on the Raspberry Pi forum suggests that this printer is a Samsung M2020 rebrand and that similar models usually work with the Splix drivers.
My CUPS installation contains neither the HP nor the Samsung M2020 printers, but the various /usr/share/cups/drv/splix-*.drv
(part of printer-driver-splix
on Debian) refer to several other models, so I tried with some of them.
It seems the 107a partially understands this driver. For example, when I tried with a Samsung model at 1200×1200 DPI, I got a sheet with this content:
SPL ERROR - IllegalResolution POSITION : 0x2000 (8912) SYSTEM : emul/com_tbl LINE : 434 VERSION : v11.73_190212 ERROR CODE : 11-1113
600×600 DPI did not work: the red question on the power button turned on, or the printer started whirring and sopped immediately, or it printed another kind of error:
SPL ERROR - Please use the proper driver POSITION : 0x018b (4235) SYSTEM : emul/SPL/SPL_image LINE : 212 VERSION : v11.73_190212 ERROR CODE : 11-1113
So, I started searching for solutions for Samsung printers, and I found this page about the Samsung ML-1670, which suggests setting the CLP-310 driver based on foo2qpdl
(provided by printer-driver-foo2zjs
on Debian, like all the foo2something
).
And to my surprise, it also worked for the Laser 107a! Later I found on some very old thread that QPDL (Quick Page Description Language) is also known as SPL2. Anyway, I can now print on Linux, and share it with my other devices through the standard IPP, too!
RedMon
Before finding this solution, I decided to try to share the printer on Windows and print from Linux.
TL; DR: skip to the IPP section. This is here only for documentation purposes, to illustrate how I reached my final solution, and to include the answer to problems other users could also encounter.
Many years ago, I had a similar problem and found RedMon. It is a fake printer port that redirects the content to print to the standard input of any executable. You can manually install any PostScript printer and couple it with Ghostscript to do a lot of different stuff, such as creating a PDF printer.
GhostScript can output to Windows printers directly with the mswinpr2
output device. You can choose Program handles output
on RedMon settings and use these program arguments (change HP Laser 103 107 108
with the name of your printer):
-sDEVICE=mswinpr2 -r300 -dBATCH -dNOPAUSE -dSAFER -sPAPERSIZE=a4 -sOutputFile="%printer%HP Laser 103 107 108" -f -
I do not know whether all of them are required, or correct. I copied the rest of the arguments from the documentation of RedMon. As a matter of fact, they work, and I managed to print what I needed, at least from the computer where the printer is connected.
If I understand the documentation correctly, Ghostscript will do the rasterization and feed a bitmap to the printer. I have no idea about how this influences the final quality. According to the (unofficial) specification, the SPL2 language is inherently bitmap. My uninformed guess is that moving the burden of rasterization to the host simplifies the peripheral a lot, hence the reason for which SPL is used especially on cheap devices.
Permission problems
RedMon looks like old software, and I was surprised its site mentioned Windows 7 support. However, it also says Windows 10 support “will not be implemented”. Indeed I had some permissions problems.
I worked around them by opening the printing dialog with rundll32
from an elevated CMD. The first command opens the wizard to add a new printer, and the second one opens the properties, from which you can adjust the port settings:
rundll32 printui.dll,PrintUIEntry /il rundll32 printui.dll,PrintUIEntry /p /n "Your Printer Name"
Sharing the printer?
My final goal was printing from my Linux machine. But I never managed to do so because, starting with Windows Vista, creating SMB shares from a Windows client has become more and more difficult.
If you have more patience than me or you are using Windows server, you might manage to create a working share. However, I do not know whether it will work: RedMon mentions also “Remote printing to a printer that uses RedMon.” as something that will not be implemented.
IPP to the rescue
IPP stands for Internet Printing Protocol. It is a standard protocol, and all its details are documented in various RFCs.
Basically, all operating systems support it. But when it comes to an IPP server on Windows, you need the server edition of the operating system.
However, IPP is yet another protocol based on HTTP, which makes it somehow simpler. But you do not need to look at the specs: you can find several implementations on GitHub.
I tried ipp-server, written in Python. It is also available on PyPI, so you can easily install it with
pip install ipp-server
If you never used Python, you might want to look for a quick guide on virtual environments, instead of installing packages at user or OS level.
With that package, you can save the file you “printed”, run a command to which the content is passed as standard input, or use undocumented functionalities 😁️. So, we can just reuse the Ghostscript command I wrote above. The server listens on localhost
by default, so we need to tell it explicitly to listen on any address with the -H
option. Finally, I specified port 631 because it is the official IPP port and I was on Windows. But if you are on Linux, CUPS will probably be already using that port. If it is not, you will need to be root to run this command since 631 is a well-known port or, better, use an unprivileged port. So, the complete command I used is:
python -m ippserver -H 0.0.0.0 -p 631 run "C:\Program Files\gs\gs10.01.2\bin\gswin64c.exe" -sDEVICE=mswinpr2 -r300 -dBATCH -dNOPAUSE -dSAFER -sPAPERSIZE=a4 -sOutputFile="%printer%HP Laser 103 107 108" -f -
With that running, you can add a new printer at ipp://your-host/
to CUPS (or ipp://your-host:port-number/
if you used a non-standard port).
ipp-server forwards the content of your requests without parsing it. So, you need to choose a PostScript printer for Ghostscript; I chose Generic PostScript Printer
. A PDF printer might work, too, maybe with some different parameters, but I am not sure, and I have not tried it.
On the host running the server, you can specify any printer you have; it does not need to be my model.
So, eventually I made it, and either way I can print from my Linux machine to this HP printer 🏆️.