• Как я оживил LaserJet 1320 и Color LaserJet CP1025 на macOS 27 — разбор по логам CUPS
• “Filter failed” и «legacy USB class driver»: анатомия двух поломок печати на M1

Дано:
macOS 27 на M1, два древних принтера HP, одно и то же сообщение «ПО принтера несовместимо с этим устройством». Выглядит как один диагноз — «драйверов под ARM нет, покупай новый принтер». На деле это две совершенно разные поломки: одна лечится одной командой, вторая не лечится вообще и требует замены драйвера на open‑source. Ниже — разбор по логам CUPS, file, nm и strings, с рабочими решениями для обоих случаев.

Исходные данные

MacBook Air M1, macOS 27.0 (build 26A428). Два USB‑принтера:

  • HP LaserJet 1320 — лазерник 2004 года, умеет PCL 5e, PCL 6 и PostScript Level 2 emulation, то есть растрирует сам.

  • HP Color LaserJet CP1025 — host‑based, он же «GDI‑принтер»: своего интерпретатора нет, всю растеризацию делает компьютер и отдаёт готовый поток ZjStream.

Эта разница между ними и окажется ключевой.

Симптомы поначалу выглядели одинаково: принтер определяется,так как до этого были установлены пакеты драйверов (как бы для apple m), в диалоге печати виден, при отправке задания — либо «ПО несовместимо», либо задание молча повисает на паузе.

Единственная команда, с которой стоит начинать

tail -40 /var/log/cups/error_log

Всё, что пишет диалог печати в macOS, — это бесполезная обобщённая формулировка. Настоящая причина лежит в логе CUPS, и она в обоих случаях оказалась совершенно конкретной. Я потратил время на форумные советы («сбросьте систему печати», «поставьте HP Smart», “переустановите драйверы”) ровно потому, что не начал с этой команды.


Случай А. LaserJet 1320: не хватает Rosetta 2

Симптом

$ lpstat -p
printer HP_LaserJet_1320_series disabled since Mon Sep 28 13:01:49 2026 -
	Unable to use legacy USB class driver.

В логе на каждое задание:

E [Job 2101] Unable to use legacy USB class driver.
E [cups-deviced] PID 1539 (hpfax) stopped with status 86!
E [cups-deviced] PID 1549 (gutenprint53+usb) crashed on signal 6!

status 86 — это ENOEXEC/“bad CPU type”, то есть система отказалась запускать бинарник. Первый намёк на архитектуру.

Разбор

Проверяем фильтр, который прописан в PPD очереди:

$ grep -a cupsFilter /etc/cups/ppd/HP_LaserJet_1320_series.ppd
*cupsFilter: "application/vnd.cups-postscript 0 /Library/Printers/hp/filter/hpPostProcessing.bundle/Contents/MacOS/hpPostProcessing"

$ file /Library/Printers/hp/filter/hpPostProcessing.bundle/Contents/MacOS/hpPostProcessing
Mach-O 64-bit executable x86_64

Вот откуда «ПО несовместимо»: фильтр печати — только Intel. Но задание падало раньше, чем доходило до фильтра, — в бэкенде. Смотрим, что внутри бэкенда:

$ strings -a /usr/libexec/cups/backend/usb | grep -i legacy
USB_LEGACY_STATUS
Unable to use legacy USB class driver.
DEBUG: Started usb(legacy) backend (PID %d)
DEBUG: usb(legacy) backend %d crashed on signal %d
DEBUG: usb(legacy) backend %d stopped with status %d
DEBUG: usb(legacy) backend running native again

Это механика из usb-darwin.c в CUPS: если у USB‑устройства в IORegistry прописан вендорный class driver, который нельзя загрузить в текущем процессе, бэкенд перезапускает самого себя другим слайсом. Исторически это писалось для перехода PPC → Intel, сейчас работает как Intel → ARM.

Кто прописывает устройству вендорный драйвер? Пакет HP. Находим codeless‑кекст:

$ plutil -p /Library/Extensions/hp_io_enabler_compound.kext/Contents/Info.plist | grep -c idProduct
323

$ plutil -p .../Info.plist | grep -A1 '"idProduct" => 4114'
      "IOClass" => "AppleUSBMergeNub"
        "USB Printing Class" => "/Library/Printers/hp/Frameworks/HPDM.framework/Runtime/HPIOPrinterClassDriver.plugin"

