Print via Brother BR-Script3 PostScript instead of the vendor driver

The HL-4150CDN emulates PostScript 3, so CUPS converts client documents to PostScript and forwards them to socket://<ip>:9100. The official BR-Script3 PPD turns device options (tray, duplex, colour, media type, toner save, ...) into setpagedevice instructions. This drops the i386 multiarch runtime and the broken Brother vendor filter chain, and removes the unused Brother Linux packages from the repo.
This commit is contained in:
juergen committed 2026-10-18 16:54:33 +02:00
1 parent 6f3162849b
commit 30c685e085
22 files changed
+1067 -270

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
# Keep version-control metadata and macOS junk out of the build context.
.jj
.git
.opencode
.DS_Store
**/.DS_Store
+2
View File
@@ -0,0 +1,2 @@
# macOS metadata
.DS_Store
+25 -41
View File
@@ -7,28 +7,32 @@
# printer is described by environment variables: # printer is described by environment variables:
# #
# podman run --rm --network host \ # podman run --rm --network host \
# -e PRINTER_IP=192.168.1.50 \ # -e PRINTER_IP=192.168.100.7 \
# -e PRINTER_NAME=HL-4150CDN \ # -e PRINTER_NAME=HL-4150CDN \
# --name printserver printserver:latest # --name printserver printserver:latest
# #
# PRINTER_URI can be used instead of PRINTER_IP for full control: # PRINTER_URI can be used instead of PRINTER_IP for full control:
# #
# -e PRINTER_URI=lpd://192.168.1.50/binary_p1 # -e PRINTER_URI=lpd://192.168.100.7/binary_p1
# #
# The HL-4150CDN emulates BR-Script3 (PostScript 3). Jobs are converted to
# PostScript inside CUPS and forwarded to the printer unchanged; the official
# BR-Script3 PPD turns the queue's options (tray, duplex, colour, ...) into
# PostScript "setpagedevice" instructions. No Brother vendor binaries or 32-bit
# libraries are involved.
FROM debian:bookworm-slim FROM debian:bookworm-slim
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
# --- Task 2.1 / 2.2: base system, CUPS, Avahi, DBus and i386 runtime ------- # --- Task 3.1: base system, CUPS, Avahi, DBus and conversion filters -------
# The Brother filter binaries are 32-bit i386 ELF executables, so the i386 # cups-filters provides the PDF/PWG/URF -> PostScript filters used for
# architecture has to be enabled and the matching runtime libraries installed. # driverless clients (AirPrint/IPP Everywhere). Ghostscript and Poppler supply
RUN dpkg --add-architecture i386 \ # the underlying converters.
&& apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
cups \ cups \
cups-client \ cups-client \
cups-filters \ cups-filters \
cups-ppdc \
avahi-daemon \ avahi-daemon \
avahi-utils \ avahi-utils \
libnss-mdns \ libnss-mdns \
@@ -36,43 +40,23 @@ RUN dpkg --add-architecture i386 \
procps \ procps \
curl \ curl \
ghostscript \ ghostscript \
ca-certificates \
poppler-utils \ poppler-utils \
libc6:i386 \ ca-certificates \
libstdc++6:i386 \
libgcc-s1:i386 \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Make sure the 32-bit dynamic loader the Brother binaries ask for exists, # --- Task 3.2: install the BR-Script3 PostScript PPD -----------------------
# even if the i386 libc places it only in the multiarch directory. # The PPD encodes every device option (paper source, duplex, colour/mono,
RUN if [ ! -e /lib/ld-linux.so.2 ] && [ -e /lib/i386-linux-gnu/ld-linux.so.2 ]; then \ # media type, toner save, resolution, secure print) as PostScript
ln -s /lib/i386-linux-gnu/ld-linux.so.2 /lib/ld-linux.so.2; \ # "setpagedevice". CUPS's pstops filter injects the selected option code and
fi \ # the PPD's JCL entries wrap the job in PJL for the printer.
&& test -e /lib/ld-linux.so.2
# --- Task 2.3: install the Brother HL-4150CDN driver packages --------------
# Copy the local driver packages from the repository into the build context and
# install them. The LPR package must be installed before the CUPS wrapper
# package, which depends on it. `--force-all` is used because the packages are
# built for i386 and have no dependency information Debian can satisfy here.
# The whole assets tree is copied because the directory name contains a space, # The whole assets tree is copied because the directory name contains a space,
# which some COPY implementations cannot quote. # which some COPY implementations cannot quote.
COPY assets /tmp/assets COPY assets /tmp/assets
RUN install -m 0644 \
RUN mkdir -p /var/spool/lpd \ "/tmp/assets/Brother HL-4150CDN/ppd/BR4150_2.PPD" \
&& dpkg -i --force-all "/tmp/assets/Brother HL-4150CDN/lpr-driver/hl4150cdnlpr-1.1.1-5.i386.deb" \ /usr/share/cups/model/BR4150_2.PPD \
&& dpkg -i --force-all "/tmp/assets/Brother HL-4150CDN/cupswrapper/hl4150cdncupswrapper-1.1.1-5.i386.deb" \ && test -s /usr/share/cups/model/BR4150_2.PPD \
&& dpkg -s hl4150cdnlpr:i386 hl4150cdncupswrapper:i386 >/dev/null \ && rm -rf /tmp/assets \
&& rm -rf /tmp/assets
# --- Task 2.4: configure CUPS and verify the driver files are in place -----
# The CUPS wrapper postinst copies the PPD into the CUPS model directory and
# creates the brlpdwrapper filter. Fail the build if anything is missing.
RUN test -f /usr/share/cups/model/brhl4150cdn.ppd \
&& test -x /usr/lib/cups/filter/brlpdwrapperhl4150cdn \
&& test -x /usr/local/Brother/Printer/hl4150cdn/lpd/brhl4150cdnfilter \
&& mkdir -p /usr/share/ppd \
&& ln -sf /usr/share/cups/model/brhl4150cdn.ppd /usr/share/ppd/brhl4150cdn.ppd \
&& rm -f /etc/cups/printers.conf /etc/cups/printers.conf.O && rm -f /etc/cups/printers.conf /etc/cups/printers.conf.O
COPY cupsd.conf /etc/cups/cupsd.conf COPY cupsd.conf /etc/cups/cupsd.conf
@@ -80,11 +64,11 @@ COPY cupsd.conf /etc/cups/cupsd.conf
# CUPS needs the runtime directories to exist in the image. # CUPS needs the runtime directories to exist in the image.
RUN mkdir -p /run/cups /run/dbus /run/avahi-daemon /var/spool/cups /var/log/cups RUN mkdir -p /run/cups /run/dbus /run/avahi-daemon /var/spool/cups /var/log/cups
# --- Task 2.5: startup script ----------------------------------------------- # --- Task 3.5: startup script ----------------------------------------------
COPY entrypoint.sh /usr/local/bin/entrypoint.sh COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod 0755 /usr/local/bin/entrypoint.sh RUN chmod 0755 /usr/local/bin/entrypoint.sh
# --- Task 2.6: exposed ports ------------------------------------------------ # --- Task 3.6: exposed ports -----------------------------------------------
# 631/tcp CUPS administration and IPP # 631/tcp CUPS administration and IPP
# 5353/udp mDNS / DNS-SD for AirPrint discovery # 5353/udp mDNS / DNS-SD for AirPrint discovery
EXPOSE 631/tcp EXPOSE 631/tcp
+84 -35
View File
@@ -1,23 +1,50 @@
# Printserver # Printserver
A containerized CUPS print server that shares a **Brother HL-4150CDN** network A containerized CUPS print server that shares a **Brother HL-4150CDN** network
printer over IPP and advertises it via AirPrint (mDNS/DNS-SD), so client printer over IPP and advertises it via AirPrint (mDNS/DNS-SD). It prints by
devices can print without installing the Brother driver themselves. sending **PostScript (BR-Script3)** straight to the printer, so no vendor driver
and no 32-bit libraries run in the container.
The container bundles: The container bundles:
- CUPS (IPP/IPP Everywhere + web admin on port 631) - CUPS (IPP + web admin on port 631) with cups-filters for format conversion
- Avahi / DNS-SD for AirPrint discovery (UDP 5353) - Avahi / DNS-SD for AirPrint discovery (UDP 5353)
- The Brother HL-4150CDN LPR + CUPS wrapper drivers and 32-bit runtime libs - Brother's official HL-4150CDN **BR-Script3 PPD** for device options
## How it works
The HL-4150CDN emulates PCL6 and BR-Script3 (PostScript 3), and accepts
PostScript over raw AppSocket (port 9100). CUPS converts whatever a client
sends into PostScript and the BR-Script3 PPD turns the selected queue options
into PostScript `setpagedevice` instructions:
```
macOS / iOS / Windows / Linux container printer
┌─────────────────┐ IPP/AirPrint ┌──────────────────────────┐ raw ┌────────────┐
│ AirPrint (URF) │ ───────────────▶ │ CUPS │ ──────▶ │ HL-4150CDN │
│ PDF / PostScript│ │ URF/PWG/PDF → PostScript│ :9100 │ BR-Script3 │
└─────────────────┘ │ pstops → setpagedevice │ └────────────┘
└──────────────────────────┘
```
For example, `Duplex=DuplexNoTumble BRPrintQuality=Color InputSlot=Tray2`
becomes:
```postscript
<</Duplex true /Tumble false>>setpagedevice
<</BRProcessColor 4 /BRHrc 0>>setpagedevice
<</ManualFeed false /BRTraysw false /BRFeeder 1>> setpagedevice
```
## Layout ## Layout
| Path | Purpose | | Path | Purpose |
| --- | --- | | --- | --- |
| `Containerfile` | Image definition (Debian base, i386 multiarch, Brother driver install) | | `Containerfile` | Image definition (Debian base, CUPS + cups-filters + Avahi, BR-Script3 PPD) |
| `cupsd.conf` | Container CUPS configuration (listen on all interfaces, share printers) | | `cupsd.conf` | Container CUPS configuration (listen on all interfaces, share printers) |
| `entrypoint.sh` | Starts D-Bus, Avahi and CUPS, then registers the printer queue | | `entrypoint.sh` | Starts D-Bus, Avahi and CUPS, then registers the printer queue |
| `assets/Brother HL-4150CDN/` | Brother driver `.deb` packages used at build time | | `assets/Brother HL-4150CDN/ppd/` | Official BR-Script3 PPD used for the queue |
| `assets/Brother HL-4150CDN/Windows/` | Vendor Windows driver the PPD was extracted from |
## Prerequisites ## Prerequisites
@@ -32,15 +59,8 @@ Run from the repository root:
podman build -t printserver:latest . podman build -t printserver:latest .
``` ```
On an arm64 host, build for x86_64 explicitly (the Brother binaries are i386 The image is architecture-independent (no i386 or other 32-bit binaries), so it
and need an x86_64 target): builds natively on x86_64 and arm64 hosts alike.
```sh
podman build --platform linux/amd64 -t printserver:latest .
```
The build installs the Brother LPR and CUPS wrapper packages from
`assets/Brother HL-4150CDN/` and verifies that the PPD and filter are in place.
## Run ## Run
@@ -50,7 +70,7 @@ networking**:
```sh ```sh
podman run -d --name printserver \ podman run -d --name printserver \
--network host \ --network host \
-e PRINTER_IP=192.168.1.50 \ -e PRINTER_IP=192.168.100.7 \
-e PRINTER_NAME=HL-4150CDN \ -e PRINTER_NAME=HL-4150CDN \
printserver:latest printserver:latest
``` ```
@@ -61,34 +81,34 @@ podman run -d --name printserver \
| --- | --- | --- | | --- | --- | --- |
| `PRINTER_IP` | *(empty)* | IP address / host name of the network printer. A device URI is derived from it (see `PRINTER_PROTOCOL`). | | `PRINTER_IP` | *(empty)* | IP address / host name of the network printer. A device URI is derived from it (see `PRINTER_PROTOCOL`). |
| `PRINTER_URI` | *(empty)* | Full device URI. Overrides `PRINTER_IP` when set. | | `PRINTER_URI` | *(empty)* | Full device URI. Overrides `PRINTER_IP` when set. |
| `PRINTER_PROTOCOL` | `lpd` | Protocol used with `PRINTER_IP`: `lpd`, `socket` or `ipp`. | | `PRINTER_PROTOCOL` | `socket` | Protocol used with `PRINTER_IP`: `socket`, `lpd` or `ipp`. |
| `PRINTER_NAME` | `HL4150CDN` | CUPS queue name. Also used as the name advertised via AirPrint/DNS-SD. | | `PRINTER_NAME` | `HL4150CDN` | CUPS queue name. Also used as the name advertised via AirPrint/DNS-SD. |
| `PRINTER_DESCRIPTION` | *(empty)* | CUPS printer description (`lpadmin -D`), shown in the CUPS web UI. | | `PRINTER_DESCRIPTION` | *(empty)* | CUPS printer description (`lpadmin -D`), shown in the CUPS web UI. |
| `PPD_FILE` | `/usr/share/cups/model/brhl4150cdn.ppd` | PPD used for the queue. | | `PPD_FILE` | `/usr/share/cups/model/BR4150_2.PPD` | PPD used for the queue. |
No queue is created when neither `PRINTER_IP` nor `PRINTER_URI` is set. No queue is created when neither `PRINTER_IP` nor `PRINTER_URI` is set.
### Choosing the connection ### Choosing the connection
The HL-4150CDN is a network printer. Set `PRINTER_IP` and let the entrypoint The HL-4150CDN accepts PostScript directly, so the default is raw AppSocket.
build the URI: Set `PRINTER_IP` and let the entrypoint build the URI:
| `PRINTER_PROTOCOL` | Resulting URI | | `PRINTER_PROTOCOL` | Resulting URI |
| --- | --- | | --- | --- |
| `lpd` (default) | `lpd://<ip>/binary_p1` — LPR/LPD, the URI Brother documents | | `socket` (default) | `socket://<ip>:9100` — raw AppSocket/JetDirect |
| `socket` | `socket://<ip>:9100` — raw AppSocket/JetDirect | | `lpd` | `lpd://<ip>/binary_p1` — LPR/LPD |
| `ipp` | `ipp://<ip>/ipp/print` | | `ipp` | `ipp://<ip>/ipp/print` |
For example, a printer at `192.168.1.50` using LPD: For example, a printer at `192.168.100.7`:
```sh ```sh
-e PRINTER_IP=192.168.1.50 -e PRINTER_IP=192.168.100.7
``` ```
Or specify the URI explicitly for full control: Or specify the URI explicitly for full control:
```sh ```sh
-e PRINTER_URI=lpd://192.168.1.50/binary_p1 -e PRINTER_URI=socket://192.168.100.7:9100
``` ```
### Advertised name ### Advertised name
@@ -101,6 +121,39 @@ set `PRINTER_DESCRIPTION` (this does not change the advertised name):
-e PRINTER_NAME=HL4150CDN -e PRINTER_DESCRIPTION="Brother HL-4150CDN (Office)" -e PRINTER_NAME=HL4150CDN -e PRINTER_DESCRIPTION="Brother HL-4150CDN (Office)"
``` ```
## Printing options
The BR-Script3 PPD exposes the HL-4150CDN's hardware options. Common ones:
| Option | PPD keyword | Values |
| --- | --- | --- |
| Paper source | `InputSlot` | `AutoSelect`, `Tray1`, `Tray2`, `MPTray` |
| Two-sided printing | `Duplex` | `None`, `DuplexNoTumble` (long edge), `DuplexTumble` (short edge) |
| Colour / mono | `BRPrintQuality` | `Auto`, `Color`, `Black` |
| Colour mode | `BRColorMode` | `Normal`, `Vivid`, `None` |
| Media type | `BRMediaType` | `Plain`, `Thin`, `Thick`, `Recycled`, `Glossy`, `Label`, envelopes, … |
| Print quality | `CAPT` | `Fine` (600×600), `SuperFine` (2400 dpi class) |
| Toner save | `TonerSaveMode` | `True`, `False` |
| Secure print | `BRJobHold` | `None`, `Private` (+ `BRJobPIN`) |
They can be selected per job, e.g.:
```sh
podman exec printserver lp -d HL4150CDN \
-o Duplex=DuplexNoTumble -o BRPrintQuality=Color -o InputSlot=Tray1 report.pdf
```
## Client support
| Platform | Path | Notes |
| --- | --- | --- |
| macOS | AirPrint / IPP Everywhere | Discovered via mDNS; no driver needed |
| iOS / iPadOS | AirPrint | Discovered via mDNS; no driver needed |
| Linux | IPP / IPP Everywhere | Native or with the shared PPD |
| Windows | IPP or raw 9100 | Install Brother's **BR-Script3** Windows driver, pointed at the printer or the shared queue |
Windows uses a client-side Brother driver; the server does not share via SMB.
## Verify ## Verify
Browse the CUPS web interface: Browse the CUPS web interface:
@@ -115,6 +168,7 @@ From the host, or inside the container:
```sh ```sh
podman exec printserver lpstat -t # queues and status podman exec printserver lpstat -t # queues and status
podman exec printserver lpstat -v HL4150CDN # device URI podman exec printserver lpstat -v HL4150CDN # device URI
podman exec printserver lpoptions -p HL4150CDN -l # available options
podman exec printserver avahi-browse -rt _ipp._tcp # mDNS advertisement podman exec printserver avahi-browse -rt _ipp._tcp # mDNS advertisement
``` ```
@@ -128,10 +182,6 @@ On macOS/iOS the shared queue should appear in the printer list via AirPrint.
## Notes and limitations ## Notes and limitations
- **Run on an x86_64 host.** The Brother driver binaries are 32-bit i386 ELF
executables. They run natively on an x86_64 kernel, but on arm64 hosts the
image can be built and the drivers installed while the filter cannot execute
without i386 emulation (for example qemu-user / binfmt).
- **Host networking is required** for Avahi to send and receive mDNS traffic. - **Host networking is required** for Avahi to send and receive mDNS traffic.
`-p 631:631` alone is enough for direct IPP access but not for AirPrint `-p 631:631` alone is enough for direct IPP access but not for AirPrint
discovery. discovery.
@@ -142,9 +192,8 @@ On macOS/iOS the shared queue should appear in the printer list via AirPrint.
```sh ```sh
-v printserver-cups:/etc/cups -v printserver-cups:/etc/cups
``` ```
- The Brother filter is a PostScript-based CUPS filter. AirPrint clients that - Colour handling is done by the printer's own PostScript RIP. Output may differ
rely on driverless (URF) printing may not be able to use the queue; macOS slightly from Brother's host-side (rasterising) driver.
clients that can use the shared CUPS queue's PPD will work. - The queue advertises AirPrint capabilities (`image/urf`, `image/pwg-raster`,
- The Brother driver packages are 32-bit (i386); the image enables Debian's `sides-supported`, `color-supported`). macOS and iOS printing is converted by
i386 multiarch to provide `libc6:i386` and the `ld-linux.so.2` loader they cups-filters; verify end to end on your network.
need.
BIN
View File
Binary file not shown.
Binary file not shown.
@@ -1,38 +0,0 @@
1. Login as a superuser ( or use "sudo" option if it is required )
2. Install LPR driver and cupswrapper driver
Turn on the printer and connect the USB cable.
Open the terminal and go to the directory where the drivers are.
Install LPR driver.The install process may take some time. Please wait until it is complete.
Command (for dpkg) : dpkg -i --force-all (lpr-drivername)
Install cupswrapper driver.The install process may take some time. Please wait until it is complete.
Command (for dpkg) : dpkg -i --force-all (cupswrapper-drivername)
Check if the LPR driver and cupswrapper driver are installed
Command (for dpkg) : dpkg -l | grep Brother
3. Depending on the connection type you are using (USB or Network), follow one of the steps below.
(for USB Connection)
Open a web browser and go to "http://localhost:631/printers".
Check if the Device URI of your printer is "usb://Brother/(your printer's model name)"
If the device URI is different from the example above, please go to "Modify Printer" of your printer to select proper device and driver.
If your printer is not listed on "http://localhost:631/printers", please go to "http://localhost:631/admin" and click "Add printer" and select proper device and driver.
(for Network Connection)
Open a web browser and go to "http://localhost:631/printers".
Click "Modify Printer" and set following parameters.
- "LPD/LPR Host or Printer" or "AppSocket/HP JetDirect" for Device
- lpd://(Your printer's IP address)/binary_p1 for Device URI
- Brother for Make/Manufacturer Selection
- Your printer's name for Model/Driver Selection
4. Try a test print
Open a text editor, write something and select "print" from the menu.
Binary file not shown.
@@ -1,20 +0,0 @@
# Step 1. Enter this command to extract the downloaded file:
Command: `gunzip linux-brprinter-installer-*.*.*-*.gz`
e.g. `gunzip linux-brprinter-installer-2.2.6-0.gz`
# Step 2. Get superuser authorization with the "su" command or "sudo su" command.
# Step 3. Run the tool:
Command: `bash linux-brprinter-installer-*.*.*-* Brother machine name`
e.g. `bash linux-brprinter-installer-2.1.1-1 HL-4150CDN`
# Step 4. The driver installation will start. Follow the installation screen directions.
When you see the message "Will you specify the DeviceURI ?",
For USB Users: Choose N(No)
For Network Users: Choose Y(Yes) and DeviceURI number.
The install process may take some time. Please wait until it is complete.
@@ -1,38 +0,0 @@
1. Login as a superuser ( or use "sudo" option if required).
2. Install the driver.
Turn on the printer and connect the usb, network or parallel cable.
Go to the directory where the driver is.
Install LPR driver.The install process may take some time. Please wait until it is complete.
Command : dpkg -i --force-all (lpr-drivername)
Check if the LPR driver is installed.
Command : dpkg -l | grep Brother
3. Confirm/Configure a file according to your connection.
Check the configuration filename for your distribution.
Example:
openSUSE, Ubuntu, Debian : /etc/printcap
Redhat, fedora, Mandriva : /etc/printcap.local
Edit the file according to your connection.
For USB Connection (Default)
Check if the parameter of ":lp" is ":lp=/dev/usb/lp0"
For Network Connection
replace ":lp" line to the following 2 lines
:rm=(ip address of your printer)\
:rp=lp\
For Parallel Connection
replace ":lp" line to the following line
:lp=/dev/lp0\
Restart the print system.
Command (for lpr): /etc/init.d/lpr restart
Command (for lprng) : /etc/init.d/lprng restart
4. Try a test print.
+680
View File
@@ -0,0 +1,680 @@
*PPD-Adobe: "4.3"
*%================================================
*% Copyright(C) 2010 Brother Industries, Ltd.
*% "Brother HL-4150CDN BR-Script3"
*%================================================
*%==== General Information Keywords ========================
*FormatVersion: "4.3"
*FileVersion: "1.01"
*LanguageEncoding: ISOLatin1
*LanguageVersion: English
*Manufacturer: "Brother"
*PCFileName: "BR4150_2.PPD"
*Product: "(Brother HL-4150CDN)"
*PSVersion: "(3010.106) 3"
*ShortNickName: "Brother HL-4150CDN BR-Script3"
*ModelName: "Brother HL-4150CDN BR-Script3"
*NickName: "Brother HL-4150CDN BR-Script3"
*%==== Basic Device Capabilities =============
*LanguageLevel: "3"
*TTRasterizer: Type42
*ColorDevice: True
*DefaultColorSpace: CMYK
*FileSystem: True
*?FileSystem:"
save
/devname (%disk0%) def
/ret false def
0 1 7{
devname exch 48 add 5 exch put
devname devstatus {
0 ne {/ret true def}if
pop pop pop pop pop pop pop
}if
}for
ret {(True)}{(False)} ifelse = flush
restore
"
*End
*Throughput: "20"
*FreeVM: "2700000"
*%==== Emulations and Protocols ==========
*Protocols: PJL TBCP
*SuggestedJobTimeout: "0"
*SuggestedWaitTimeout: "300"
*PrintPSErrors: True
*%==== PostScript Patches ==========
*%*JobPatchFile 1: "statusdict/setusbbinary known{statusdict begin true setusbbinary end}if"
*%==== JCL Features ==========================
*JCLBegin: "<1B>%-12345X@PJL JOB<0A>"
*JCLToPSInterpreter: "@PJL ENTER LANGUAGE = POSTSCRIPT <0A>"
*JCLEnd: "<1B>%-12345X@PJL EOJ <0A><1B>%-12345X"
*%==== Installable Options ===================
*OpenGroup: InstallableOptions/Options Installed
*OpenUI *OptionTrays/Number of Input Trays: PickOne
*DefaultOptionTrays: 2Trays
*OptionTrays 1Trays/ 1: ""
*OptionTrays 2Trays/ 2: ""
*?OptionTrays:"
save
<</BRFeeder 1>>setpagedevice currentpagedevice/BRFeeder get
1 eq{(2Trays)}{(1Trays)}ifelse
= flush
restore
"
*End
*CloseUI: *OptionTrays
*CloseGroup: InstallableOptions
*UIConstraints: *OptionTrays 1Trays *InputSlot Tray2
*UIConstraints: *InputSlot Tray2 *OptionTrays 1Trays
*%==== Media Selection ======================
*OpenUI *PageSize: PickOne
*OrderDependency: 30 AnySetup *PageSize
*DefaultPageSize: A4
*PageSize Letter/Letter: "<< /PageSize [612 792] /ImagingBBox null >> setpagedevice"
*PageSize Legal/Legal: "<< /PageSize [612 1008] /ImagingBBox null >> setpagedevice"
*PageSize Executive/Executive: "<< /PageSize [522 756] /ImagingBBox null >> setpagedevice"
*PageSize A4/A4: "<< /PageSize [595 842] /ImagingBBox null >> setpagedevice"
*PageSize A5/A5: "<< /PageSize [420 595] /ImagingBBox null >> setpagedevice"
*PageSize A5L/A5 Long Edge: "<< /PageSize [595 419] /ImagingBBox null >> setpagedevice"
*PageSize A6/A6: "<< /PageSize [297 420] /ImagingBBox null >> setpagedevice"
*PageSize Env10/Com-10: "<< /PageSize [297 684] /ImagingBBox null >> setpagedevice"
*PageSize EnvMonarch/Monarch: "<</PageSize [279 540] /ImagingBBox null>> setpagedevice"
*PageSize EnvDL/DL: "<< /PageSize [312 624] /ImagingBBox null >> setpagedevice"
*PageSize EnvDLRotated/DL Long Edge: "<< /PageSize [624 312] /ImagingBBox null >> setpagedevice"
*PageSize EnvC5/C5: "<</PageSize [459 649] /ImagingBBox null>> setpagedevice"
*PageSize EnvISOB5/B5 : "<< /PageSize [499 709] /ImagingBBox null >> setpagedevice"
*PageSize EnvISOB6/B6 : "<< /PageSize [354 499] /ImagingBBox null >> setpagedevice"
*PageSize B5/JIS B5: "<< /PageSize [515.0 727.0] /ImagingBBox null >> setpagedevice"
*PageSize B6/JIS B6: "<< /PageSize [363.0 515.0] /ImagingBBox null >> setpagedevice"
*PageSize 3x5/3x5: "<< /PageSize [216 360] /ImagingBBox null >> setpagedevice"
*PageSize FanFoldGermanLegal/Folio: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice"
*CloseUI: *PageSize
*OpenUI *PageRegion: PickOne
*OrderDependency: 40 AnySetup *PageRegion
*DefaultPageRegion: A4
*PageRegion Letter/Letter: "<< /PageSize [612 792] /ImagingBBox null >> setpagedevice"
*PageRegion Legal/Legal: "<< /PageSize [612 1008] /ImagingBBox null >> setpagedevice"
*PageRegion Executive/Executive: "<< /PageSize [522 756] /ImagingBBox null >> setpagedevice"
*PageRegion A4/A4: "<< /PageSize [595 842] /ImagingBBox null >> setpagedevice"
*PageRegion A5/A5: "<< /PageSize [420 595] /ImagingBBox null >> setpagedevice"
*PageRegion A5L/A5 Long Edge: "<< /PageSize [595 419] /ImagingBBox null >> setpagedevice"
*PageRegion A6/A6: "<< /PageSize [297 420] /ImagingBBox null >> setpagedevice"
*PageRegion Env10/Com-10: "<< /PageSize [297 684] /ImagingBBox null >> setpagedevice"
*PageRegion EnvMonarch/Monarch: "<</PageSize [279 540] /ImagingBBox null>> setpagedevice"
*PageRegion EnvDL/DL: "<< /PageSize [312 624] /ImagingBBox null >> setpagedevice"
*PageRegion EnvDLRotated/DL Long Edge: "<< /PageSize [624 312] /ImagingBBox null >> setpagedevice"
*PageRegion EnvC5/C5: "<</PageSize [459 649] /ImagingBBox null>> setpagedevice"
*PageRegion EnvISOB5/B5 : "<< /PageSize [499 709] /ImagingBBox null >> setpagedevice"
*PageRegion EnvISOB6/B6 : "<< /PageSize [354 499] /ImagingBBox null >> setpagedevice"
*PageRegion B5/JIS B5: "<< /PageSize [515.0 727.0] /ImagingBBox null >> setpagedevice"
*PageRegion B6/JIS B6: "<< /PageSize [363.0 515.0] /ImagingBBox null >> setpagedevice"
*PageRegion 3x5/3x5: "<< /PageSize [216 360] /ImagingBBox null >> setpagedevice"
*PageRegion FanFoldGermanLegal/Folio: "<< /PageSize [612 936] /ImagingBBox null >> setpagedevice"
*CloseUI: *PageRegion
*DefaultImageableArea: A4
*ImageableArea Letter/Letter: "12.0 12.12 599.88 780.0"
*ImageableArea Legal/Legal: "12.0 12.12 599.88 996.0"
*ImageableArea Executive/Executive: "11.99 12.12 510.0 744.0"
*ImageableArea A4/A4: "12.0 12.24 583.08 829.92"
*ImageableArea A5/A5: "12.0 11.88 407.4 582.96"
*ImageableArea A5L/A5 Long Edge: "12.0 11.88 407.4 582.96"
*ImageableArea A6/A6: "12.0 12.6 285.48 408.0"
*ImageableArea Env10/Com-10: "12.0 12.12 284.88 672.0"
*ImageableArea EnvMonarch/Monarch: "12.0 12.12 266.76 528.0"
*ImageableArea EnvDL/DL: "12.0 12.24 299.88 612.0"
*ImageableArea EnvDLRotated/DL Long Edge: "17.76 12.12 606.24 300.0"
*ImageableArea EnvC5/C5: "12.0 12.24 446.76 636.96"
*ImageableArea EnvISOB5/B5 : "12.0 12.48 486.72 696.96"
*ImageableArea EnvISOB6/B6 : "12.0 12.24 342.12 486.96"
*ImageableArea B5/JIS B5: "12.0 12.48 502.92 714.96"
*ImageableArea B6/JIS B6: "12.0 12.00 350.88 503.00"
*ImageableArea 3x5/3x5: "12.0 12.12 204.00 348.00"
*ImageableArea FanFoldGermanLegal/Folio: "12.0 12.12 599.88 924.0"
*%==== Information About Media Sizes ========
*DefaultPaperDimension: A4
*PaperDimension Letter/Letter: "612 792"
*PaperDimension Legal/Legal: "612 1008"
*PaperDimension Executive/Executive: "522 756"
*PaperDimension A4/A4: "595 842"
*PaperDimension A5/A5: "420 595"
*PaperDimension A5L/A5 Long Edge: "420 595"
*PaperDimension A6/A6: "297 420"
*PaperDimension Env10/Com-10: "297 684"
*PaperDimension EnvMonarch/Monarch: "279 540"
*PaperDimension EnvDL/DL: "312 624"
*PaperDimension EnvDLRotated/DL Long Edge: "624 312"
*PaperDimension EnvC5/C5: "459 649"
*PaperDimension EnvISOB5/B5 : "499 709"
*PaperDimension EnvISOB6/B6 : "354 499"
*PaperDimension B5/JIS B5: "516 729"
*PaperDimension B6/JIS B6: "363 516"
*PaperDimension 3x5/3x5: "216 360"
*PaperDimension FanFoldGermanLegal/Folio: "612 936"
*%==== Custom Page Sizes ====================
*NonUIOrderDependency: 40 AnySetup *CustomPageSize
*VariablePaperSize: True
*LeadingEdge Short: ""
*LeadingEdge Long: ""
*DefaultLeadingEdge: Short
*MaxMediaWidth: "612"
*MaxMediaHeight: "1152"
*HWMargins: 13 13 13 13
*CustomPageSize True: "
<</BRCustomPageSize true>> setpagedevice
exch pop exch pop 0 eq{exch}if
<< /PageSize [ 5 -2 roll ] /ImagingBBox null >>
setpagedevice
"
*End
*ParamCustomPageSize Width: 1 points 198 612
*ParamCustomPageSize Height: 2 points 328 1152
*ParamCustomPageSize WidthOffset: 3 points 0 0
*ParamCustomPageSize HeightOffset: 4 points 0 0
*ParamCustomPageSize Orientation: 5 int 0 1
*%==== 5.12 Finishing Features =================================
*%%%%% Resolution and Appearance Control %%%%%
*DefaultResolution: 600dpi
*OpenUI *CAPT/Print Quality:PickOne
*OrderDependency: 10 AnySetup *CAPT
*DefaultCAPT: Fine
*CAPT Fine/Normal (600 x 600 dpi): "<</BRApt 0 /HWResolution [600 600]>> setpagedevice"
*CAPT SuperFine/Fine (2400 dpi class): "<</BRApt 2 /HWResolution [600 600]>> setpagedevice"
*?CAPT: "
currentpagedevice /BRApt get 2 eq
{(SuperFine)}
{
currentpagedevice/HWResolution get 0 get 600 eq{(Fine)}{(Draft)}ifelse
}ifelse = flush
"
*End
*CloseUI: *CAPT
*%==== 5.13 Media Handling Features ============================
*OpenUI *BRMediaType/Media Type: PickOne
*OrderDependency: 28 AnySetup *BRMediaType
*DefaultBRMediaType:Plain
*BRMediaType Plain/Plain Paper: "<</MediaType (REGULAR)>>setpagedevice"
*BRMediaType Thin/Thin Paper: "<</MediaType (THIN)>>setpagedevice"
*BRMediaType Thick/Thick Paper: "<</MediaType (THICK)>>setpagedevice"
*BRMediaType ThickPaper2/Thicker Paper: "<</MediaType (THICK2)>>setpagedevice"
*BRMediaType BOND/Bond Paper: "<</MediaType (BOND)>>setpagedevice"
*BRMediaType Env/Envelopes: "<</MediaType (ENVELOPES)>>setpagedevice"
*BRMediaType EnvThick/Env. Thick: "<</MediaType (ENVTHICK)>>setpagedevice"
*BRMediaType EnvThin/Env. Thin: "<</MediaType (ENVTHIN)>>setpagedevice"
*BRMediaType Recycled/Recycled Paper: "<</MediaType (RECYCLED)>>setpagedevice"
*BRMediaType Label/Label: "<</MediaType (LABEL)>>setpagedevice"
*BRMediaType Glossy/Glossy Paper: "<</MediaType (GLOSSY)>>setpagedevice"
*CloseUI: *BRMediaType
*OpenUI *InputSlot: PickOne
*OrderDependency: 29 AnySetup *InputSlot
*DefaultInputSlot: AutoSelect
*InputSlot AutoSelect/Auto Select: "<</ManualFeed false /BRTraysw true >> setpagedevice"
*InputSlot Tray1/Tray1: "<</ManualFeed false /BRTraysw false /BRFeeder 0>> setpagedevice"
*InputSlot Tray2/Tray2: "<</ManualFeed false /BRTraysw false /BRFeeder 1>> setpagedevice"
*InputSlot MPTray/MP Tray: "<</ManualFeed false /BRTraysw false /BRFeeder 4>> setpagedevice"
*CloseUI: *InputSlot
*RequiresPageRegion All:True
*OpenUI *ManualFeed/Manual Feed: Boolean
*OrderDependency: 19 AnySetup *ManualFeed
*DefaultManualFeed: False
*ManualFeed True: "<</ManualFeed true>> setpagedevice"
*ManualFeed False: "<</ManualFeed false>> setpagedevice"
*CloseUI: *ManualFeed
*%=== Duplex ================================
*OpenUI *Duplex: PickOne
*OrderDependency: 25 AnySetup *Duplex
*DefaultDuplex: None
*Duplex DuplexTumble: "<</Duplex true /Tumble true>>setpagedevice"
*Duplex DuplexNoTumble: "<</Duplex true /Tumble false>>setpagedevice"
*Duplex None: "<</Duplex false /Tumble false>>setpagedevice"
*CloseUI: *Duplex
*%=== Output Bin =============================
*DefaultOutputBin: OnlyOne
*% === Collate ==========
*%=== JobHold ================================
*OpenUI *BRJobHold/Secure Print: PickOne
*OrderDependency: 21 AnySetup *BRJobHold
*DefaultBRJobHold: None
*BRJobHold None/Off: "<</BRHold 0>>setpagedevice"
*BRJobHold Private/On: "<</BRHold 2 /BRHoldType 1>>setpagedevice"
*CloseUI: *BRJobHold
*OpenUI *BRJobPIN/Password: PickOne
*OrderDependency: 22 AnySetup *BRJobPIN
*DefaultBRJobPIN: HoldKey0
*BRJobPIN HoldKey0/0000: "<</BRHoldKey 0>> setpagedevice"
*BRJobPIN HoldKey1/1002: "<</BRHoldKey 1002>> setpagedevice"
*BRJobPIN HoldKey2/2833: "<</BRHoldKey 2833>> setpagedevice"
*BRJobPIN HoldKey3/3410: "<</BRHoldKey 3410>> setpagedevice"
*BRJobPIN HoldKey4/4791: "<</BRHoldKey 4791>> setpagedevice"
*BRJobPIN HoldKey5/0052: "<</BRHoldKey 0052>> setpagedevice"
*BRJobPIN HoldKey6/9612: "<</BRHoldKey 9612>> setpagedevice"
*BRJobPIN HoldKey7/0438: "<</BRHoldKey 0438>> setpagedevice"
*BRJobPIN HoldKey8/7328: "<</BRHoldKey 7328>> setpagedevice"
*BRJobPIN HoldKey9/0001: "<</BRHoldKey 0001>> setpagedevice"
*CloseUI: *BRJobPIN
*OpenUI *BRUser/User Name: PickOne
*OrderDependency: 91 AnySetup *BRUser
*DefaultBRUser: UserSystem
*BRUser UserSystem/System Name: "
"
*End
*CloseUI: *BRUser
*OpenUI *BRJobName/Job Name: PickOne
*OrderDependency: 92 AnySetup *BRJobName
*DefaultBRJobName: JobNameSystem
*BRJobName JobNameSystem/System Name: ""
*BRJobName JobName1/1: "%%BRTitle: 1
"
*End
*BRJobName JobName2/2: "%%BRTitle: 2
"
*End
*BRJobName JobName3/3: "%%BRTitle: 3
"
*End
*BRJobName JobName4/4: "%%BRTitle: 4
"
*End
*BRJobName JobName5/5: "%%BRTitle: 5
"
*End
*BRJobName JobName6/6: "%%BRTitle: 6
"
*End
*BRJobName JobName7/7: "%%BRTitle: 7
"
*End
*BRJobName JobName8/8: "%%BRTitle: 8
"
*End
*BRJobName JobName9/9: "%%BRTitle: 9
"
*End
*CloseUI: *BRJobName
*OpenUI *TonerSaveMode/Toner Save: Boolean
*DefaultTonerSaveMode: False
*OrderDependency: 10 AnySetup *TonerSaveMode
*TonerSaveMode False/Off: "
statusdict/tonersave known{statusdict begin false tonersave end}if
"
*End
*TonerSaveMode True/On: "
statusdict/tonersave known{statusdict begin true tonersave end}if
"
*End
*CloseUI: *TonerSaveMode
*OpenUI *Sleep/Sleep Time [Min.]: PickOne
*DefaultSleep: PrinterDefault
*OrderDependency: 10 AnySetup *Sleep
*Sleep PrinterDefault/Printer Default: ""
*Sleep 2minutes/2: "statusdict/powersavetime known{statusdict begin 2 powersavetime end}if"
*Sleep 10minutes/10: "statusdict/powersavetime known{statusdict begin 10 powersavetime end}if"
*Sleep 30minutes/30: "statusdict/powersavetime known{statusdict begin 30 powersavetime end}if"
*CloseUI: *Sleep
*%==== BR-Script Color Original UI ==================================
*OpenUI *BRPrintQuality/Colour/Mono: PickOne
*OrderDependency: 15 AnySetup *BRPrintQuality
*DefaultBRPrintQuality: Auto
*BRPrintQuality Auto/Auto: "
<</BRProcessColor 4 /BRHrc 0>>setpagedevice
<</BRColorAdapt true>>setpagedevice
<</BRRenderMode false>>setpagedevice"
*BRPrintQuality Color/Colour: "
<</BRProcessColor 4 /BRHrc 0>>setpagedevice
<</BRColorAdapt false>>setpagedevice
<</BRRenderMode false>>setpagedevice"
*BRPrintQuality Black/Mono: "
<</BRProcessColor 1>>setpagedevice
<</BRColorAdapt false>>setpagedevice
<</BRRenderMode true>>setpagedevice"
*?BRPrintQuality: "
save
currentpagedevice /BRProcessColor get 1 eq
{(Black)}{(Color)}ifelse
= flush
restore
"
*End
*CloseUI: *BRPrintQuality
*% Color Mode Information ===============
*OpenUI *BRColorMode/Colour Mode: PickOne
*OrderDependency: 131.0 AnySetup *BRColorMode
*DefaultBRColorMode: Normal
*BRColorMode Normal/Normal: "
<</UseCIEColor true>>setpagedevice
<</BRColorMode 0>>setpagedevice
"
*End
*BRColorMode Vivid/Vivid: "
<</UseCIEColor true>>setpagedevice
<</BRColorMode 1>>setpagedevice
"
*End
*BRColorMode None/None: "
<</UseCIEColor false>>setpagedevice
"
*End
*CloseUI: *BRColorMode
*% Improve Gray Color Information ===============
*OpenUI *BRImprovedGray/Improve Grey Colour: PickOne
*OrderDependency: 132.0 AnySetup *BRImprovedGray
*DefaultBRImprovedGray: True
*BRImprovedGray True/On: "
<</BRImprovedGray true>>setpagedevice
"
*End
*BRImprovedGray False/Off: "
<</BRImprovedGray false>>setpagedevice
"
*End
*CloseUI: *BRImprovedGray
*% UCRGCR Information ===============
*OpenUI *UCRGCRForImage/Enhance Black Printing: Boolean
*OrderDependency: 133 AnySetup *ScreenLock
*DefaultUCRGCRForImage: False
*UCRGCRForImage False/Off: "
statusdict begin false ucrgcrforimage end
"
*End
*UCRGCRForImage True/On: "
statusdict begin true ucrgcrforimage end
"
*End
*CloseUI: *UCRGCRForImage
*% Halftone Screen Lock Information ===============
*OpenUI *ScreenLock/Halftone Screen Lock: Boolean
*OrderDependency: 90 AnySetup *ScreenLock
*DefaultScreenLock: True
*ScreenLock True/On: "
<</HalftoneMode 1>>setuserparams
"
*End
*ScreenLock False/Off: "
<</HalftoneMode 0>>setuserparams
"
*End
*CloseUI: *ScreenLock
*% Reduced Image ===============
*OpenUI *BRReducedImage/High Quality Image Printing: Boolean
*OrderDependency: 131.0 AnySetup *BRReducedImage
*DefaultBRReducedImage: False
*BRReducedImage False/Off: "
<</BRReduceImage true>>setpagedevice
"
*End
*BRReducedImage True/On: "
<</BRReduceImage false>>setpagedevice
"
*End
*CloseUI: *BRReducedImage
*% Improve Print Output ===============
*OpenUI *ImprovePrintOutput/Improve Print Output: PickOne
*OrderDependency: 135.0 AnySetup *ImprovePrintOutput
*DefaultImprovePrintOutput: None
*ImprovePrintOutput None/Off: "
<</BRReducePaperCurl false /BRImproveTonerFixing false>>setpagedevice
"
*End
*ImprovePrintOutput ReducePaperCurl/Reduce Paper Curl: "
<</BRReducePaperCurl true /BRImproveTonerFixing false>>setpagedevice
"
*End
*ImprovePrintOutput ImproveTonerFixing/Improve Toner Fixing: "
<</BRReducePaperCurl false /BRImproveTonerFixing true>>setpagedevice
"
*End
*CloseUI: *ImprovePrintOutput
*%==== 5.17 Gray Levels and Halftoninig ========================
*AccurateScreenSupport: False
*ScreenFreq: "60.0"
*ScreenAngle: "0.0"
*DefaultScreenProc: Dot
*ScreenProc Dot: "{1.0 add 180 mul 1 add sin 0.001 add exch 1.0 add 180 mul 2 add sin mul}"
*DefaultTransfer: Null
*Transfer Null: "{}"
*Transfer Null.Inverse: "{1 exch sub}"
*%==== 5.18 Color Issues =======================================
*% BlackSubstitution -> Original UI
*%==== 5.19 Color Separation Keywords ==========================
*DefaultColorSep: ProcessBlack
*ColorSepScreenFreq ProcessBlack.71lpi.600dpi/71 lpi / 600 dpi: "70.7107"
*ColorSepScreenFreq CustomColor.71lpi.600dpi/71 lpi / 600 dpi: "70.7107"
*ColorSepScreenFreq ProcessCyan.71lpi.600dpi/71 lpi / 600 dpi: "63.2456"
*ColorSepScreenFreq ProcessMagenta.71lpi.600dpi/71 lpi / 600 dpi: "63.2456"
*ColorSepScreenFreq ProcessYellow.71lpi.600dpi/71 lpi / 600 dpi: "66.6667"
*ColorSepScreenFreq ProcessBlack.60lpi.300dpi/60 lpi / 300 dpi: "60"
*ColorSepScreenFreq CustomColor.60lpi.300dpi/60 lpi / 300 dpi: "60"
*ColorSepScreenFreq ProcessCyan.60lpi.300dpi/60 lpi / 300 dpi: "60"
*ColorSepScreenFreq ProcessMagenta.60lpi.300dpi/60 lpi / 300 dpi: "60"
*ColorSepScreenFreq ProcessYellow.60lpi.300dpi/60 lpi / 300 dpi: "60"
*ColorSepScreenFreq ProcessBlack.53lpi.300dpi/53 lpi / 300 dpi: "53.033"
*ColorSepScreenFreq CustomColor.53lpi.300dpi/53 lpi / 300 dpi: "53.033"
*ColorSepScreenFreq ProcessCyan.53lpi.300dpi/53 lpi / 300 dpi: "47.4342"
*ColorSepScreenFreq ProcessMagenta.53lpi.300dpi/53 lpi / 300 dpi:"47.4342"
*ColorSepScreenFreq ProcessYellow.53lpi.300dpi/53 lpi / 300 dpi: "50.0"
*ColorSepScreenAngle ProcessBlack.71lpi.600dpi/71 lpi / 600 dpi: "45.0"
*ColorSepScreenAngle CustomColor.71lpi.600dpi/71 lpi / 600 dpi: "45.0"
*ColorSepScreenAngle ProcessCyan.71lpi.600dpi/71 lpi / 600 dpi: "71.5651"
*ColorSepScreenAngle ProcessMagenta.71lpi.600dpi/71 lpi / 600 dpi: "18.4349"
*ColorSepScreenAngle ProcessYellow.71lpi.600dpi/71 lpi / 600 dpi: "0.0"
*ColorSepScreenAngle ProcessBlack.60lpi.300dpi/60 lpi / 300 dpi: "45"
*ColorSepScreenAngle CustomColor.60lpi.300dpi/60 lpi / 300 dpi: "45"
*ColorSepScreenAngle ProcessCyan.60lpi.300dpi/60 lpi / 300 dpi: "15"
*ColorSepScreenAngle ProcessMagenta.60lpi.300dpi/60 lpi / 300 dpi: "75"
*ColorSepScreenAngle ProcessYellow.60lpi.300dpi/60 lpi / 300 dpi: "0"
*ColorSepScreenAngle ProcessBlack.53lpi.300dpi/53 lpi / 300 dpi: "45.0"
*ColorSepScreenAngle CustomColor.53lpi.300dpi/53 lpi / 300 dpi: "45.0"
*ColorSepScreenAngle ProcessCyan.53lpi.300dpi/53 lpi / 300 dpi: "71.5651"
*ColorSepScreenAngle ProcessMagenta.53lpi.300dpi/53 lpi / 300 dpi: "18.4349"
*ColorSepScreenAngle ProcessYellow.53lpi.300dpi/53 lpi / 300 dpi: "0.0"
*End
*InkName: ProcessBlack/Process Black
*InkName: CustomColor/Custom Color
*InkName: ProcessCyan/Process Cyan
*InkName: ProcessMagenta/Process Magenta
*InkName: ProcessYellow/Process Yellow
*%==== 5.20 Font Related Keywords ==============================
*DefaultFont: Courier
*Font AvantGarde-Book: Standard "(001.006S)" Standard ROM
*Font AvantGarde-BookOblique: Standard "(001.006S)" Standard ROM
*Font AvantGarde-Demi: Standard "(001.007S)" Standard ROM
*Font AvantGarde-DemiOblique: Standard "(001.007S)" Standard ROM
*Font Bookman-Demi: Standard "(001.004S)" Standard ROM
*Font Bookman-DemiItalic: Standard "(001.004S)" Standard ROM
*Font Bookman-Light: Standard "(001.004S)" Standard ROM
*Font Bookman-LightItalic: Standard "(001.004S)" Standard ROM
*Font Courier: Standard "(002.004S)" Standard ROM
*Font Courier-Bold: Standard "(002.004S)" Standard ROM
*Font Courier-BoldOblique: Standard "(002.004S)" Standard ROM
*Font Courier-Oblique: Standard "(002.004S)" Standard ROM
*Font Helvetica: Standard "(001.006S)" Standard ROM
*Font Helvetica-Bold: Standard "(001.007S)" Standard ROM
*Font Helvetica-BoldOblique: Standard "(001.007S)" Standard ROM
*Font Helvetica-Narrow: Standard "(001.006S)" Standard ROM
*Font Helvetica-Narrow-Bold: Standard "(001.007S)" Standard ROM
*Font Helvetica-Narrow-BoldOblique: Standard "(001.007S)" Standard ROM
*Font Helvetica-Narrow-Oblique: Standard "(001.006S)" Standard ROM
*Font Helvetica-Oblique: Standard "(001.006S)" Standard ROM
*Font NewCenturySchlbk-Bold: Standard "(001.009S)" Standard ROM
*Font NewCenturySchlbk-BoldItalic: Standard "(001.007S)" Standard ROM
*Font NewCenturySchlbk-Italic: Standard "(001.006S)" Standard ROM
*Font NewCenturySchlbk-Roman: Standard "(001.007S)" Standard ROM
*Font Palatino-Bold: Standard "(001.005S)" Standard ROM
*Font Palatino-BoldItalic: Standard "(001.005S)" Standard ROM
*Font Palatino-Italic: Standard "(001.005S)" Standard ROM
*Font Palatino-Roman: Standard "(001.005S)" Standard ROM
*Font Times-Bold: Standard "(001.007S)" Standard ROM
*Font Times-BoldItalic: Standard "(001.009S)" Standard ROM
*Font Times-Italic: Standard "(001.007S)" Standard ROM
*Font Times-Roman: Standard "(001.007S)" Standard ROM
*Font ZapfChancery-MediumItalic: Standard "(001.007S)" Standard ROM
*Font ZapfDingbats: Special "(001.004S)" Special ROM
*Font Symbol: Special "(001.007S)" Special ROM
*Font Alaska: Standard "(001.005)" Standard ROM
*Font AlaskaExtrabold: Standard "(001.005)" Standard ROM
*Font AntiqueOakland: Standard "(001.005)" Standard ROM
*Font AntiqueOakland-Bold: Standard "(001.005)" Standard ROM
*Font AntiqueOakland-Oblique: Standard "(001.005)" Standard ROM
*Font ClevelandCondensed: Standard "(001.005)" Standard ROM
*Font Connecticut: Standard "(001.005)" Standard ROM
*Font Guatemala-Antique: Standard "(001.005)" Standard ROM
*Font Guatemala-Bold: Standard "(001.005)" Standard ROM
*Font Guatemala-Italic: Standard "(001.005)" Standard ROM
*Font Guatemala-BoldItalic: Standard "(001.005)" Standard ROM
*Font LetterGothic: Standard "(001.005)" Standard ROM
*Font LetterGothic-Bold: Standard "(001.005)" Standard ROM
*Font LetterGothic-Oblique: Standard "(001.005)" Standard ROM
*Font Maryland: Standard "(001.005)" Standard ROM
*Font Oklahoma: Standard "(001.005)" Standard ROM
*Font Oklahoma-Bold: Standard "(001.005)" Standard ROM
*Font Oklahoma-Oblique: Standard "(001.005)" Standard ROM
*Font Oklahoma-BoldOblique: Standard "(001.005)" Standard ROM
*Font Utah: Standard "(001.005)" Standard ROM
*Font Utah-Bold: Standard "(001.005)" Standard ROM
*Font Utah-Oblique: Standard "(001.005)" Standard ROM
*Font Utah-BoldOblique: Standard "(001.005)" Standard ROM
*Font UtahCondensed: Standard "(001.005)" Standard ROM
*Font UtahCondensed-Bold: Standard "(001.005)" Standard ROM
*Font UtahCondensed-Oblique: Standard "(001.004)" Standard ROM
*Font UtahCondensed-BoldOblique: Standard "(001.005)" Standard ROM
*Font BermudaScript: Standard "(001.005)" Standard ROM
*Font Germany: Standard "(001.005)" Standard ROM
*Font SanDiego: Standard "(001.005)" Standard ROM
*Font US-Roman: Standard "(001.005)" Standard ROM
*?FontQuery: "
save
count 1 gt
{exch dup dup
=string cvs (/) print print (:) print
FontDirectory exch known
{pop(Yes)}
{(fonts/)AppendName exch pop mark exch
{}=string filenameforall counttomark
0 gt
{cleartomark(Yes)}
{cleartomark(No)}ifelse
}ifelse
=
}if
(*) = flush
restore
"
*End
*?FontList: "
save
FontDirectory{pop ==}forall
(fonts/*)
{dup length 6 sub 6 exch getinterval cvn ==
}=string filenameforall
(*) = flush
restore
"
*End
*%==== 5.21 Printer Messages ===================================
*%
*% Printer Message
*%
*PrinterError: "service call"
*PrinterError: "cover open"
*PrinterError: "end of ink"
*PrinterError: "out of maintenance paper"
*PrinterError: "out of paper"
*PrinterError: "paper jam"
*PrinterError: "manual feed time out"
*PrinterError: "load paper letter size"
*PrinterError: "load paper legal size"
*PrinterError: "load paper B5 size"
*PrinterError: "load paper A4 size"
*PrinterError: "offline"
*Status: "idle"
*Status: "busy"
*Status: "waiting"
*Status: "printing"
*Status: "warming up"
*Status: "PrinterError: service call"
*Status: "PrinterError: cover open"
*Status: "PrinterError: end of ink"
*Status: "PrinterError: out of paper"
*Status: "PrinterError: paper jam"
*Status: "PrinterError: manual feed time out"
*Status: "PrinterError: load paper letter size"
*Status: "PrinterError: load paper legal size"
*Status: "PrinterError: load paper B5 size"
*Status: "PrinterError: load paper A4 size"
*Status: "PrinterError: offline"
*% Input Sources (format: %%[ status: <stat>; source: <one of these> ]%% )
*Source: "Serial"
*Source: "Parallel"
*Source: "EtherTalk"
*Source: "LPR"
*Source: "PrintServer"
*Source: "Internal"
*Message: "%%[ exitserver: permanent state may be changed ]%%"
*Message: "%%[ Flushing: rest of job (to end-of-file) will be ignored ]%%"
*Message: "\FontName\ not found, using BR-03B."
*%==== 5.22 System Management ==================================
*Password: "0"
*ExitServer: "
serverdict begin 0 exitserver
"
*End
*Reset: "
clear cleardictstack
serverdict begin 0 exitserver
systemdict /quit get exec
"
*End
+41
View File
@@ -0,0 +1,41 @@
# BR-Script3 PPD — Brother HL-4150CDN
`BR4150_2.PPD` is Brother's official **BR-Script3** (PostScript 3) PPD for the
HL-4150CDN.
## Provenance
Extracted from the vendor Windows driver in `../Windows/`:
```
Y10B_C1-ps-win8-64-103-en.EXE (ZIP self-extracting archive)
└── eng/BR4150_2.PPD
```
```sh
unzip -j "Y10B_C1-ps-win8-64-103-en.EXE" "eng/BR4150_2.PPD"
```
The archive also contains PPDs for the related BR4140 and BR4570 models; only
the HL-4150CDN PPD is used here. Line endings were normalised from CRLF to LF.
## Why this file
The HL-4150CDN emulates PCL6 and BR-Script3 (PostScript 3). This PPD encodes
every device setting as PostScript `setpagedevice`, for example:
| PPD option | Emitted PostScript |
| --- | --- |
| `InputSlot Tray2` | `<</ManualFeed false /BRTraysw false /BRFeeder 1>> setpagedevice` |
| `InputSlot MPTray` | `<</ManualFeed false /BRTraysw false /BRFeeder 4>> setpagedevice` |
| `Duplex DuplexNoTumble` | `<</Duplex true /Tumble false>>setpagedevice` |
| `BRPrintQuality Black` | `<</BRProcessColor 1>>… <</BRRenderMode true>>setpagedevice` |
| `BRColorMode Normal` | `<</UseCIEColor true>>… <</BRColorMode 0>>setpagedevice` |
| `BRMediaType Recycled` | `<</MediaType (RECYCLED)>>setpagedevice` |
CUPS's `pstops` filter injects the selected option code, and the PPD's
`*JCLBegin` / `*JCLToPSInterpreter` / `*JCLEnd` entries wrap the job in PJL.
This lets the HL-4150CDN be driven with a plain PostScript queue, so the
container does **not** need Brother's 32-bit Linux CUPS wrapper/filter
(`brlpdwrapperhl4150cdn`) or its Ghostscript rasterisation step.
+15 -8
View File
@@ -5,10 +5,15 @@
# the Brother HL-4150CDN queue if it does not exist yet. The CUPS daemon is # the Brother HL-4150CDN queue if it does not exist yet. The CUPS daemon is
# kept in the foreground so the container lives as long as the print server. # kept in the foreground so the container lives as long as the print server.
# #
# The queue uses Brother's BR-Script3 (PostScript 3) PPD and, by default,
# sends jobs to the printer over raw AppSocket (socket://<ip>:9100). CUPS
# converts client documents to PostScript and the PPD turns device options
# (tray, duplex, colour, ...) into PostScript "setpagedevice" instructions.
#
# Configuration (all optional, via environment): # Configuration (all optional, via environment):
# PRINTER_IP IP address / host name of the network printer. # PRINTER_IP IP address / host name of the network printer.
# PRINTER_URI Full device URI; overrides PRINTER_IP when set. # PRINTER_URI Full device URI; overrides PRINTER_IP when set.
# PRINTER_PROTOCOL lpd (default), socket or ipp - used with PRINTER_IP. # PRINTER_PROTOCOL socket (default), lpd or ipp - used with PRINTER_IP.
# PRINTER_NAME CUPS queue name and advertised (DNS-SD) name. # PRINTER_NAME CUPS queue name and advertised (DNS-SD) name.
# PRINTER_DESCRIPTION CUPS Description (lpadmin -D) shown in the web UI. # PRINTER_DESCRIPTION CUPS Description (lpadmin -D) shown in the web UI.
# PPD_FILE PPD used for the queue. # PPD_FILE PPD used for the queue.
@@ -17,28 +22,30 @@ set -eu
PRINTER_NAME="${PRINTER_NAME:-HL4150CDN}" PRINTER_NAME="${PRINTER_NAME:-HL4150CDN}"
PRINTER_IP="${PRINTER_IP:-}" PRINTER_IP="${PRINTER_IP:-}"
PRINTER_URI="${PRINTER_URI:-}" PRINTER_URI="${PRINTER_URI:-}"
PRINTER_PROTOCOL="${PRINTER_PROTOCOL:-lpd}" PRINTER_PROTOCOL="${PRINTER_PROTOCOL:-socket}"
PRINTER_DESCRIPTION="${PRINTER_DESCRIPTION:-}" PRINTER_DESCRIPTION="${PRINTER_DESCRIPTION:-}"
PPD_FILE="${PPD_FILE:-/usr/share/cups/model/brhl4150cdn.ppd}" PPD_FILE="${PPD_FILE:-/usr/share/cups/model/BR4150_2.PPD}"
LOG_PREFIX="[entrypoint]" LOG_PREFIX="[entrypoint]"
log() { echo "${LOG_PREFIX} $*"; } log() { echo "${LOG_PREFIX} $*"; }
# Build a device URI from PRINTER_IP unless an explicit PRINTER_URI is given. # Build a device URI from PRINTER_IP unless an explicit PRINTER_URI is given.
# Raw AppSocket is the default: the HL-4150CDN accepts PostScript directly on
# port 9100 (its BR-Script3 interpreter auto-detects the job language).
if [ -z "${PRINTER_URI}" ] && [ -n "${PRINTER_IP}" ]; then if [ -z "${PRINTER_URI}" ] && [ -n "${PRINTER_IP}" ]; then
case "${PRINTER_PROTOCOL}" in case "${PRINTER_PROTOCOL}" in
lpd)
PRINTER_URI="lpd://${PRINTER_IP}/binary_p1"
;;
socket) socket)
PRINTER_URI="socket://${PRINTER_IP}:9100" PRINTER_URI="socket://${PRINTER_IP}:9100"
;; ;;
lpd)
PRINTER_URI="lpd://${PRINTER_IP}/binary_p1"
;;
ipp) ipp)
PRINTER_URI="ipp://${PRINTER_IP}/ipp/print" PRINTER_URI="ipp://${PRINTER_IP}/ipp/print"
;; ;;
*) *)
log "unknown PRINTER_PROTOCOL '${PRINTER_PROTOCOL}', defaulting to lpd" log "unknown PRINTER_PROTOCOL '${PRINTER_PROTOCOL}', defaulting to socket"
PRINTER_URI="lpd://${PRINTER_IP}/binary_p1" PRINTER_URI="socket://${PRINTER_IP}:9100"
;; ;;
esac esac
fi fi
@@ -2,61 +2,104 @@
## Context ## Context
See proposal.md for motivation - we need to create a Podman container that runs a CUPS print server for Brother HL-4150CDN. The repo contains the Brother driver packages in `assets/Brother HL-4150CDN/`: See proposal.md. We need a Podman container that runs CUPS for the Brother
- `lpr-driver/hl4150cdnlpr-1.1.1-5.i386.deb` HL-4150CDN network printer and shares it over IPP/AirPrint.
- `cupswrapper/hl4150cdncupswrapper-1.1.1-5.i386.deb`
- `installer/linux-brprinter-installer-2.2.6-0.gz` (reference only; we will NOT run it in the build - it is interactive and downloads from the network)
Key observations: Facts established while exploring the device at `192.168.100.7`:
- Brother drivers are i386 binaries (32-bit ELF). Container needs 32-bit runtime libraries.
- CUPS wrapper + LPR packages provide PPD, filters, and helper binaries. - The printer is a Brother HL-4150CDN (`Ver.1.22`) with PCL6 and **BR-Script3
- AirPrint requires CUPS + Avahi/mDNS (DNS-SD). (PostScript 3)** emulation — `@PJL INFO CONFIG` lists `POSTSCRIPT`.
- Brother's cups wrapper installs files to /usr/local/Brother/ and may need symlinks into CUPS directories. - Open services: `:9100` (raw/AppSocket), `:515` (LPR/LPD), `:631` (IPP/IPPS)
and `:80` (Brother web UI). It has one paper cassette plus the MP tray.
- A raw PostScript job sent to `:9100` is interpreted by the printer, and a full
CUPS job with `Duplex=DuplexNoTumble BRPrintQuality=Color` printed correctly
(duplex, colour).
An earlier iteration used Brother's Linux packages. That vendor CUPS chain is
broken in `debian:bookworm-slim`: `filterhl4150cdn` needs `file` (and `a2ps` as
a fallback), which are absent, so the filter exits 1 and emits zero bytes. That
chain also rasterises locally (Ghostscript → `ppmraw` → `brhl4150cdnfilter`) and
stores per-queue options in a single global file (`brhl4150cdnrc`), which is
heavy and racy. The packages have since been removed from the repository.
Crucially, the Brother **vendor** PPD (`brhl4150cdn.ppd`) cannot be used for
direct PostScript because its option values are blank (`" "`); all
option handling lives in the vendor filter. Brother's **BR-Script3 PPD**, in
contrast, encodes every option as PostScript `setpagedevice`.
## Goals / Non-Goals ## Goals / Non-Goals
**Goals:** **Goals:**
- Create a Containerfile that builds a working image for Podman - Build a working CUPS image for Podman with no 32-bit dependencies.
- Install and configure Brother HL-4150CDN drivers - Drive the printer with its native PostScript (BR-Script3) interpreter.
- Share printer via IPP with AirPrint discovery - Preserve the hardware options the user cares about: paper tray, duplex and
- Expose ports 631 (CUPS/IPP) and 5353/udp (mDNS) colour/mono (plus the other options the PPD exposes).
- Make it easy to run with podman - Share the queue over IPP and advertise it via AirPrint.
- Keep the printer address/name runtime-configurable.
**Non-Goals:** **Non-Goals:**
- Managing multiple printers - Managing multiple printers.
- Custom SSL/TLS configuration for CUPS (use defaults or documented) - Sharing via SMB/Samba (Windows uses a client-side Brother driver).
- Persistent CUPS spool/state beyond basic setup - Persisting CUPS spool/state beyond the container lifecycle.
- TLS for the CUPS web interface.
## Decisions ## Decisions
### Base image ### Base image and packages
- Use Debian/Ubuntu (or similar) as base to handle .deb packages and 32-bit libs easily. Alternatively Alpine, but Alpine needs musl + 32-bit support can be more complex for prebuilt i386 ELF binaries from Brother. Debian stable is practical. Use `debian:bookworm-slim` with `cups`, `cups-client`, `cups-filters`,
`avahi-daemon`, `avahi-utils`, `libnss-mdns`, `dbus`, `ghostscript` and
`poppler-utils`. No `dpkg --add-architecture i386` and no Brother `.deb`
packages: the job is converted to PostScript in CUPS and interpreted by the
printer, so no vendor binary is needed.
### Driver installation _Alternative considered:_ keep Brother's Linux CUPS wrapper + LPR filter. It
- Use the local `.deb` packages from `assets/Brother HL-4150CDN/` (copied into the build context) and install with `dpkg -i --force-all`. No network download at build time for the driver itself. provides the same options but requires 32-bit libraries, Ghostscript
- Do not run the Brother installer script (`linux-brprinter-installer-2.2.6-0.gz`) in the build - it is interactive and downloads packages from download.brother.com. rasterisation and the missing `file`/`a2ps` tools, and it writes options to a
- Also need to install brcupsconfpt1 helper if needed - comes with cups wrapper. single global config file. Rejected.
- Run the cups wrapper install logic as per Brother installer (or manually create symlinks).
### CUPS + Avahi + DBus ### Print path: direct PostScript via the BR-Script3 PPD
- Install cups, avahi-daemon, dbus. Run dbus and avahi-daemon; start cupsd. Install Brother's official BR-Script3 PPD as
- Configure CUPS to allow remote access/sharing. For containerized setup, typically need to listen on all interfaces and configure sharing. `/usr/share/cups/model/BR4150_2.PPD` (committed at
`assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`, extracted from the vendor Windows
driver) and create the queue with it. CUPS's `pstops` filter reads the PPD and
injects the selected option code (e.g. `/BRFeeder`, `/Duplex`,
`/BRProcessColor`, `/MediaType`) into the job; the PPD's `*JCLBegin`,
`*JCLToPSInterpreter` and `*JCLEnd` entries wrap it in PJL. The result is
forwarded unchanged to the printer.
### Printer configuration A stock PostScript PPD (like CUPS's own `generic.ppd`) has no `*cupsFilter`
- Add printer via lpadmin using the Brother PPD. Point to network URI (e.g., ipp://PRINTER_IP/ipp or socket://PRINTER_IP:9100 - depends on printer; HL-4150CDN is network printer). either, and CUPS accepts such PPDs — the printer's native format is
- Enable printer sharing and default options. `application/vnd.cups-postscript`.
### Device URI
Use raw AppSocket as the default: `socket://<ip>:9100`. `lpd://<ip>/binary_p1`
and `ipp://…` remain available through `PRINTER_PROTOCOL`/`PRINTER_URI`.
### Client support
- macOS / iOS / iPadOS: AirPrint → CUPS. The queue advertises `image/urf`,
`image/pwg-raster`, `application/pdf` and `application/postscript`, with
`urf-supported = V1.4,CP1,W8,PQ4,SRGB24,RS600,DM1,FN3`, `sides-supported`
(one-sided/two-sided long/short edge) and `color-supported = true`.
- Linux: IPP / IPP Everywhere, or plain IPP with PDF/PostScript.
- Windows: client-side Brother BR-Script3 Windows driver, pointed at the
printer directly or at the shared queue.
### Runtime configuration ### Runtime configuration
- The printer endpoint and advertised name are supplied through environment variables rather than baked into the image, so the same image can be pointed at any HL-4150CDN: The printer endpoint and advertised name come from environment variables
- `PRINTER_IP` + `PRINTER_PROTOCOL` (lpd/socket/ipp) derive the device URI. (`PRINTER_IP`, `PRINTER_PROTOCOL`, `PRINTER_URI`, `PRINTER_NAME`,
- `PRINTER_URI` overrides the derived URI for full control. `PRINTER_DESCRIPTION`, `PPD_FILE`) rather than being baked into the image. The
- `PRINTER_NAME` sets the CUPS queue name and the DNS-SD/AirPrint advertised name. entrypoint derives the URI and runs `lpadmin` on startup, then shares the queue.
- `PRINTER_DESCRIPTION` sets the CUPS Description (Info) shown in the web UI.
- The entrypoint builds the URI and runs lpadmin at startup, then shares the queue.
## Risks / Trade-offs ## Risks / Trade-offs
- [Risk] Brother binaries are 32-bit only → require multiarch libs (libc6:i386, etc.). Increases image size slightly. - [Risk] The AirPrint path (URF → PDF → PostScript) relies on cups-filters'
- [Risk] Using .deb packages assumes glibc-based base. If we choose different base, need to ensure compatibility. `rastertopdf`; it was not exercised with a real URF job during exploration.
- [Risk] Avahi in container needs --net=host or proper mDNS setup. AirPrint discovery typically works better with host network mode; document this. macOS/iOS printing should be verified end to end.
- [Risk] CUPS state (printers.conf, etc.) should be persisted if we want config to survive restarts - may need volumes. - [Risk] Colour handling now relies on the printer's PostScript RIP rather than
Brother's host-side colour tables; output may differ slightly from the vendor
raster driver.
- [Risk] The committed PPD is a Windows PPD and contains no CUPS-specific keys.
CUPS accepts it as a PostScript PPD (verified for this CUPS version), but this
should be re-checked on CUPS upgrades.
- [Risk] Avahi needs host networking (or equivalent) to advertise mDNS.
- [Risk] CUPS state is not persisted; the queue is recreated on every start.
@@ -2,28 +2,56 @@
## Why ## Why
Provide a Podman container that runs CUPS and shares the Brother HL-4150CDN network printer as an AirPrint and IPP printer. Clients should be able to print without installing local printer drivers. Run a Podman container that shares the Brother HL-4150CDN network printer over
IPP/AirPrint, so clients on macOS, iOS/iPadOS, Linux and Windows can print.
The HL-4150CDN already emulates BR-Script3 (PostScript 3) and accepts PostScript
on its AppSocket/LPD ports, so the container can forward PostScript directly to
the printer instead of shipping Brother's 32-bit Linux CUPS wrapper plus
Ghostscript rasterisation. This removes the i386 dependency, the multiarch
runtime and the fragile vendor filter chain.
The previous approach (Brother Linux `.deb` packages) turned out not to work in
`debian:bookworm-slim`: the vendor filter `filterhl4150cdn` needs `file` (with
`a2ps` as a fallback), which are not installed, so it exits with an error and
produces no output. The official BR-Script3 PPD avoids that entire code path.
## What Changes ## What Changes
- Create a Containerfile for Podman (based on a Linux distro that supports CUPS and 32-bit binaries) - Create a Containerfile for Podman based on Debian stable running CUPS, Avahi
- Extract and install Brother driver files (from `assets/Brother HL-4150CDN/` - local .deb packages: `hl4150cdnlpr` and `hl4150cdncupswrapper`) needed for HL-4150CDN and D-Bus (no i386 multiarch).
- Configure CUPS to run in the container and share the network printer - Install Brother's official **BR-Script3 PPD** (committed under
- Enable mDNS/Avahi for AirPrint discovery `assets/Brother HL-4150CDN/ppd/`) so CUPS emits device options — paper source
- Provide minimal runtime configuration (ports 631, 5353/udp) and documentation for running with podman (tray), duplex and colour/mono, plus media type, print quality, toner save and
- Handle 32-bit dependencies required by Brother i386 binaries secure print — as PostScript `setpagedevice`.
- Point the queue at the printer with a raw AppSocket URI (`socket://<ip>:9100`)
by default.
- Convert incoming client formats (URF/Apple Raster, PWG Raster, PDF, PostScript)
to PostScript inside CUPS and pass them through to the printer's PostScript
interpreter.
- Share the queue over IPP and advertise it via mDNS/DNS-SD (Avahi/AirPrint).
- Keep runtime configuration (printer address, protocol, queue name) in
environment variables.
- Document the supported client matrix.
## Capabilities ## Capabilities
### New Capabilities ### New Capabilities
- `printserver/cups`: Containerized CUPS print server with AirPrint/IPP sharing and Brother HL-4150CDN driver support - `printserver/cups`: Containerised CUPS print server which shares the Brother
HL-4150CDN over IPP/AirPrint and prints by sending PostScript (BR-Script3)
directly to the printer.
### Modified Capabilities ### Modified Capabilities
None None
## Impact ## Impact
- New Containerfile (and possibly supporting files) in repository root - Containerfile plus supporting `cupsd.conf` and `entrypoint.sh` in the
- Uses Brother driver artifacts in `assets/Brother HL-4150CDN/` repository root.
- Runtime ports: CUPS (631), mDNS (5353/udp) for AirPrint - Uses `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`.
- Depends on Avahi/DBus, CUPS, and 32-bit compatibility libs for Brother binaries - Runtime ports: CUPS/IPP (631/tcp), mDNS/DNS-SD (5353/udp).
- No 32-bit runtime libraries; the image no longer depends on the host CPU
architecture.
- Windows clients install Brother's own BR-Script3 Windows driver client-side.
- The unused Brother Linux `.deb` packages previously under
`assets/Brother HL-4150CDN/` have been removed.
@@ -2,34 +2,69 @@
## Purpose ## Purpose
Provide a containerized CUPS print server that shares the Brother HL-4150CDN network printer as an AirPrint and IPP printer so clients can print without installing local printer drivers. Provide a containerized CUPS print server that shares the Brother HL-4150CDN
network printer as an AirPrint/IPP printer and prints by sending PostScript
directly to the printer, so clients can print without a server-side vendor
driver.
## ADDED Requirements ## ADDED Requirements
### Requirement: Container image builds with required dependencies ### Requirement: Container image builds with required dependencies
The container SHALL include CUPS, Avahi/mDNS, DBus, and required 32-bit runtime libraries to run Brother HL-4150CDN i386 binaries. The container SHALL include CUPS, cups-filters, Avahi/mDNS, D-Bus and the
conversion tools needed to turn client documents into PostScript, and SHALL NOT
require any 32-bit runtime libraries.
#### Scenario: Image contains CUPS #### Scenario: Image contains CUPS
- **WHEN** the image is built - **WHEN** the image is built
- **THEN** CUPS is installed and available at /usr/sbin/cupsd - **THEN** CUPS is installed and available at /usr/sbin/cupsd
#### Scenario: Image supports 32-bit Brother binaries #### Scenario: No 32-bit runtime required
- **WHEN** the image is built - **WHEN** the image is built
- **THEN** required 32-bit libraries are present for the Brother i386 filters - **THEN** the image contains no i386 multiarch libraries and no Brother vendor binaries
### Requirement: Brother HL-4150CDN driver is installed in container ### Requirement: Brother BR-Script3 PPD is installed
The container SHALL install the Brother HL-4150CDN CUPS wrapper, PPD, LPR/filter components from the provided driver artifacts. The container SHALL install Brother's official HL-4150CDN BR-Script3 PPD from
the committed asset so CUPS can emit device options as PostScript.
#### Scenario: Driver files present #### Scenario: PPD present
- **WHEN** the container image is built - **WHEN** the image is built
- **THEN** the HL-4150CDN PPD and Brother filters are installed in standard system locations - **THEN** the BR-Script3 PPD is present in the CUPS model directory
#### Scenario: CUPS recognizes HL-4150CDN #### Scenario: CUPS recognises the model
- **WHEN** CUPS starts with the driver installed - **WHEN** the queue is created with the PPD
- **THEN** CUPS is able to use the HL-4150CDN PPD - **THEN** CUPS reports the printer make and model as "Brother HL-4150CDN BR-Script3"
### Requirement: Hardware options are sent to the printer
The system SHALL translate the PPD's device options into PostScript
`setpagedevice` instructions so the printer's own hardware options are used.
#### Scenario: Paper source
- **WHEN** a job selects an input slot (auto select, a tray or the MP tray)
- **THEN** the emitted PostScript selects the corresponding paper source on the printer
#### Scenario: Duplex
- **WHEN** a job selects long-edge or short-edge two-sided printing
- **THEN** the emitted PostScript sets `/Duplex` and `/Tumble` accordingly
#### Scenario: Colour or mono
- **WHEN** a job selects colour or mono
- **THEN** the emitted PostScript sets the corresponding colour/mono device parameters
### Requirement: Jobs are printed via direct PostScript
The container SHALL forward the converted job as PostScript to the printer
without a server-side vendor filter or host-side rasterisation.
#### Scenario: Default device URI
- **WHEN** the container is started with a printer IP and no explicit URI
- **THEN** the queue is created with a raw AppSocket URI (`socket://<ip>:9100`)
#### Scenario: A job is printed
- **WHEN** a print job is submitted to the queue
- **THEN** the job is delivered to the printer as PostScript and printed by the printer's PostScript interpreter
### Requirement: Printer is shared and discoverable ### Requirement: Printer is shared and discoverable
The system SHALL share the Brother HL-4150CDN printer over IPP and make it discoverable via AirPrint (mDNS/DNS-SD) on the container network. The system SHALL share the queue over IPP and advertise it via AirPrint
(mDNS/DNS-SD).
#### Scenario: IPP printer is shared #### Scenario: IPP printer is shared
- **WHEN** CUPS runs in the container - **WHEN** CUPS runs in the container
@@ -37,7 +72,22 @@ The system SHALL share the Brother HL-4150CDN printer over IPP and make it disco
#### Scenario: AirPrint discovery #### Scenario: AirPrint discovery
- **WHEN** Avahi runs alongside CUPS - **WHEN** Avahi runs alongside CUPS
- **THEN** the printer is advertised via AirPrint so macOS/iOS clients can discover it without driver installation - **THEN** the printer is advertised via AirPrint with URF, sides and colour capabilities so macOS and iOS/iPadOS clients can discover it without a driver
### Requirement: Supported client platforms
The shared printer SHALL be usable from macOS, iOS/iPadOS, Linux and Windows.
#### Scenario: macOS and iOS/iPadOS
- **WHEN** a macOS or iOS/iPadOS client prints via AirPrint
- **THEN** the job is converted to PostScript and printed
#### Scenario: Linux
- **WHEN** a Linux client prints over IPP
- **THEN** the job is converted to PostScript and printed
#### Scenario: Windows
- **WHEN** a Windows client prints
- **THEN** it uses a client-side BR-Script3 driver against the printer or the shared queue
### Requirement: Runtime configuration is exposed ### Requirement: Runtime configuration is exposed
The container SHALL expose CUPS on port 631 and mDNS on UDP port 5353. The container SHALL expose CUPS on port 631 and mDNS on UDP port 5353.
@@ -50,13 +100,6 @@ The container SHALL expose CUPS on port 631 and mDNS on UDP port 5353.
- **WHEN** the container runs - **WHEN** the container runs
- **THEN** UDP port 5353 is available for AirPrint discovery - **THEN** UDP port 5353 is available for AirPrint discovery
### Requirement: No client drivers required
The shared printer SHALL be exposed in a way that client devices can print without installing vendor printer drivers.
#### Scenario: AirPrint compatibility
- **WHEN** a client discovers the printer via AirPrint
- **THEN** the client uses native IPP/AirPrint drivers
### Requirement: Printer endpoint and advertised name are configurable at runtime ### Requirement: Printer endpoint and advertised name are configurable at runtime
The container SHALL accept the network printer address and the advertised printer name through environment variables so the same image can target a different printer or name without rebuilding. The container SHALL accept the network printer address and the advertised printer name through environment variables so the same image can target a different printer or name without rebuilding.
@@ -66,7 +109,7 @@ The container SHALL accept the network printer address and the advertised printe
#### Scenario: Printer protocol is selected #### Scenario: Printer protocol is selected
- **WHEN** the container is started with `PRINTER_IP` and `PRINTER_PROTOCOL` - **WHEN** the container is started with `PRINTER_IP` and `PRINTER_PROTOCOL`
- **THEN** the device URI uses that protocol (lpd, socket or ipp) - **THEN** the device URI uses that protocol (socket, lpd or ipp), defaulting to socket
#### Scenario: Full URI override #### Scenario: Full URI override
- **WHEN** `PRINTER_URI` is set - **WHEN** `PRINTER_URI` is set
@@ -3,21 +3,31 @@
## 1. Repository initialization ## 1. Repository initialization
- [x] 1.1 Initialize jujutsu repository with `jj git init` in repo root and verify `.jj` directory exists - [x] 1.1 Initialize jujutsu repository with `jj git init` in repo root and verify `.jj` directory exists
## 2. Container build setup ## 2. BR-Script3 PostScript PPD asset
- [x] 2.1 Create Containerfile in repository root based on Debian/Ubuntu base image with multiarch support for i386 - [x] 2.1 Extract Brother's official HL-4150CDN BR-Script3 PPD (`eng/BR4150_2.PPD`) from the vendor Windows driver archive and commit it under `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`
- [x] 2.2 Install required system packages: cups, avahi-daemon, dbus, wget/curl, and 32-bit runtime libraries (libc6:i386, libstdc++6:i386, etc.) - [x] 2.2 Document the provenance and the option→`setpagedevice` mapping in `assets/Brother HL-4150CDN/ppd/README.md`
- [x] 2.3 Copy the local Brother driver packages (`assets/Brother HL-4150CDN/lpr-driver/hl4150cdnlpr-1.1.1-5.i386.deb` and `assets/Brother HL-4150CDN/cupswrapper/hl4150cdncupswrapper-1.1.1-5.i386.deb`) into the build context and install them in the container with `dpkg -i --force-all` (verify install reports success)
- [x] 2.4 Configure CUPS and Brother drivers (symlink PPD/filter files as needed, set up cupsd.conf for container use) and verify files are in correct locations
- [x] 2.5 Set up startup script to run dbus, avahi-daemon, and cupsd in the container
- [x] 2.6 Expose ports 631 (CUPS/IPP) and 5353/udp (mDNS) in Containerfile and verify ports are declared
## 3. Printer configuration ## 3. Container build
- [x] 3.1 Add logic/config to create and share the Brother HL-4150CDN printer (using lpadmin) with appropriate network URI and PPD; ensure printer is shared for network clients - [x] 3.1 Create Containerfile based on Debian stable with CUPS, cups-filters, Avahi, D-Bus, Ghostscript and Poppler (no i386 multiarch)
- [x] 3.2 Configure Avahi/CUPS for AirPrint advertisement and verify printer will be discoverable - [x] 3.2 Install the BR-Script3 PPD into the CUPS model directory in the Containerfile
- [x] 3.3 Add environment-based configuration for the printer address and advertised name (`PRINTER_IP`, `PRINTER_PROTOCOL`, `PRINTER_NAME`, `PRINTER_DESCRIPTION`; `PRINTER_URI` overrides) - [x] 3.3 Remove the Brother vendor `.deb` installation, i386 multiarch and the 32-bit loader setup from the Containerfile
- [x] 3.4 Keep cupsd.conf (listen on all interfaces, share printers, DNS-SD) and the required runtime directories
- [x] 3.5 Set up the startup script to run dbus, avahi-daemon and cupsd, and create the queue
- [x] 3.6 Expose ports 631/tcp and 5353/udp in the Containerfile
## 4. Documentation and testing ## 4. Printer configuration
- [x] 4.1 Create or update README with instructions for building and running the container with podman (including host network mode note for mDNS, volume mounts if needed) - [x] 4.1 Create the queue with the BR-Script3 PPD and a raw AppSocket URI by default (`socket://<ip>:9100`)
- [x] 4.2 Test container build with podman build and verify image builds successfully - [x] 4.2 Keep environment-based configuration (`PRINTER_IP`, `PRINTER_PROTOCOL`, `PRINTER_URI`, `PRINTER_NAME`, `PRINTER_DESCRIPTION`, `PPD_FILE`)
- [x] 4.3 Test container run and verify CUPS is accessible and printer is shared/discoverable (manual verification) - [x] 4.3 Share the queue and set it as default; verify AirPrint capabilities (URF, sides, colour)
- [x] 4.4 Verify `podman run` with `PRINTER_IP` and a custom `PRINTER_NAME` creates the queue at the derived URI and advertises that name
## 5. Documentation and testing
- [x] 5.1 Update README for the PostScript/BR-Script3 approach and the client matrix (macOS, iOS/iPadOS, Linux, Windows)
- [x] 5.2 Build the image with podman and verify it builds
- [x] 5.3 Run the container and verify CUPS is reachable and the queue is shared/discoverable
- [x] 5.4 Submit a job (colour + duplex) and verify it prints correctly
- [x] 5.5 Verify `PRINTER_IP`/`PRINTER_PROTOCOL`/`PRINTER_NAME` derive the expected queue URI and advertised name
## 6. Cleanup
- [x] 6.1 Add `.gitignore` for macOS metadata and stop tracking existing `.DS_Store` files
- [x] 6.2 Remove the unused Brother Linux vendor packages (`lpr-driver/`, `cupswrapper/`, `installer/`) from the repository
- [x] 6.3 Prune the obsolete `printserver:amd64` image, the test containers and scratch files