HACKER Q&A
📣 pushedx

How do I write a Linux driver for my 15 year old photo printer?


I'm interested in writing a x86_64 Linux driver for my 15 year old photo printer.

It looks like someone out there maintains 32 bit drivers for this printer, but I'd like low-hassle native support for my 64-bit install.

https://askubuntu.com/questions/1324015/how-to-install-print...

Where do I get started with this? What's the toolchain for sniffing USB data and that sort of thing?


  👤 fuckstick Accepted Answer ✓
This is an extremely poor venue for this type of question - the answers are all over the place and mostly unhelpful (printer drivers in Linux almost never involve a custom kernel driver). You might have better luck on Arch Linux forums of all places.

What you’re asking for probably won’t be low hassle compared to just running the 32 bit usermode “driver” - which should run fine on a 64 bit system with some packaging help.

Ask yourself, are you trying to use the damn printer or you want a possibly educational rabbit hole to go down. Even if you sniff the USB (you can simply use pcap/wireshark) what are you expecting to see? It will likely be Canons proprietary raster and control format. Reversing that from the bus alone will be an enormous amount of work. I’ve written proprietary “WinPrinter” printer drivers with the spec in hand and it’s still not trivial.


👤 yyyk
Modern printers usually work one of two ways: You can feed them directly a typical printer language (PostScript, PCL or PDF), or you work with CUPS PPD files. Both are userspace.

It would be easiest to see if there's a PPD for closely related printer* - most manufacturers reuse components and/or evolve them incrementally - and start modifying stuff from there. There's a decent chance it would already work for basic functionality, and that you'll be able to improve it by trial and error. If you are lucky, you may be able to get a decent driver without even needing to bother with USB sniffing.

* e.g. A similar Canon printer by model name.


👤 btdmaster
AUR package: https://aur.archlinux.org/packages/cnijfilter-ip1800series (Arch uses PKGBUILDs, which are roughly bash shell scripts: https://wiki.archlinux.org/title/PKGBUILD)

If you read https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=cnijf..., you should be able to compile the 32-bit driver yourself and try and port stuff from there, but note that only parts of the driver are GPL2 and some are proprietary, and it's not entirely obvious which is which (though, from the looks of it, the prebuilt libraries are proprietary and everything with Makefile.am and autogen.sh is GPL2)


👤 mmastrac
The printer driver appears to be 100% userspace, so you can more than likely use QEMU in userspace mode to run the driver on any system:

https://www.qemu.org/docs/master/user/main.html


👤 chpatrick
Maybe it's easier to add it to Gutenprint? http://gimp-print.sourceforge.net/

It supports Pixma ip2000, so maybe it's not a huge change.

This describes how to add a new printer: http://gimp-print.sourceforge.net/reference-html/c199.html


👤 nixcraft
RMS started open source because of printer driver issues (he wanted the source code but wasn't allowed it and thought it as a betrayal of the hacker culture). This post is like history repeating itself.

👤 antegamisou
Grab a copy of Linux Device Drivers by Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman:

https://lwn.net/Kernel/LDD3/

Don't mind the document's age, the principles have largely remained unchanged. Besides, it's probably a better fit since you're targeting a device from 2007

I understand this may be kind of non-specific to what you were expecting, but it's the most rewarding way of achieving what you want and coming up much faster with a driver for an obscure device next time.


👤 lagrange77
> What's the toolchain for sniffing USB data

You can use Wireshark for that part.

https://wiki.wireshark.org/CaptureSetup/USB


👤 rroot
Small rant, although on topic.

I once had to ditch a perfectly functioning scanner (HP), due to out-of-date drivers and no linux support. I now do my best to always buy hardware that I know is well supported on Linux.

For example, some CanoScan scanners are completely supported by Sane, see http://www.sane-project.org/lists/sane-mfgs-cvs.html


👤 brudgers
For what it's worth, fifty bucks solved my Linux photoprinter driver problem (Canon Pro100). [1]

I bought Turboprint. https://www.turboprint.info/

To me, it is the shortcut that will save endless searching for something that doesn't exist.

My free all Linux based solution was driverless printing, but it has limitations.

My non-Linux exclusive solution was an old Thinkpad running windows and SD card sneakernet. That was the simplest thing that might work so I tried it first.

Good luck.

[1] Well mostly solved it...I mean it solved all the important issues with a color managed workflow. At the scale of color managed workflows, $50 is about rounding error on X-rite gear...or even Datacolor gear. Never mind if you price your time.


👤 torstenvl
I've never written a kernel driver, but wouldn't it be easier to start with the 32-bit driver, update the kernel APIs, and move (most?) integer types to fixed-width?

👤 worthless-trash
You're all jerking up the wrong tree.

The actual source is available, http://ppa.launchpad.net/thierry-f/fork-michael-gruz/ubuntu/... http://ppa.launchpad.net/thierry-f/fork-michael-gruz/ubuntu/...

etc..

The packages are compiled for x86-64.

What am i missing, no reversing required ?


👤 lallysingh
These folks seem to have a 64-bit linux driver for it, for $49 eur: https://www.turboprint.info/

👤 triggercut
There was a really good article posted the other day here, and while focusing on windows, gives a lot of interesting tips for investigating the history of how the driver package was put together and who wrote the driver and using that to help.

https://news.ycombinator.com/item?id=32714806


👤 Comevius
https://github.com/endlessm/cnijfilter-common

You only need cnijfilter-4.10, pstocanonij and 312/libs_bin32, which are the 32-bit proprietary libraries used to communicate with your printer. Those are the ones you would want to replace.


👤 hapless
Canon devices usually support PCL and Postscript.

The proprietary drivers are just faster/fancier.


👤 lifeisstillgood
Thank you for posting this here. I have managed to get bogged down just replacing my home router with OpenWRT version (I blame lack of time) so while I cannot give you any useful tips, I can celebrate your bravery (or time management skills) and wish you all the very best.

The site is Hacker News, so we need a bit more low level hackery here, and a few less insights into ideal product management style.


👤 MisterTea
Printers are odd beasts. At first glance they appear to be a bitmap printing engine for paper (or whatever the medium) and you send it a bitmap and maybe some settings. But no, they actually have a front end computer that speaks one or more page layout languages. That language tells the printer how to render the data into bitmap which is printed.

You first have to figure out which language your printer speaks. If it speaks a common language like postscript (basis for PDF) or PCL (printer command language) then you might be able to use a generic driver or one from a similar printer. If it is proprietary you will need to reverse engineer it by installing the printer in a native environment along with tools to sniff/log the communications send some test prints with magic data and figure out the command language that way.

Given that your printer already has a 32 bit driver it stands to reason you could have a look at the 386 source and see what fails to build on an amd64 machine. Then correct that and you have a driver.


👤 iam-TJ
Lots of great advice here along the lines of "is it really worth your time and energy", but if you really want to tackle it don't focus on the hardware, focus on the existing (proprietary) software, and wrap it with your own libraries to observe and record inputs and outputs.

  lp myfile -> input-wrapper -> proprietary-library -> system-library -> printer
                          |                             |
                          ---------floss-library---------

As the existing driver is 32-bit there are two options for debugging on a x86_64 platform:

1. A 32-bit virtual-machine install with the printer connected via USB pass-through so the existing driver correctly operates the printer

2. As someone else said, use qemu-system-i386 with a 32-bit chroot minimal install

Look at the source-code of the binary package containing the driver. Identify the proprietary binary blobs (most likely shared libraries) that are included.

Use tools like objdump to identify the names of external functions they import from system libraries (which they'll call), and the functions they export for other tools to call into.

Create basic wrapper libraries with the same names as the system libraries that export the same function names and signatures as the system library.

Have those functions in your wrapper libraries call the same functions in the system libraries and pass through the arguments untouched BUT also have your wrapper functions log/dump/record the function and arguments being passed.

In the same way create wrapper libraries that have the same name as the proprietary blob libraries and export the same functions. Have these functions call into the proprietary libraries and pass arguments untouched, and log/dump/record in the same way.

Use LD_LIBRARY_PATH to have your wrapper libraries loaded and used by the tool used to print - I'd recommend using something basic like "lp".

Do basic text printing to begin with and observe what the proprietary libraries output to the printer in response.

You'll likely see control codes to configure the printer and then possibly the actual ASCII codes of the text unless the driver converts everything to bitmaps before sending. Even then, by printing one character at a time it is usually possibly to determine the data format of bitmaps and the positioning data.

Compare with existing open-source drivers for similar devices from the same manufacturer since there is likely to be a lot of overlap and shared technology/code.

Once you think you've got a handle on it have your wrapper library that pretends to be the proprietary library bypass the proprietary library and directly format and send the data to the system libraries.

As you figure out more of the data format put that into your replacement FLOSS library until the proprietary is no longer required. At that point you can build the FLOSS library for 64-bit and upstream it for everyone to enjoy.

Or just buy a replacement printer that is well supported already!


👤 m00dy
First of all, you would need a buffer :) Just joking, I would try to check out the source code and build it under 64bit arch you have. There might be some issues on the way and start to fix them could be the first step.

👤 jchw
I'd recommend doing some reconnaissance by looking at the 32 bit driver. What does the package contain? Prod at any binaries with binwalk, strings and maybe even Ghidra if you can to try to gather information.

If you don't understand the higher level bits of what's going on in the driver, it leaves room for a gap in understanding what exactly you might need to write to replace the 32 bit parts of the driver. If the driver works with cups, it'd be good to try to understand how exactly that works. (I'm being somewhat vague here since I don't personally know.)


👤 Joel_Mckay
Training on the kernel is probably necessary, and the Linux foundation course is expensive... but LFD430 is what you are seeking.

Primarily, there were many trends in the kernel module structures, and a lot of deprecated apis. If you just read the code, you are guaranteed have issues with the legacy code peppered in the module source.

Essentially, if you just need a USB workaround, than a user space program with libusb will greatly simplify your life. =)


👤 weare138
Might be easier to check out the source to the 32bit driver if it works. The USB and printing protocols should already be implemented and possibly documented in the source. Then you could poke around with the 64bit drivers for similar model printers, that same protocol is probably used in other printers. Could be able to just lift the relevant code from an existing 64bit driver.

👤 AshamedCaptain
Why don't you try one of the CUPS, GutenPrint, etc. user mailing lists?

This is not the most appropriate venue for asking this type of questions.


👤 SanjayMehta
Look at Gutenprint code for ideas. They had an open source driver for my photo printer. They might even support your printer, if getting it to work is the only objective.

👤 gigatexal
The hassle is not worth it. Just buy a new, modern AirPrint compatible printer.

👤 hasajacyszatan
You can install Windows XP with printing server in virtual machine

👤 barkingcat
Do you have technical documentation regarding this device?

👤 glouwbug
Hackernews is primarily software. Hackaday could help