HP IO Enabler 3.4.0 (2016), AppleUSBMergeNub, 323 USB product ID вендора 0x03F0 — то есть практически вся линейка HP. Каждому подходящему устройству он навешивает свойство USB Printing Class с путём к своему class driver. А драйвер вот такой:

$ file .../HPIOPrinterClassDriver.plugin/Contents/MacOS/HPIOPrinterClassDriver
Mach-O 64-bit bundle x86_64

2017 год, только Intel. Бэкенд usb собран как universal (x86_64, arm64e, arm64e.x1), поэтому он честно пытается перезапуститься x86-слайсом. И вот финальная деталь:

$ ls /Library/Apple/usr/libexec/oah
RosettaLinux
$ pgrep -x oahd
# пусто

Rosetta 2 не установлена. Запускать x86-слайс нечем → Unable to use legacy USB class driver → задание не доезжает, очередь уходит в disabled.

Решение

sudo softwareupdate --install-rosetta --agree-to-license

Затем удалить очередь принтера и добавить заново — одна Rosetta уже залипшую очередь не оживила. Перезагрузка не нужна. Новая очередь встала на тот же PPD от HP, с тем же x86-фильтром hpPostProcessing, и под Rosetta печатает.

Проверка:

pgrep -x oahd          # демон Rosetta должен быть жив
lpstat -p              # idle, enabled — а не disabled

Если Rosetta нельзя

Два обходных пути, оба рабочие по логике механизма:

1. Убрать кекст HP — тогда устройству достанется родной универсальный class driver Apple:

$ file /System/Library/Printers/Libraries/USBGenericPrintingClass.plugin/Contents/MacOS/USBGenericPrintingClass
Mach-O universal binary with 3 architectures: [x86_64] [arm64e] [arm64e.x1]
sudo mv /Library/Extensions/hp_io_enabler_compound.kext ~/Desktop/   # бэкапом
sudo kmutil install --update-all
# перезагрузка

Очередь при этом заводить без фильтров HP:

sudo lpadmin -p HP1320 -E -v 'usb://...' -m drv:///sample.drv/generic.ppd

drv:///sample.drv/generic.ppd — это «Generic PostScript Printer», Level 2, ровно под эмуляцию 1320.

2. Ethernet вместо USB — у 1320n встроенный JetDirect:

sudo lpadmin -p HP1320 -E -v socket://192.168.1.50:9100 -m drv:///sample.drv/generic.ppd

Так мы обходим и USB‑бэкенд, и весь код HP целиком. Это самый долговечный вариант: ни одного вендорного бинарника в цепочке.


Случай Б. Color LaserJet CP1025: драйвер починить нельзя

Дальше я взялся за второй принтер — уверенный, что Rosetta уже всё решила. Не решила.

Симптом

[Job 2112] PdfColorSpace::initProfile CMGetDefaultProfileBySpace error:-192
[Job 2112] CMOpenProfile error -192
[Job 2112] PID 7774 (/Library/Printers/hp/laserjet/cp1020series/hpcp1020filter.plugin/.../hpcp1020) crashed on signal 11.
[Job 2112] printer-state-message="Filter failed"

USB‑часть в порядке: в логе выше видно, что загрузился Apple‑овский USBGenericPrintingClass.plugin, соединение открыто, первые байты ушли. Падает растеризатор — signal 11, то есть SIGSEGV.

Разбор

$ nm -u /Library/Printers/hp/laserjet/cp1020series/hpcp1020filter.plugin/Contents/Resources/hpcp1020
_CMCloseProfile
_CMCopyProfile
_CMGetDefaultProfileBySpace
_CMGetProfileMD5
_CMOpenProfile

Это Carbon ColorSync — API, которого в macOS больше нет. Драйвер (HP, 2012) просит цветовой профиль, получает -192, не проверяет результат и разыменовывает NULL.

Принципиальная разница со случаем А: под Rosetta бинарник запускается нормально. Проблема не в архитектуре, а в отсутствующих функциях системы. Их не вернуть ни Rosetta, ни установкой старых пакетов. А поскольку CP1025 host‑based — без этого фильтра растрировать нечем, и принтер превращается в кирпич.

