A working driver for the Canon LBP2900 (LASER SHOT / i-SENSYS LBP2900/2900B) on modern macOS — including Apple Silicon — where Canon ships no driver at all.
🇬🇧 English | 🇻🇳 Tiếng Việt
Works on Apple Silicon (M1/M2/M3/M4) and Intel Macs across modern macOS (Sonoma, Sequoia, Tahoe — macOS 14 / 15 / 26). If you were looking for a Canon 2900 Mac driver, Canon LBP2900 macOS driver, LBP-2900 / LBP2900B driver for Mac, or how to install the Canon LBP2900 on macOS / Apple Silicon — this is it. One command and you're printing.
The LBP2900 is a host-based (GDI) printer: it has no PostScript/PCL interpreter and only speaks Canon's proprietary CAPT protocol (Smart Compression Architecture / Hi-SCoA). Canon's official macOS packages only cover the LBP3000 and up, so the 2900 is left unsupported.
This project provides a CUPS filter (rastertocapt) that implements CAPT, plus a PPD describing the printer. It is built on the open-source captdriver project (GPLv3) with additional patches required to make the LBP2900 actually print on macOS (see The fix).
Status: verified working — prints real pages on macOS (Apple Silicon, arm64). Page-progress and out-of-paper reporting are integrated into the native macOS print queue.
- ✅ Printing (600 DPI, all standard paper sizes, plain/heavy/envelope media, toner save, manual duplex)
- ✅ Fully bidirectional CAPT over USB via the standard CUPS
usbbackend — no kext, no SIP changes - ✅ Live page progress in the macOS print queue (“Printing page N”)
- ✅ Out of paper status + notification; resumes when paper is reloaded
- ✅ Offline / disconnected reporting (handled by the CUPS USB backend)
⚠️ Not yet: distinguishing paper jam vs cover open (the underlying driver doesn’t decode those status bits — see Roadmap)
- macOS with CUPS (every macOS has it). Tested on macOS 26 (Tahoe-era), Apple Silicon.
- Apple Silicon (arm64): a prebuilt filter is bundled — nothing to compile.
- Intel (x86_64): no prebuilt binary is bundled; the installer builds from source automatically. You need Xcode Command Line Tools (
xcode-select --install) and autotools (brew install autoconf automake).
Plug in and power on the printer, then:
git clone https://github.com/duy12i1i7/canon-LBP2900-for-macOS.git
cd canon-LBP2900-for-macOS
./setup.shsetup.sh does everything — run it without sudo (it asks for your password
only when it needs admin rights):
- installs the CAPT filter into
/usr/libexec/cups/filter/(writable data volume; works with SIP enabled) and the PPD into/Library/Printers/PPDs/…, - detects the USB printer and creates a queue named
Canon_LBP2900, - sets up a self-healing LaunchDaemon so the driver survives macOS updates (see below),
- installs the menu-bar progress app.
If the printer isn’t connected yet, everything installs anyway — just re-run
./setup.sh once it’s plugged in to add the queue.
Prefer to install the pieces separately?
sudo ./install.sh # driver + queue + self-heal
cd menubar && ./install-menubar.sh # menu-bar app (no sudo)A major macOS update can wipe third-party CUPS filters out of /usr/libexec/cups/filter/. To make that a non-event, install.sh keeps a persistent copy of the filter + PPD in /Library/Application Support/CanonLBP2900/ (on the data volume, untouched by updates) and installs a LaunchDaemon com.lbp2900.heal that runs at every boot and re-installs the filter/PPD/queue automatically if they went missing. So after an OS update, the printer just keeps working — no reinstall needed. (Verified by simulating a wipe: the daemon restores the filter on the next run.)
Print from any app and pick Canon LBP2900, or from the terminal:
lpr -P Canon_LBP2900 some-file.pdf
lpstat -p Canon_LBP2900 # queue statusThere is no Canon-style floating status window — that’s a closed Windows-only app. Instead, this driver feeds status into the native macOS print queue window (System Settings ▸ Printers & Scanners ▸ Canon LBP2900 ▸ Open Print Queue, or the Dock icon while printing):
- Progress — “Printing page N” (
PAGE:messages) - Out of paper — a warning badge + notification (
STATE: +media-empty); reload paper and the job continues - Offline / not connected — reported by the CUPS USB backend when the cable is unplugged or the printer is off
The driver sends pages one at a time and waits for each to physically print before the next, and reports progress as it goes. The reliable ways to watch it:
-
Menu-bar app (recommended, no Terminal): a tiny native app that shows
🖨 2/3in the menu bar while printing. Seemenubar/—cd menubar && ./install-menubar.sh(no sudo). This exists because Apple's own “Printing N of M” widget is frozen for this printer (see the note below). -
Terminal (most precise): run
progress.sh:./progress.sh # prints e.g. job #12 "Report.xlsx": printed 4/10 pagesIt reads CUPS’
job-media-sheets-completed(driven by the driver’sPAGE:reports and verified to advance in real time). From the macOS print dialog the total is usually known, so you getprinted X / Y; a plainlpr file.txtmay only showprinted X. -
The pages themselves — one sheet ejects roughly every several seconds.
Note on macOS’ “Printing N of M” text — and why the driver can’t fix it. On modern macOS this counter stays frozen at “1 of M” for the LBP2900 (and any non-AirPrint / host-based CUPS printer). This was investigated thoroughly and it is not fixable from the driver, by design:
- The two CUPS job counters the filter does drive —
job-media-sheets-completedandjob-impressions-completed— were measured advancing correctly live (0→1→2→3) as each page prints.- Yet the Apple UI ignores them. It even shows the correct total “of 3” while the CUPS
job-impressionsattribute is unset — proving Apple’s print proxy reads its page count from the spool document on the PrintCore side, not from the CUPS job the driver updates. So there is no filter-side attribute that can move “N”.- Live per-page progress in that widget only works for AirPrint / IPP Everywhere printers, which report progress back over IPP. The LBP2900 is a raw USB CAPT/GDI device with no IPP, so it structurally can’t feed that widget.
The driver’s progress reporting is correct — use
progress.shfor an accurate live count, or just watch the pages. The frozen widget is a macOS platform limitation shared by all classic CUPS drivers.
Enable verbose logging and watch it while you print:
sudo cupsctl LogLevel=debug
tail -f /var/log/cups/error_log # lines tagged "CAPT:" are from this driver
sudo cupsctl LogLevel=warn # turn it back off afterwardsfilter failed— check the filter is present and executable:ls -l /usr/libexec/cups/filter/rastertocapt(should be-rwxr-xr-x root wheel). Re-runsudo ./install.shif missing.- Job stuck at “now printing” forever (desynced page counters) — this usually happens after you cancel a job mid-print: the cancelled job never sends a clean end-of-job, so the printer’s cumulative page counters drift and the next job waits forever. Fix:
cancel -a Canon_LBP2900, then power-cycle the printer (off ~10 s, on, wait for a steady green light) to reset the counters, and print again. This is a known captdriver behavior. - macOS auto-adds a “Generic/AirPrint” queue — the LBP2900 has no AirPrint; use the
Canon_LBP2900queue created by the installer (it has the correct PPD). - Blank or shifted output — pick the correct paper size (A4/Letter) in the print dialog; the printer needs ~5 mm minimum margins.
CUPS filter chain: app → PDF → cgpdftoraster → rastertocapt → usb backend → printer.
rastertocapt rasterizes each page into CAPT/Hi-SCoA compressed bands and streams them to the printer, using CUPS’ standard back-channel (cupsBackChannelRead) and side-channel (cupsSideChannelDoRequest) APIs for the bidirectional status handshake. That’s why it needs no kernel extension and no elevated privileges beyond sudo at install time.
Upstream captdriver registers the LBP2900 with a conditional status strategy (capt_get_xstatus / capt_wait_ready). That only fetches the extended printer status (CAPT command 0xA0A8) when the XSTATUS_CHNG flag is set — which this unit never sets. The per-page counters (page_decoding / page_out / page_completed) live only in the extended status record, so they were never refreshed, leaving stale/garbage values and hanging the end-of-page wait loops (the classic endlessly-looping 0xE0A0 status poll, captdriver#3).
The patch switches the LBP2900 to the same strategy the known-working LBP3010 uses — always read the extended status (capt_get_xstatus_only / capt_wait_xready_only). Once the counters are read correctly they converge (1/1/1/1) and the page prints. The same patch also adds the PAGE:/STATE: reporting described above. See patches/lbp2900-macos.patch.
This behaviour matches the reverse-engineered CAPT protocol spec (see captdriver/SPECS): the extended-status record (reply to 0xA0A8) carries the page counters at bytes 14–21, and paper-out is STATUS0 bit 1 / STATUS1 bit 14.
Prebuilt arm64 filter is under prebuilt/arm64/. To rebuild (e.g. for Intel or a universal binary), see docs/BUILD.md. In short:
cd captdriver
autoreconf -fi && ./configure
make CFLAGS="-D_DARWIN_C_SOURCE -std=gnu99 -O2" # -> src/rastertocaptThe captdriver/ tree here is upstream captdriver with the macOS/LBP2900 patch already applied, included both for one-command building and for GPLv3 source-availability compliance.
- Decode the cover-open / paper-jam status bits (STATUS2 bit 7 = “Problem” per the spec) to show distinct errors instead of a generic stall.
- Universal (arm64 + x86_64) prebuilt binary.
- captdriver by Moses Chong and contributors — the CAPT CUPS filter this is built on.
- The original CAPT reverse engineering by Alexey Galakhov, Nicolas Boichat, Benoit Bolsee and others (see
captdriver/AUTHORSandcaptdriver/SPECS). - macOS port, LBP2900 status-strategy fix, and native status reporting: this repository.
This is unofficial software, not endorsed by or affiliated with Canon Inc.
GNU General Public License v3 — see LICENSE. captdriver is GPLv3, and this derivative work (patches + built binary) is distributed under the same terms.