mailto: blog -at- heyrick -dot- eu

Navi: Previous entry Display calendar Next entry
Switch to desktop version

FYI! Last read at 19:03 on 2024/11/21.

Printing to a Samsung SL-M2022W IPP laser printer from RISC OS

The state of printing on RISC OS today

RISC OS is provided with a rich set of printer drivers, with support for many manufacturers - Brother, Canon, Epson, HP, Mannesmann Tally, Olivetti, Qume, Star...

Maybe some of those names might have given away that it was reasonably good support for the early '90s.

Printing support on RISC OS nowadays is pretty poor. The general "solution" (in scare quotes) is to print to a PDF and then use something else to send the data to a printer. But even that's a broken solution - the standard PostScript driver outputs complete gibberish when faced with Unicode. There is a solution but it costs £35/€40 which is a bit steep when you consider that it only creates proper PostScript, it doesn't send anything to a printer, and my entire inkjet cost less. So, one can finally print Japanese with it, but we're still stuck with the problem of getting data to a printer.

 

Playing with IPP

Something that I have been working on for a while is in detecting and interacting with IPP (Internet Printing Protocol) printers. It's not difficult to scan for and open a port to retrieve information about a printer, once you understand that IPP is basically like an HTTP request, only it uses a binary payload. That is to say, things are tagged with bytes of specific value rather than keywords.

The problem with IPP is that it primarily comes in two flavours. The most recent version, that might be useful to RISC OS, is thanks to the IPP Everywhere initiative, making an open specification on ways to communicate with networked printers. In the long run, supporting this on RISC OS will give the platform the ability to access a new generation of modern printing devices.
The older incarnation of IPP specified the transport. It did not specify the raster format, and for this, the de facto standard is Apple's "AirPrint". The raster format in use here is called "URF", which probably means something like Unified Raster Format. There appear to be at least a dozen or so incarnations, and only one (a 24 bit RGB packbits style encoding) has been known to have been decoded. Sort of. There's a lot of parts marked as unknown. Sending that data to my HP 3630 inkjet did work, but sending it to my laser failed. Not a surprise really, what's a monochrome laser to do with 24 bit RGB?
All of the other support via drivers for PCs, or custom drivers on Android, use device specific protocols. For my inkjet, that's PCL3GUI as far as I can tell, and for the laser it's QPDL.
Neither of those are officially documented either.

 

The printer

The sacrificial lamb printer in question is a Samsung SL-M2022W.
It is a low cost simple monochrome laser printer, that is discussed here.

 

My next great idea

Yesterday, began the day with the idea of printing to a generic laserjet and translating that into a monochrome sprite:

The plan was to then slice this into something that could be converted to QPDL for use with my laser.
This step was going to be slow, but would be necessary because older printers accept their raster data row by row, while it appears the QPDL breaks the bitmap into slices, and then encodes vertically within each slice, as is better explained by a simple drawing (actual slices are 128 pixels, this is simplified for clarity):

That's where I hit a roadblock. QPDL is compressed. Not in the sort-of-packbits like everything else, but in a method that uses bits of uncompressed data and a table of entries into it for reconstituting the rest of the data. I'm not very good at mathematics, so the description of what was going on was... well... gibberish. I also was not intending to so much as look at the source code of the existing (splix) implementation for Linux, because it was licenced GPL and I wanted this to be entirely my own work (so could be anything other than GPL).
I had an example dump from Windows (print to file) and that's when I noticed something:

It wasn't just a raw dump of the QPDL data, it was prefixed with a lot of PJL. That's HP's "Printer Job Language" that sets up a number of attributes before specifying which "language" to switch to for the data, in this case, QPDL.

 

Fun with PCL

So, I thought, why not - just as a test - try some PCL (HP's Printer Command Language, what people used to mean when they said "LaserJet compatible" though it's evolved a lot since then).

So I replaced the file with this:

<esc>%-12345X@PJL JOB NAME "A Test"<cr><lf>
@PJL ENTER LANGUAGE = PCL<cr><lf>
The things in angle brackets are explaining characters not directly visible, namely ASCII 27 for escape, and the usual carriage return/life feed pairing.

Nothing happened. This was good, the printer wasn't throwing an error.

Time to flesh it out a little.

<esc>%-12345X@PJL JOB NAME "A Test"<cr><lf>
@PJL ENTER LANGUAGE = PCL<cr><lf>
<esc>EHello!
<esc>%-12345X@PJL EOF<cr><lf>
<esc>%-12345X

And this was accepted, resulting in a page that said "Hello!" (and not "EHello!").

One more test:

<esc>%-12345X@PJL JOB NAME "A Test"<cr><lf>
@PJL ENTER LANGUAGE = PCL<cr><lf>
<esc>E<esc>*p500x500YHello!
<esc>%-12345X@PJL EOF<cr><lf>
<esc>%-12345X

This had the same effect, only the "Hello!" was printed further away from the edges of the page.

Which meant this printer, that made no mention of supporting PCL in it's IPP data block, and which specifically claimed not to support PCL in the instruction booklet...
...actually appears to support PCL.

So I decided to just go for it. I took the entire raster bitmap that I'd already generated and pasted it in place of the "Hello!" line. All megabyte or so of it.

AND IT WORKED!

Okay, it didn't entirely work, I got about an inch of print followed by gibberish, but this was a mere implementation issue (the printer probably cacked itself it have a megabyte tossed to it in a manner of seconds). The important thing was that the SL-M2022W was actually capable of understanding output intended for an HP LaserJet.

This was the first time I've had a native printout from RISC OS in around 15 years, and given the last time was something that had a parallel port attached to a RiscPC, this is the first time I've had native 32 bit RISC OS printing anything by itself ever.

It's probably sad that that's a big moment, but there you go... I'm sad and proud of it.

 

Refining

The rest of the day was spent making a program to scan the network looking for a compatible printer, and then trickle-feeding (the printer is actually kind of slow at dealing with this) data to it. And then making my program (that was originally "a hack") into something a little more bombproof. At least good enough that it can work.

Printing is actually a two-stage process. Something (whatever) is printed from RISC OS to a file. When that has completed, you run my program that takes the file, adds some PCL preamble, and then feeds it to the printer. Maybe one day this could be added directly to !Printers, to print to a raw port (9100) on a specific IP address? But for now it's a two-stage process. But I'm perfectly happy with that, as my program can work in a TaskWindow (so doesn't tie up the machine) and it's a lot less crap than making everything into a PDF and then fetching that from Windows or my phone to then do the actual printing.

 

Will it work for you?

If you have an IPP (WiFi/mobile printing) laser printer, then I'd suggest giving it a try. It may not work, I don't know how widespread support for HP's PCL is. I was actually pretty surprised that it worked at all with my printer. There are some nice printers that can print directly from an uploaded PDF. My SL-M2022W, on the other hand, is a budget laser that is pretty inexpensive but punches above its weight with some useful features like the NFC tap-to-print (so friends can print directly to it without having to associate with your WiFi). It also supported PCL too. So maybe your printer might as well?

If you have a colour inkjet, not only is this unlikely to work (being a mono raster), my program will specifically discount your printer as compatible. This is primarily because my inkjet is a lower IP address and I wanted to find the laser printer not the inkjet.

 

Setting up your system

Load !Printers, and click on any of the icons on the iconbar.

Click on Install new printer. A window with numerous directories will open. Double-click on the HP directory to open it, and then double-click on the LasJet-6 file.

A new icon will appear on the iconbar.

Menu-click on the new icon to open the menu, and choose the third option down, Printer control....

The printer control window will open:

Menu-click on the new printer name to open the control menu, and choose Configure....

In the configuration window, change the name to something to reflect your printer.
Then set the quality to High (600dpi) - that counts as "normal" these days. RISC OS doesn't have 1,200dpi capabilities.
The rest (paper feed auto, quality grey/diffused) can be left at their default settings.

Close that window, call up the menu again, and choose Connection....

Here, you can tick Print in background if you like.
In the list of connection choices, select File and set the destination to be <Wimp$ScrapDir>.LJ6data.

Smile as you click on Set that the other setup window had an 'OK' button, not a 'Set' button. Such consistency from the people that wrote The Style Guide. ☺

Go back to the iconbar icon, and click on Save choices, or all of this will be forgotten when you next start !Printers.

 

Your first print

With !Printers loaded, click on the printer to make it the current one (cream, not grey):

Load up whatever document you would like to print. Here you can see the lyrics to the song Hello, shooting star by moumoon in Ovation.

The group is called "moumoon", and since we're printing a raster bitmap directly from RISC OS, you can print anything that FontManager is capable of dealing with.
Note: If you don't have Ovation and you'd like a superior word processor / basic desktop publisher, you can pick up a copy from right here.

Choose to Print. This is Ovation's print dialogue. Yours will be sort-of-similar. Let it get on with things.

The job isn't done yet. You have a printer file, but what to do with it?

That's where SammyPrint comes into play.

Get your copy of SammyPrint (v0.02b)

Unpack SammyPrint and double-click to run it. Your computer will pause while SammyPrint does its stuff. That is to say, it will scan your local network for compatible IPP printers. The first compatible printer that it finds (active, mono, supports URF) will have the printout sent to it.
[hourglass]You can see what SammyPrint is doing by looking at the hourglass that appears. If the upper LED is being shown (as in the hourglass shown on the left here) that means that your network is being scanned to look for compatible printers. Scanning is in numerical order, so it'll find x.x.x.8 much faster than x.x.x.99.
While attempting to connect to a printer, the lower LED will be shown, And when actually sending data, the percentage counter will count up reflecting how much has been sent.

If it worked, then that's it.
Printing is a two-stage process. Print to file as if for a LaserJet 6, then use SammyPrint to find an IPP printer and send the data to it.

 

And if it didn't print?

Normally there are no messages at all from SammyPrint, it will only muck around with the hourglass to reflect its status.
However, if you should get a message...

And, on the printer side:

Generally speaking, if it doesn't work it probably won't work.

 

What to do next?

If it does not work, delete the LJ6 printer profile that you added to !Printers. I'm sorry if it doesn't work for you, but on the plus side you're no worse off than you were before.

If it does work, then I suggest you rename SammyPrint to !SammyPrint and place it in $.Apps so it'll get added to your Apps resource for easy access.
Alternatively, create a TaskObey file to run SammyPrint, and drop that in Apps. The program is just as happy running in a TaskWindow - it'll still report its activity using the hourglass, but your machine will carry on multitasking.

Either way please drop a note on the ROOL forum to let me know how you get on.

 

Updated 2019/07/30

SammyPrint has been updated (to version 0.02 - please update if you downloaded an earlier version).

This version includes a number of command line options to tailor its behaviour:

SammyPrint -?
Syntax: SammyPrint [-colour] [-file <filename>] [-ip <addr>] [-nopreamble] [-verbose] 
        -colour     to allow colour printers to be accepted in network scan
        -file <f>   to use a file other than <Wimp$ScrapDir>.LJ6data.
        -ip <addr>  is an IP address of a printer, device will NOT
                    be checked for compatibility first.
        -nopreamble to send data verbatim, without PJL setup.
        -verbose    to be talkative (best used in a TaskWindow)

Examples:
  To print a LaserJet 6 output to a Samsung M2022W laser printer:
    SammyPrint
  To do likewise, but specify the printer:
    SammyPrint -ip 192.168.1.24
  To send "$.kittens.jpeg" to an HP3630 inkjet:
    SammyPrint -colour -file "$.kittens/jpeg" -nopreamble -verbose
    (this may work also for PDFs or PostScript if supported by the printer)

This is SammyPrint version 0.02 (30th July 2019) by Rick Murray.
Please refer to https://heyrick.eu/blog/index.php?diary=20190729

If you specify no options, it will behave as before - scanning for a monochrome AirPrint printer to send it the printout file <Wimp$ScrapDir>.LJ6data (as described above).

However, you can now...

Working examples:

That last example works because SammyPrint actually only looks at the first character of the parameter, so -nopreamble, -n, -nobrexit and -nowayjose all look the same...

As before, please let me know how you get on.

 

 

Your comments:

David Pilling, 30th July 2019, 19:56
"the standard PostScript driver outputs complete gibberish when faced with Unicode" as it does when faced with anything else (sprites with masks).
David Pilling, 31st July 2019, 13:41
cf RComp Uniprint
Rick, 31st July 2019, 13:50
UniPrint - a good solution (with price comparable to the PS3 driver), let down only slightly by the fact that it needs another computer to do the actual grunt work. ;-) 
http://www.arsvcs.demon.co.uk/rci/uniprint/index.html 
 
Yesterda y evening I printed Frobnicate issue 31 (the Frenchie one) completely from RISC OS on my Pi. Just told OvationPro to print it as a pamphlet doing the even pages, then the odds as two separate jobs. Then did it all again because I put the turned pages in the wrong way up (duh!). Took about five minutes, required nothing else. I'm happy with that.
David Pilling, 1st August 2019, 13:31
Good point about IPP having a bitmap format - that's the key - which I'd not taken in.
David Pilling, 1st August 2019, 16:03
In a way then printers have come full circle, what did the damage to RISC OS and inspired things like Uniprint was complicated secret command sets. Things which needed a lot of code and inside knowledge to get good results. 
David Pilling, 1st August 2019, 16:04
PS Good work!
Timo Hartong, 2nd October 2023, 23:27
I can now print on my network printer from the Pinebook Pro this is fantastic

Add a comment (v0.11) [help?]
Your name:

 
Your email (optional):

 
Validation:
Please type 09129 backwards.

 
Your comment:

 

Navi: Previous entry Display calendar Next entry
Switch to desktop version

Search:

See the rest of HeyRick :-)