Решение: foo2zjs

Нужен open‑source драйвер, который сам умеет в ZjStream. Это foo2zjs, и под macOS на Apple Silicon есть готовая сборка: github.com/ardabeh/hp‑legacy‑mac. Ставит foo2zjs и свой arm64-ghostscript в /Library/Printers/hp-legacy-mac — важно, что не в /usr/local и не в /opt/homebrew: песочница CUPS в macOS запрещает запуск оттуда, поэтому brew‑версия ghostscript тут не годится.

curl -fsSL https://raw.githubusercontent.com/ardabeh/hp-legacy-mac/main/install.sh -o /tmp/hp-legacy-mac.sh
sudo sh /tmp/hp-legacy-mac.sh

Итоговая цепочка вместо упавшего фильтра HP:

gs -sDEVICE=pksmraw -r1200x600 -g10200x6600   (arm64, из бандла)
  → foo2zjs -z3 -c
    → /usr/libexec/cups/backend/usb
      → принтер

И вот тут меня ждали две ловушки, каждая из которых ломала уже работавшее.

Ловушка 1: при двух USB‑принтерах установщик перенастраивает не ту очередь

В install.sh:

DEVICE_URI="$(lpstat -v 2>/dev/null | sed -nE 's/.*: (usb:.*)/\1/p' | head -1)"
QUEUE="$(lpstat -v 2>/dev/null | grep -i 'usb:' | awk '{print $3}' | sed 's/:$//' | head -1)"

head -1 по списку очередей. Модель он определил верно — подобрал PPD HP-LaserJet_Pro_CP1025nw. А вот очередь и device URI взял первые из lpstat -v, то есть от LaserJet 1320. Результат: драйвер CP1025 записан в очередь 1320, с USB‑адресом 1320.

$ grep -a NickName /etc/cups/ppd/HP_LaserJet_1320_series.ppd
*NickName: "HP LaserJet Pro CP1025nw Foomatic/foo2zjs-z3 (recommended)"

Два принтера сломаны одним запуском. Спасает то, что CUPS при замене PPD сохраняет прежний как .ppd.O — оттуда 1320 и восстановилась.

Если USB‑принтеров больше одного, очередь надо заводить руками. Берём PPD из бандла, вырезаем его строки *cupsFilter и подставляем фильтр бандла:

gunzip -c /Library/Printers/hp-legacy-mac/ppd/HP-LaserJet_Pro_CP1025nw.ppd.gz > /tmp/cp1025.ppd
grep -v '^\*cupsFilter' /tmp/cp1025.ppd > /tmp/t && mv /tmp/t /tmp/cp1025.ppd
printf '*cupsFilter: "application/vnd.cups-pdf 0 hp-legacy-mac"\n' >> /tmp/cp1025.ppd

sudo lpadmin -p CP1025 \
  -v 'usb://Hewlett-Packard/HP%20LaserJet%20CP1025?serial=XXXXXXXX' \
  -P /tmp/cp1025.ppd -E -o printer-error-policy=retry-job

Плюс конфиг очереди, который читает фильтр (имя файла должно совпадать с именем очереди):

sudo tee /Library/Printers/hp-legacy-mac/queues/CP1025.conf <<'EOF'
DRIVER="foo2zjs-wrapper -z3 -P -L0"
COLOR_CAPABLE=1
COLOR_FLAGS="-c -C gs9"
EOF

Ловушка 2: драйвер HP возвращается сам

Настроил, проверил, работает. Выключил принтер кнопкой, включил — снова CMOpenProfile error -192 и signal 11. Смотрим на времена файлов:

$ ls -l /etc/cups/ppd/ /etc/cups/printers.conf*
-rw-r--r--  385518 Sep 28 15:12 HP_LaserJet_CP1025.ppd      # снова 385 КБ — это PPD от HP
-rw-------    1906 Sep 28 15:12 printers.conf
-rw-------    1069 Sep 28 15:11 printers.conf.O

При переподключении устройства автонастройка печати в macOS пересобрала очередь и выбрала «самый подходящий» установленный драйвер — а это драйвер HP 2012 года, лежащий в системных папках. PPD из бандла она не видит: он не в /Library/Printers/PPDs.

Лечение — унести драйвер HP физически, чтобы выбирать было нечего:

sudo mkdir -p /Library/Printers/hp-legacy-mac/hp-driver-disabled
sudo mv /Library/Printers/hp/laserjet/cp1020series \
        /Library/Printers/hp-legacy-mac/hp-driver-disabled/
cd /Library/Printers/PPDs/Contents/Resources
sudo mv "HP LaserJet CP 1025.gz" "HP LaserJet CP 1025nw.gz" \
        "HP LaserJet CP1025.gz" "HP LaserJet CP1025nw.gz" \
        /Library/Printers/hp-legacy-mac/hp-driver-disabled/

И назвать свою очередь иначе, чем назвала бы система. Я назвал CP1025, оставив имя HP_LaserJet_CP1025 системе под пустышку. Печатать — на CP1025.

Быстрая проверка в любой момент:

$ grep cupsFilter /etc/cups/ppd/CP1025.ppd
*cupsFilter: "application/vnd.cups-pdf 0 hp-legacy-mac"     # хорошо
# hpcp1020 в этой строке = драйвер HP вернулся, повторить вынос

После этого печать пережила и выключение принтера, и переподключение кабеля.


Как определить свой случай

Тип принтера

Примеры

Что ломается

Решение

Растрирует сам (PostScript / PCL)

LaserJet 1160, 1320, 2100, серия 4000, сетевые офисные лазерники

x86-only class driver и фильтр HP; без Rosetta бэкенд не может перезапуститься x86-слайсом

Rosetta 2 + пересоздать очередь. Ещё лучше — Generic PostScript по socket://IP:9100

Host‑based / GDI / winprinter

Color LaserJet CP1025, CP1215, LaserJet 1000/1005/1018/1020/1022, P1005–P1008, M12, M1132

фильтр HP зовёт вырезанный ColorSync → SIGSEGV; без фильтра растрировать нечем

заменить драйвер на foo2zjs, драйвер HP вынести из системных папок

Универсальная диагностика для любого вендора, не только HP:

tail -40 /var/log/cups/error_log                  # что именно упало
file <путь к фильтру из cupsFilter в PPD>         # только x86_64? → пробовать Rosetta
nm -u <тот же путь> | grep '^_CM'                 # есть _CM*? → ColorSync мёртв, драйвер не спасти

Механика общая: то же сообщение «ПО несовместимо» встречается на Samsung ML-1640, а он тоже host‑based (там нужен foo2qpdl), так что логика второго случая применима и к нему.

Выводы

  1. Диалог печати в macOS не говорит ничего. /var/log/cups/error_log говорит всё.

  2. «Принтер определяется, но не печатает» на Apple Silicon — чаще не отсутствие драйвера, а отсутствие Rosetta 2. Проверяется одной командой pgrep -x oahd.

  3. Если драйвер импортирует символы _CM*, дальше можно не искать: этот код мёртв навсегда, нужен open‑source аналог.

  4. Автонастройка печати в macOS — активный участник событий. Она пересобирает очереди при переподключении устройства и выбирает драйвер сама. Пока сломанный драйвер лежит в системных папках, он будет возвращаться.

  5. Если у железа есть Ethernet и оно понимает PostScript, сеть плюс Generic PostScript — самое долговечное решение: в цепочке не остаётся ни одного вендорного бинарника, которому может что‑то понадобиться от системы.

    Мой первый пост, надеюсь поможет кому‑то. Я долго бился с этой проблемой, даже таскал старый ноут на винде для печати.

Комментарии (1)


  1. Shaman_RSHU
    30.09.2026 13:01

    Вероятно я невнимательно прочитал статью, но фундаментальный вывод по «Случаю А» (LaserJet 1320) ошибочен. Ошибка «ПО несовместимо» и падение с status 86 возникают исключительно из-за попытки насильно установить устаревший проприетарный пакет драйверов HP (с x86-бинарниками и codeless-kext 2016 года). Это не только не нужно, но и нарушает принципы безопасности.

    HP LaserJet 1320 аппаратно поддерживает PostScript Level 2 и PCL. macOS на Apple Silicon имеет встроенные универсальные (Universal Binary: arm64 + x86_64) драйверы. Принтер работает нативно, без Rosetta и без вендорного мусора.

    Вот как у меня на MacBoook Pro M5 MacOS 27: