Tag Archives: print

Print on FreeBSD

Nothing compares more to the sense of power UNIX sysadmin experiences when being able to print from a command line on its UNIX system :p

I kinda omitted this topic (printing) for quite a lot of time – when I was using FreeBSD in the corporate environment I still printed from Windows VM on a network printers. Then they forced me to use Windows anyway. At home my wife always had a printer configured (as she uses it more) and the other printer also had USB port – so you could just copy the PDF or JPG file to a USB pendrive – attach it the printer and hit print button for the selected files. No configuration needed.

I was also disappointed when I tried several years ago to configure USB printer on FreeBSD … and failed.

Recently I though that its about fucking time to dig into that topic and have at least one working printer on FreeBSD.

cups
This guide will focus on using two printers with CUPS on FreeBSD:

  • HP Color LaserJet 200 M251nw Printer (attached over TCP/IP network)
  • Samsung Black/White ML-1915 Printer (local USB attached)

There will be two different prompt types used for the commands:

  • starting with % for commands that can be executed as regular user or root
  • starting with # for commands that must be executed as root user

The Table of Contents for this article is shown below.

  • CUPS Packages and Service Configuration
  • Network Printer – HP M251nw
  • Try to Print Some Document
  • USB Printer – Samsung ML-1915
  • Choose Default Printer
  • CUPS Printers Config
  • Command Line Printing
  • Last Chance Fancy Pants
  • Summary

CUPS Packages and Service Configuration

There are only three pkg(8) packages needed for my printers – these are:

# pkg install cups cups-filters splix

We will also need to add some lines to the /etc/devfs.rules file.

These lines are important for printing with CUPS:

add path 'lpt*'      mode 0660 group cups
add path 'ulpt*'     mode 0660 group cups
add path 'unlpt*'    mode 0660 group cups

The rest of the config is just the rest of my desktop config and can be omitted for printing.

The entire /etc/devfs.rules file looks as follows.

% cat /etc/devfs.rules
[desktop=10]
add path 'lpt*'      mode 0660 group cups
add path 'ulpt*'     mode 0660 group cups
add path 'unlpt*'    mode 0660 group cups
add path 'acd*'      mode 0660 group operator
add path 'cd*'       mode 0660 group operator
add path 'da*'       mode 0660 group operator
add path 'pass*'     mode 0660 group operator
add path 'xpt*'      mode 0660 group operator
add path 'fd*'       mode 0660 group operator
add path 'md*'       mode 0660 group operator
add path 'uscanner*' mode 0660 group operator
add path 'ugen*'     mode 0660 group operator
add path 'usb/*'     mode 0660 group operator
add path 'video*'    mode 0660 group operator
add path 'cuse*'     mode 0660 group operator

We will also need to add devfs_system_ruleset=desktop to the /etc/rc.conf file.

% grep desktop /etc/rc.conf
  devfs_system_ruleset=desktop

Now we need to restart the devfs daemon to read new config.

# service devfs restart

We can also make sure that devfs(8) know our ruleset config.

