Ask HN: 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?
113 comments
[ 4.7 ms ] story [ 176 ms ] thread(not sure if the kernel USB API is the same, that might be a tricky part)
https://www.canon-europe.com/support/consumer_products/produ...
You can use Wireshark for that part.
https://wiki.wireshark.org/CaptureSetup/USB
The proprietary drivers are just faster/fancier.
I can't really find a definitive answer, of course, but all of the basics are from the early 90s, with some obvious followup "oh shit we need money" patents from 2000. (Obviously, 2000s era technology seems obvious today. I don't know if it was obvious in 2000. Things like "4 digit dates" were a new idea back then ;)
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.
Are 15 year old photo printers modern?
Windows 2000 had full support builtin, and CUPS has had it for about the same timeframe, making it really damn easy to print anything, from any device built since, and its all in userspace.
I guess at some point they had to ruin it by making all consumer printers use buggy wifi stacks.
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.)
https://www.qemu.org/docs/master/user/main.html
Now writing or reversing a Linux driver for the printer though can be a fun project but I personally wouldn't buy this driver just so I can use the printer.
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. =)
Speaking of RMS writings and your comment, he also wrote on free software v. open source. https://www.gnu.org/philosophy/open-source-misses-the-point....
Wouldn't go that far to call them hostile.
https://www.gnu.org/gnu/incorrect-quotation.html
Actually pretty funny! I can't believe he wrote an article about it.
> For the free software movement, however, nonfree software is a social problem, and the solution is to stop using it and move to free software.
edit: of course it's a bit Fine Gael/Fianna Fáil, but it's hard to throw a rock without hitting an OSS advocate who thinks that Free Software is communist fascism.
Yes. I remember there was a 4chan Stallman interjector written in Perl. The script would reply to anyone talking about Linux with that text. I can't seem to find that code anymore but I found newer incarnations of the concept such as this Telegram interjector.
https://github.com/perronet/interjection-bot/blob/master/sta...
While on the other hand, contemporary accounts date it to a Xerox 9700 printer at MIT in 1980.
I don't know. You could say in the 1980s the printer story sounded too absurd so they emphasized the clash of Titans aspect or you could say that we really like provincial origin stories these days so this "a simple motivated man with a great idea" framework is more appealing
This kind of stuff is fascinating; how history is narrated differently throughout time
For people uninitiated, the idea is materially, only discrete events happen. Stories are the narrative sense making humans project on them.
This is not the most appropriate venue for asking this type of questions.
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)
They are Bash scripts.
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
https://github.com/endlessm/cnijfilter-common/blob/0c5cfbf85...
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.
And who says you can't write a kernel driver for a printer? It's certainly overkill but if you're into low level programming it's a very fascinating way to dive deeper into it, as I assumed is the case going by the last sentence of the OP.
No it does not. It’s easy enough to scan the USB chapter and see that it is entirely targeting the kernel interface.
> And who says you can't write a kernel driver for a printer
Well there already is one - usblp. If you’re trying to grok the esoterica of Linux USB kernel mode interfaces - a printer class driver is not the worst exercise - but this is to me very far removed from the task at hand - driving the hardware.
> a printer class driver is not the worst exercise
Maybe that's why it's a good introductory to kernel drivers programming? Some friends back in school were tasked the exact same thing (implement usblp 'from scratch').
I do remember having a bit of trouble finding the most recent source code for the book at the time (which was 12 years ago).
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.
That said, sniffing and replaying packets might get you pretty far. You should be able to do basic things like making the windows driver eject a piece of paper, and then doing that from Linux.
I've been curious about doing something like this for a while, but don't even really know where to start when it comes to researching information on this topic. Do you have any good resources for accomplishing this?
https://www.youtube.com/watch?v=wdgULBpRoXk
https://www.youtube.com/watch?v=N0O5Uwc3C0o
And some videos on using chips and breadboards to meet protocols- https://www.youtube.com/watch?v=l7rce6IQDWs
And a digital protocol too- https://www.youtube.com/watch?v=MCi7dCBhVpQ
Understanding how the USB wire protocol works is definitely valuable knowledge in some arenas, but not at all important for the kind of reverse engineering task OP is trying to perform, as they can generally speaking trust the electrical layer is standard and only need to operate at a level above it.
Same for the "write 3 bytes to a USB device" hypothetical from upthread - electrical understanding of USB is interesting but ultimately unimportant if you're using an existing USB stack - higher level knowledge of USB endpoint types and transport mechanisms is the name of the game there.
If I were given this task and I had to produce a driver with source code (rather than just get things working), I'd start with a combination of USB sniffing and static decompilation (Ghidra/IDA) of the Canon binaries, followed by perhaps some dynamic analysis (logging shims) if things turned out very complex.
If I just had to get things working, I'd just use one of the many approaches to mix 32/64-bit userland binaries in order to shim the 32 bit Canon binaries into a 64-bit CUPS driver.
From there, being a USB HID device will be a lot easier on your host machine code. You have to speak a predefined protocol, but the OS can use its own drivers to take advantage of the functionality you offer. For example, your microcontroller code can be a keyboard or a joystick. (It's still bidirectional, so you should be able to configure the color of the on-board LED. I don't know whether or not there's a standard there so you can just use a pre-written host app across platforms.)
Finally, if you want to pick apart an actual product that does this, I just found: https://www.blinkstick.com/
...is a pretty readable book.
What we have here is an enthusiastic hacker wanting to go down the rabbit hole of writing a hardware driver. That's no easy task (like you point out), and answers like this are not helpful at all.
The answer is discouraging and seem to only sow doubt in OPs mind. Let him find out how hard it is. May I remind that this website is called "Hacker News".
Let the voting suggest the venue for the question - it hit the front page of hacker news.
Also, the suggestion to check the arch linux forums was spot on.
I think OPs answer was very helpful and polite.
is it as complicated as calculus? or running your own e-mail server? you're perpetuating the same sentiment. Let the OP figure it out on their own.
Also, this is a relatively new post so maybe relevant information will eventually bubble up. I am starting to see some interesting comments.
"Essentially" is essentially dishonest here. The top post says:
1. HN is not the best venue to get help for this.
2. The answers that you have gotten so far are mostly bad.
3. Printer drivers in Linux almost never involve a custom kernel driver.
4. The Arch Linux forums would be better for this question.
5. Running the 32 bit driver might be easier than writing a 64 bit driver.
6. You might need some packaging help to run the 32 bit driver on a 64 bit system.
7. This would probably only be a worthwhile project only if you were trying to learn, because there are easier ways to get the printer to work.
8. What's coming over the wire will probably be proprietary and obfuscated.
9. Figuring out Canon's format with wireshark output will be very difficult, even for someone with experience at writing drivers.
It also inspired a comment from jrockway that offers additional practical, experienced advice.
----
What I can't figure out is what you're offering other than your approval and disapproval of what other people are doing. There's maybe one more comment on this entire thread, recently submitted, that offers more information than the one you're criticizing.
In my humble opinion, way more complicated.
considering that you'd need to know calculus, linear algebra, and other disciplines of math to be able to build some of the image, vectoring, and rastering logic... yes.
> Let the OP figure it out on their own.
the OP is literally soliciting opinions and help
Email servers have whole scripts and instructions and tutorials on how to run them with a completeness that is surely missing from this printer. Calculus has whole libraries full of instructional books.
It’s probably similarly hard to learning bash and Linux and networking and c and writing an email server from scratch with only the SMTP spec in hand or learning all of calculus by being told simply that you can calculate the slope of a line and being handed a slide rule.
(That’s how my professor taught calculus btw. It sucked)
I think it is far worse than that. Printers are commodity products and pretty cheap for what you get new for hundred to a few hundred bucks, which is a hardware and software package that is likely to work flawlessly out of the box and for at least a few years. Labor is not cheap. There was a threshold crossed 20-25 years ago where it no longer made economic sense to repair hardware, and ever since the broken is simply replaced. Even if this printer technically works, if the 32-bit driver is unacceptable, then it classifies. The amount of effort required compared to the value of the product is staggering. Add to this that it already works, albeit with a 32-bit driver, and we're entering the territory of mental illness; perfectionism and obsession are not virtues, they are symptoms.
OP is not a hacker, but rather is attempting to Tom Sawyer a hacker into painting his fence for him. Hackers are notorious for ugly solutions and would not ever whine about using a 32-bit driver, nor do they ask for all the work to be done for them. What possible realized benefit of having a 64-bit driver for this printer is not exactly clear. It has the memory that it has, 128MB, and a driver capable of 4 billion times the address space should make absolutely no difference, because the memory is what it is.
The top reply is apt, and the GP is only encouraging heartache, disappointment and failure. If the OP wants a 64-bit driver, he'll need to find a replacement printer that comes with one. Conversely, he can earn a computer engineering degree and go to work for a few years in the device driver industry to get the experience necessary to approach and solve this tiny problem requiring massive knowledge for pretty much no benefit. I would recommend instead meditating on why it is difficult to impossible to change the nature of something and/or why you shouldn't build your castle in a swamp.[1]
[1] https://www.youtube.com/watch?v=w82CqjaDKmA&t=0m2s
"I'm interested in writing a x86_64 Linux driver for my 15 year old photo printer."
Is a very clear statement. Maybe if they had solicited, "how difficult would this be?" -- but that was not asked. Iterating how difficult the project is doesn't move the needle forward and in fact, does the opposite and is not at all helpful to the OP. Don't project your inadequacies.
Can't believe I'm defending a fuckstick rn, but here we are.
The problem is, everyone who knows a thing about "Printer drivers" shivers when they read that statement, in part because it mentions Linux or x86_64, which kind of implies some level of confusion. Also, it doesn't mention whether he's doing it for the sake of an old printer (which then makes the question the wrong thing to ask -- rather you should ask "I want to make my printer work with x86_64 Linux" -- which likely has a much simpler answer) or the sake of how to learn to write Linux printer drivers (which makes the question bizarre -- there are no Linux printer drivers per se).
> Iterating how difficult the project is doesn't move the needle forward and in fact, does the opposite and is not at all helpful to the OP. Don't project your inadequacies
This is really the wrong take here. If someone asks "I want to learn to pave roads for 4-wheel bikes" you don't answer with "OK, tarmac is made with crushed stone, tar, ...". You answer with "WTF are you doing this for?". Because it's highly likely that the questioner is having some type of confusion, rather than explicitly wanting to make such a strange request.
As Eric S. Raymond put long ago:
> Often, people who need technical help have a high-level goal in mind and get stuck on what they think is one particular path towards the goal. They come for help with the step, but don't realize that the path is wrong. It can take substantial effort to get past this.
By not addressing the user's exact question, and considering the user's final goal, you may be moving the needle much forward than if you just blindly answer it like some people have done here.
Yes it was. OP asked for a “low hassle” solution, explicitly soliciting low difficulty level.
What would your advice be if we assume that was what the author wanted? I had a lot of fun reverse engineering my laptop's keyboard LEDs and I'd love another rabbit hole to go down into...
last i played with this, i had to hack up scapy to handle the windows usb packet capture format. (windows and linux usb packet captures are/were in different formats, unfortunately)
when you're on windows you should print a bunch of images and then try and train a transformers neural network to predict the packets from the images alone.
if you got this to work, it would be cool.
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
[1] https://www.hamrick.com/
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.
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.
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.
The main problem is that the format is not documented, and there may also be a layer of compression.