I have a Brother HL-3040CN networked colour laser printer. I bought it 5 years ago and I kinda wish I hadn’t. I’d done the appropriate research to confirm it worked with Linux, but I didn’t realise it only worked via a 32-bit binary driver. It’s the only reason I have 32 bit enabled on my house server and I really wish I’d either bought a GDI printer that had an open driver (Samsung were great for this in the past) or something that did PCL or Postscript (my parents have an Xerox Phaser that Just Works). However I don’t print much (still just on my first set of toner) and once setup the driver hasn’t needed much kicking.

A more major problem comes with firmware updates. Brother only ship update software for Windows and OS X. I have a Windows VM but the updater wants the full printer driver setup installed and that seems like overkill. I did a bit of poking around and found reference in the service manual to the ability to do an update via USB and a firmware file. Further digging led me to a page on resurrecting a Brother HL-2250DN, which discusses recovering from a failed firmware flash. It provided a way of asking the Brother site for the firmware information.

First I queried my printer details:

$ snmpwalk -v 2c -c public hl3040cn.local iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.1 = STRING: "MODEL=\"HL-3040CN series\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.2 = STRING: "SERIAL=\"G0JXXXXXX\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.3 = STRING: "SPEC=\"0001\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.4 = STRING: "FIRMID=\"MAIN\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.5 = STRING: "FIRMVER=\"1.11\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.6 = STRING: "FIRMID=\"PCLPS\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.7 = STRING: "FIRMVER=\"1.02\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.8 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.9 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.10 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.11 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.12 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.13 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.14 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.15 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.16 = STRING: ""

I used that to craft an update file which I sent to Brother via curl:

curl -X POST -d @hl3040cn-update.xml https://firmverup.brother.co.jp/kne_bh7_update_nt_ssl/ifax2.asmx/fileUpdate -H "Content-Type:text/xml" --sslv3

This gave me back some XML with a URL for the latest main firmware, version 1.19, filename LZ2599_N.djif. I downloaded that and took a look at it, discovering it looked like a PJL file. I figured I’d see what happened if I sent it to the printer:

cat LZ2599_N.djf | nc hl3040cn.local 9100

The LCD on the front of printer proceeded to display something like “Updating Program” and eventually the printer re-DHCPed and indicated the main firmware had gone from 1.11 to 1.19. Great! However the PCLPS firmware was still at 1.02 and I’d got the impression that 1.04 was out. I didn’t manage to figure out how to get the Brother update website to give me the 1.04 firmware, but I did manage to find a copy of LZ2600_D.djf which I was then able to send to the printer in the same way. This led to:

$ snmpwalk -v 2c -c public hl3040cn.local iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.1 = STRING: "MODEL=\"HL-3040CN series\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.2 = STRING: "SERIAL=\"G0JXXXXXX\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.3 = STRING: "SPEC=\"0001\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.4 = STRING: "FIRMID=\"MAIN\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.5 = STRING: "FIRMVER=\"1.19\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.6 = STRING: "FIRMID=\"PCLPS\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.7 = STRING: "FIRMVER=\"1.04\""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.8 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.9 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.10 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.11 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.12 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.13 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.14 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.15 = STRING: ""
iso.3.6.1.4.1.2435.2.4.3.99.3.1.6.1.2.16 = STRING: ""

Cool, eh?

[Disclaimer: This worked for me. I’ve no idea if it’ll work for anyone else. Don’t come running to me if you brick your printer.]