# devfs rule -s 10 show | column -t
100   path  acd*       group  operator  mode  660
200   path  cd*        group  operator  mode  660
300   path  da*        group  operator  mode  660
400   path  pass*      group  operator  mode  660
500   path  xpt*       group  operator  mode  660
600   path  fd*        group  operator  mode  660
700   path  md*        group  operator  mode  660
800   path  uscanner*  group  operator  mode  660
900   path  lpt*       group  cups      mode  660
1000  path  ulpt*      group  cups      mode  660
1100  path  unlpt*     group  cups      mode  660
1200  path  ugen*      group  operator  mode  660
1300  path  usb/*      group  operator  mode  660
1400  path  video*     group  operator  mode  660
1500  path  cuse*      group  operator  mode  660

The column(1) is not needed here – I used it only to format the output.

What amaze me to this day that column(1) command is still not available on such enterprise (and overpriced also) IBM AIX system πŸ™‚

Here are the contents of fresh CUPS installation at /usr/local/etc/cups dir.

# tree -F --dirsfirst /usr/local/etc/cups
/usr/local/etc/cups
β”œβ”€β”€ ppd/
β”œβ”€β”€ ssl/
β”œβ”€β”€ cups-files.conf
β”œβ”€β”€ cups-files.conf.sample
β”œβ”€β”€ cupsd.conf
β”œβ”€β”€ cupsd.conf.sample
β”œβ”€β”€ snmp.conf
└── snmp.conf.sample

3 directories, 6 files

You will need to add cupsd_enable=YES to the /etc/rc.conf file.

% grep cups /etc/rc.conf
  cupsd_enable=YES

Make sure that cupsd service is started and running.

# service cupsd start
Starting cupsd.

# service cupsd status
cupsd is running as pid 44515.

# sockstat -l4 | grep -e ADDRESS -e 631
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
root     cupsd      44515 6  tcp4   127.0.0.1:631         *:*

Just in case – here are the groups in which my vermaden user is:

% id | tr ',' '\n'
uid=1000(vermaden) gid=1000(vermaden) groups=1000(vermaden)
0(wheel)
5(operator)
44(video)
69(network)
145(webcamd)
920(vboxusers)

It was not needed to add my vermaden user to the cups group to print – but feel free to also test that if you face any problems.

Network Printer – HP M251nw

First I will go with the TCP/IP attached network printer – HP M251nw.

printer-HP-M251nw
Before doing any steps or configuration on FreeBSD part we first need to connect that printer to the TCP/IP network. As the HP M251nw printer has WiFi – I decided to connect it to my wireless WiFi router instead of using RJ45 cable. I will not document that part as HP already provides decent guide on how to achieve that – https://youtu.be/jLDzQBAtKyQ – on YouTube service.

In my case I used the 10.0.0.9 IP address and I configured my WiFi router to always attach that MAC address to that IP address.

printer-HP-M251nw-www

Next step is to open http://localhost:631/ page in your browser. You will see default CUPS web interface.

cups-page-01

Hit the Administration tab on the top. Then click the Add Printer button in the middle of the page – you will be asked for username and password – use your username and your password here.

cups-page-03-admin-01-ADD-PRINTER

The HP M251nw network attached browser has already been detected by CUPS. Select it and click Continue button.

cups-page-03-admin-03-ADD-PRINTER

CUPS will suggest some long names and description as showed below.

cups-page-03-admin-04-ADD-PRINTER

… but we will use simpler and shorter name instead.

cups-page-03-admin-05-ADD-PRINTER

Next we need to choose which driver to use.

We will not find a HP M251nw driver on the CUPS list but there are two drivers that will work here:

  • HP LaserJet Series PCL 6 CUPS (en)
  • HP Color LaserJet Series PCL 6 CUPS (en)

As HP M251nw is color printer we will choose HP Color LaserJet Series PCL 6 CUPS here.

cups-page-03-admin-06-ADD-PRINTER-driver

After a moment we will see a message that HP M251nw printer has been successfully added to CUPS.

cups-page-03-admin-07-ADD-PRINTER

You can notice that new PPD file appeared at CUPS dir named exactly like the printer name.

% ls -l /usr/local/etc/cups/ppd
total 9K
-rw-r----- 1 root cups 9721 2023-02-06 11:24 HP-M251nw.ppd
-rw-r----- 1 root cups 9736 2023-02-06 11:23 HP-M251nw.ppd.O

This is how our HP M251nw printer status page looks like.

cups-page-03-admin-08-ADD-PRINTER

We should now setup the default printing options. From the Administration drop down menu select Set Default Options option. The only things I selected/set that are different from the CUPS defaults are A4 paper size and 1200 DPI resolution.

cups-page-03-admin-09-ADD-PRINTER-prefs

Try to Print Some Document

I will now use Atril PDF viewer to test how the printing on the HP M251nw works – I used a small one page PDF file with one of my old guides – the ZFS Madness one from 2014. From the File menu select Print… option – or just hit [CTRL]+[P] shortcut.

PDF-print-01

Then select HP-M251nw printer from the list and hit the Print button below.

PDF-print-02

After some noises and time (not much later) the printer dropped a printed page. Seems to work properly.

real-printed-page

Looks good.

Lets now add USB printer.

USB Printer – Samsung ML-1915

To get needed PPD driver for the Samsung ML-1915 printer we installed the print/splix package.

printer-SAMSUNG-ML-1915

Here is the exact driver we will use.

% pkg info -l splix | grep 1915
        /usr/local/share/cups/model/samsung/ml1915.ppd

Before attaching the Samsung ML-1915 printer to your computer you may check what devices devd(8) will create.

First power on the Samsung ML-1915 printer.

Then attach the USB cable from the printer to your FreeBSD box (assuming that printer has AC power and is powered on).

You should see something similar from devd(8) daemon.

# nc -U /var/run/devd.pipe
!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/0.3.0
!system=DEVFS subsystem=CDEV type=CREATE cdev=ugen0.3
!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/0.3.2
!system=DEVFS subsystem=CDEV type=CREATE cdev=usb/0.3.3
!system=USB subsystem=DEVICE type=ATTACH ugen=ugen0.3 cdev=ugen0.3 vendor=0x04e8 product=0x3297 devclass=0x00 devsubclass=0x00 sernum="Z2L9BACSC00641K." release=0x0100 mode=host port=2 parent=ugen0.2
!system=USB subsystem=INTERFACE type=ATTACH ugen=ugen0.3 cdev=ugen0.3 vendor=0x04e8 product=0x3297 devclass=0x00 devsubclass=0x00 sernum="Z2L9BACSC00641K." release=0x0100 mode=host interface=0 endpoints=2 intclass=0x07 intsubclass=0x01 intprotocol=0x02
!system=DEVFS subsystem=CDEV type=CREATE cdev=ulpt0
!system=DEVFS subsystem=CDEV type=CREATE cdev=unlpt0
+ulpt0 at bus=0 hubaddr=2 port=2 devaddr=3 interface=0 ugen=ugen0.3 vendor=0x04e8 product=0x3297 devclass=0x00 devsubclass=0x00 devproto=0x00 sernum="Z2L9BACSC00641K." release=0x0100 mode=host intclass=0x07 intsubclass=0x01 intprotocol=0x02 on uhub4

These are the created devices.

% ls -ltra /dev | tail -3
lrw-rw----  1 root     operator      9 2023-02-06 11:38 ugen0.3 -> usb/0.3.0
crw-rw----  1 root     cups     2, 113 2023-02-06 11:38 ulpt0
crw-rw----  1 root     cups     2, 114 2023-02-06 11:38 unlpt0

They are created with proper cups group.

Now we will go to the CUPS web page at http://localhost:631/ again to add the Samsung ML-1915 printer.

Go again to the Administration tab and click Add Printer button.

cups-page-03-admin-01-ADD-PRINTER

The Samsung ML-1915 should be already detected as local printer as shown below.

cups-samsung-01-ADD-PRINTER

Select it and hit Continue button.

As earlier we will use shorter more reasonable name.

cups-samsung-03-ADD-PRINTER

We will then select Samsung ML-1915, 2.0.0 (en, en) driver for this printer.

cups-samsung-04-ADD-PRINTER

… and Samsung ML-1915 black/white printer has been added.

cups-samsung-06-ADD-PRINTER

Same as earlier the PPD file is copied to the /usr/local/etc/cups/ppd CUPS dir.

% ls -l /usr/local/etc/cups/ppd
total 14K
-rw-r----- 1 root cups  9721 2023-02-06 11:24 HP-M251nw.ppd
-rw-r----- 1 root cups  9736 2023-02-06 11:23 HP-M251nw.ppd.O
-rw-r----- 1 root cups 12391 2023-02-06 11:58 Samsung-ML-1915.ppd

You now have two printers configured in CUPS.

cups-samsung-07-ADD-PRINTER

Choose Default Printer

I will now choose the HP M251nw printer as the default for two reasons. First – its always available as its attached over WiFi. Second – its more powerful and provides color at the same time.

To do that I went to the Printers and clicked the HP M251nw printer.

cups-samsung-08-ADD-PRINTER

Next from the Administration drop down menu I have chosen Set As Server Default option.

cups-samsung-09-ADD-PRINTER

From now on – if not explicitly specified – all the print jobs will land on the HP M251nw printer.

cups-samsung-10-ADD-PRINTER

CUPS Printers Config

After our actions CUPS stored two printers configuration in its /usr/local/etc/cups/printers.conf config file.

# cat /usr/local/etc/cups/printers.conf
# Printer configuration file for CUPS v2.4.2
# Written by cupsd
# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING
NextPrinterId 3
<DefaultPrinter HP-M251nw>
PrinterId 1
UUID urn:uuid:b760d323-5f46-36cd-4ca0-d9015c9fb7ca
Info 
Location 
MakeModel HP Color LaserJet Series PCL 6 CUPS
DeviceURI socket://10.0.0.9
State Idle
StateTime 1675683146
ConfigTime 1675679066
Type 8400972
Accepting Yes
Shared No
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy stop-printer
Attribute marker-colors \#000000,#00FFFF,#FF00FF,#FFFF00
Attribute marker-levels 99,98,98,99
Attribute marker-names Black Cartridge HP CF210X,Cyan Cartridge HP CF211A,Magenta Cartridge HP CF213A,Yellow Cartridge HP CF212A
Attribute marker-types toner,toner,toner,toner
Attribute marker-change-time 1675683146
</DefaultPrinter>
<Printer Samsung-ML-1915>
PrinterId 2
UUID urn:uuid:4434851b-5516-3b73-702a-286dabf630b0
Info 
Location 
MakeModel Samsung ML-1915, 2.0.0
DeviceURI usb://Samsung/ML-191x%20252x%20Series?serial=Z2L9BACSC00641K.
State Idle
StateTime 1675681099
ConfigTime 1675681099
Type 12372
Accepting Yes
Shared No
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy stop-printer
</Printer>

Command Line Printing

Besides being able to print from graphical applications that support CUPS we can also print directly from the command line if needed.

Use lpstat(1) command to see all available printers – including the default one.

% lpstat -p -d
printer HP-M251nw is idle.  enabled since Mon Feb  6 12:02:39 2023
printer Samsung-ML-1915 is idle.  enabled since Mon Feb  6 11:58:19 2023
system default destination: HP-M251nw

You can check more information about the default printer with lpoptions(1) command.

% lpoptions -l
PageSize/Media Size: Letter Legal Executive Tabloid A3 *A4 A5 B5 EnvISOB5 Env10 EnvC5 EnvDL EnvMonarch
InputSlot/Media Source: *Default Auto MultiPurpose Upper Lower LargeCapacity Manual Envelope
ColorModel/Output Mode: *RGB Gray
Resolution/Output Resolution: 150dpi 300dpi 600dpi *1200dpi
Duplex/Double-Sided Printing: *None DuplexNoTumble DuplexTumble
OptionDuplex/Duplexer: True *False

… or even more details and information when executed without arguments.

I have used tr(1) tool to make the output more readable as by default all this information is separated only by spaces.

% lpoptions | tr ' ' '\n'
copies=1
device-uri=socket://10.0.0.9
finishings=3
job-cancel-after=10800
job-hold-until=no-hold
job-priority=50
job-sheets=none,none
marker-change-time=1675681359
marker-colors=#000000,#00FFFF,#FF00FF,#FFFF00
marker-levels=99,98,98,99
marker-names='Black\
Cartridge\
HP\
CF210X,Cyan\
Cartridge\
HP\
CF211A,Magenta\
Cartridge\
HP\
CF213A,Yellow\
Cartridge\
HP\
CF212A'
marker-types=toner,toner,toner,toner
number-up=1
print-color-mode=color
printer-commands=AutoConfigure,Clean,PrintSelfTestPage
printer-info
printer-is-accepting-jobs=true
printer-is-shared=false
printer-is-temporary=false
printer-location
printer-make-and-model='HP
Color
LaserJet
Series
PCL
6
CUPS'
printer-state=3
printer-state-change-time=1675681359
printer-state-reasons=none
printer-type=10629196
printer-uri-supported=ipp://localhost/printers/HP-M251nw

We will now print the same PDF document using command line with lp(1) command.

% lp ZFS-Madness-2014.pdf
request id is HP-M251nw-02 (1 file(s))

Believe me or not – that PDF document got printed exactly the same as when invoked from Atril PDF browser.

Last Chance Fancy Pants

There is of course a chance that your printer will not be detected – or it will not print – or the driver will not attach to it properly … life happens.

What then? Fuck it. There is even more fun way to print … even without any drivers or configuration … directly with nc(1) command πŸ™‚

First lets check of your printer listens on 9100 port – this is called HP JetDirect.

% grep 9100 /etc/services
jetdirect       9100/tcp   #HP JetDirect card
pdl-datastream  9100/tcp   #Printer PDL Data Stream
pdl-datastream  9100/udp   #Printer PDL Data Stream

% nmap -A 10.0.0.9
Starting Nmap 7.93 ( https://nmap.org ) at 2023-02-06 23:41 CET
Nmap scan report for 10.0.0.9
Host is up (0.0072s latency).
Not shown: 988 closed tcp ports (conn-refused)
PORT     STATE SERVICE        VERSION
21/tcp   open  ftp            oftpd
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_.
|_ftp-bounce: bounce working!
| ftp-syst:
|_  SYST: .
23/tcp   open  telnet         HP LaserJet printer telnetd (busy)
80/tcp   open  soap           gSOAP 2.7
| http-server-header:
|   Virata-EmWeb/R6_2_1
|_  gSOAP/2.7
81/tcp   open  tcpwrapped
82/tcp   open  tcpwrapped
83/tcp   open  tcpwrapped
443/tcp  open  ssl/tcpwrapped
| ssl-cert: Subject: commonName=NPI04344D/organizationName=Hewlett-Packard Co.
| Not valid before: 2012-09-01T00:00:00
|_Not valid after:  2022-09-01T00:00:00
|_http-server-header: gSOAP/2.7
|_ssl-date: TLS randomness does not represent time
515/tcp  open  printer
631/tcp  open  soap           gSOAP 2.7
| http-server-header:
|   Virata-EmWeb/R6_2_1
|_  gSOAP/2.7
5222/tcp open  tcpwrapped
| xmpp-info:
|   STARTTLS Failed
|   info:
|     features:
|     auth_mechanisms:
|     xmpp:
|     unknown:
|     compression_methods:
|     errors:
|       (timeout)
|_    capabilities:
8080/tcp open  soap           gSOAP 2.7
| http-server-header:
|   Virata-EmWeb/R6_2_1
|_  gSOAP/2.7
9100/tcp open  jetdirect?
Service Info: OS: Unix; Device: printer

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.37 seconds

Lets try to connect to it with nc(1) tool.

% nc -v 10.9 9100
Connection to 10.9 9100 port [tcp/jetdirect] succeeded!

… and yes you do not have to always type that whole 10.0.0.9 address as the middle zeroes can be omitted and 10.9 will be interpretted as 10.0.0.9 address.

Something basic for a start – a plain text print.

% lsblk | nc 10.9 9100

In a moment you should have the output of lsblk(8) command printed on a page.

Lets try something more fancy like a PDF file then.

% nc 10.9 9100 < ZFS-Madness-2014.pdf

Yep. Printed. No CUPS configuration needed here.

Maybe I should start the article with that instead πŸ™‚

Summary

Not sure what I can add here as I am definitely not printing expert.

Hope these instructions will help you to setup your printer on FreeBSD (or any other CUPS supported) system.

EOF