HP LaserJet M14-M17 在Debian下无法打印

我需要在 Debian (KDE) 环境下通过 USB 连接 HP LaserJet M14-M17 打印机打印几张试卷。打印机插入后能够被系统识别并出现在设备列表中,但实际发送打印任务时,状态显示"打印完成",打印机却毫无反应,仅指示灯象征性地闪烁了两下。值得注意的是,打印选项中没有双面打印。

第一反应是检查 HPLIP 。系统的 HPLIP 版本是 3.22.10 。随后执行 sudo hp-setup -i ,系统正确检测到了打印机并匹配了对应的 PPD 文件(hp-laserjet_m14-m17.ppd)。但在打印测试页时,终端输出以下错误:

复制代码
error: Channel write error
error: Device is busy or in an error state.

打印机依然没有反应。HPLIP 虽然识别了设备型号,但实际的数据通信失败了。这就很奇怪了。

查询发现, HP LaserJet M14-M17 是一款支持 IPP Everywhere 的打印机,通过 USB 连接时使用的是 IPP over USB 协议,而非传统的 USB 批量传输。在 Debian 中,负责处理该协议的是 ipp-usb 守护进程。

我尝试检查 ipp-usb 的状态。

bash 复制代码
systemctl status ipp-usb
复制代码
○ ipp-usb.service - Daemon for IPP over USB printer support
     Loaded: loaded (/usr/lib/systemd/system/ipp-usb.service; static)
     Active: inactive (dead)
       Docs: man:ipp-usb(8)
Apr 25 18:40:15 localhost systemd[1]: Started ipp-usb.service - Daemon for IPP over USB printer support.
Apr 25 18:41:04 localhost systemd[1]: ipp-usb.service: Deactivated successfully.

服务处于 inactive (dead) 状态,且日志中显示它曾被多次启动但均在短时间内退出。也许是 ipp-usb 本身的问题?

bash 复制代码
systemctl status ipp-usb.socket
复制代码
Unit ipp-usb.socket could not be found.

socket 单元不存在。ipp-usb 并非通过 socket 激活。

原来,服务反复退出的真正原因是打印机未开机------ipp-usb 在 udev 模式下运行时,如果没有检测到 IPP over USB 设备,就会自动退出。

打开打印机后,先用 lsusb 确认设备已被系统识别:

bash 复制代码
lsusb | grep -i hp
复制代码
Bus 001 Device 006: ID 03f0:be2a HP, Inc HP LaserJet M14-M17
bash 复制代码
systemctl status ipp-usb
复制代码
● ipp-usb.service - Daemon for IPP over USB printer support
     Loaded: loaded (/usr/lib/systemd/system/ipp-usb.service; static)
     Active: active (running) since Sat 2026-04-25 19:03:40 CST; 2min 2s ago
   Main PID: 3904 (ipp-usb)
      Tasks: 12 (limit: 4306)
     Memory: 14.2M (peak: 15M)
        CPU: 98ms
     CGroup: /system.slice/ipp-usb.service
             └─3904 /usr/sbin/ipp-usb udev
Apr 25 19:03:40 localhost systemd[1]: Started ipp-usb.service - Daemon for IPP over USB printer support.

ipp-usb 成功保持运行,且命令行参数为 udev,印证了它以 udev 模式工作。查看journal,其中却只记录了 systemd 的启停信息,看不到 ipp-usb 自身的日志。通过 ipp-usb -h 查看帮助信息,发现它支持 debug 模式。

复制代码
Usage:
    ipp-usb mode [options]
Modes are:
    standalone  - run forever, automatically discover IPP-over-USB
                  devices and serve them all
    udev        - like standalone, but exit when last IPP-over-USB
                  device is disconnected
    debug       - logs duplicated on console, -bg option is
                  ignored
    check       - check configuration and exit
    status      - print ipp-usb status and exit
bash 复制代码
systemctl stop ipp-usb
ipp-usb debug
复制代码
  ===============================
  ipp-usb started in "debug" mode, pid=4190
  ctrlsock: listening at "/var/ipp-usb/ctrl"
+ PNP Bus 001 Device 006: added
  ===============================
+ Found new device. VID:PID = 03f0:be2a
  HWID quirks: EMPTY
  Loading quirks for model: "HP LaserJet M14-M17"
  Device quirks:
    [*]
      ; (/usr/share/ipp-usb/quirks/default.conf:5)
      http-connection = ""
+ Bus 001 Device 006: opened HP LaserJet M14-M17
  Device info:
    USB Port:      2
    Ident:         03f0-be2a-VN50B02739-HP-LaserJet-M14-M17
    Manufacturer:  HP
    Product:       HP LaserJet M14-M17
    SerialNumber:  VN50B02739
    BasicCaps:     print,http
  USB stack parameters
    authorized_default:          1
    autosuspend:                 2
    blinkenlights:               N
    initial_descriptor_timeout:  5000
    nousb:                       N
    old_scheme_first:            N
    quirks:
    usbfs_memory_mb:             16
    usbfs_snoop:                 N
    usbfs_snoop_max:             65536
    use_both_schemes:            Y
  USB interfaces:
    Config Interface Alt Class SubClass Proto
       1       0      0   7      1       2
       1       1      0   255    4       1
*      1       1      1   7      1       4
       1       2      0   255    4       1
*      1       2      1   7      1       4
       1       3      0   255    4       1
*      1       3      1   7      1       4
  USB[0]: open: Bus 001 Device 006 Interface 1 Alt 1
  USB[1]: open: Bus 001 Device 006 Interface 2 Alt 1
  USB[2]: open: Bus 001 Device 006 Interface 3 Alt 1
> HTTP[000]: POST ipp://localhost:60000/ipp/print
> HTTP[000]: request body: got 461 bytes; closed
> HTTP[000]: body is small (461 bytes), prefetched before sending
  USB[0]: connection allocated, 1 in use: a-- --- ---
  HTTP[000]: connection 0 allocated
  USB[0]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[000]: POST ipp://localhost:60000/ipp/print - 200 OK
  USB[0]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[000]: response body: got 1566 bytes; EOF
  USB[0]: connection released, 0 in use: --- --- ---
< HTTP[000]: done with response body
  IPP FaxOut service not in capabilities
> HTTP[001]: GET http://localhost:60000/eSCL/ScannerCapabilities
> HTTP[001]: body is empty, sending as is
  USB[1]: connection allocated, 1 in use: --- a-- ---
  HTTP[001]: connection 1 allocated
  USB[1]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[001]: GET http://localhost:60000/eSCL/ScannerCapabilities - 404 Not Found
< HTTP[001]: client has gone; draining response from USB
! ESCL: eSCL: HTTP status: 404 Not Found
> HP LaserJet M16a (435CA7): _printer._tcp TXT record:
    usb_SER=VN50B02739
    usb_HWID=03f0&be2a
> HP LaserJet M16a (435CA7): _ipp._tcp TXT record:
    air=none
    mopria-certified=1.3
    rp=ipp/print
    priority=50
    kind=document,envelope,photo
    PaperMax=legal-A4
    UUID=564e3530-4230-3237-3339-c46516435ca7
    Color=F
    Duplex=F
    note=
    qtotal=1
    usb_MDL=HP LaserJet M14-M17
    usb_MFG=HP
    usb_CMD=PJL,PML,PWG_RASTER,URP
    ty=HP LaserJet M14-M17
    product=(HP LaserJet M14-M17)
    pdl=application/PCLm,application/octet-stream,image/pwg-raster
    txtvers=1
    adminurl=http://localhost:60000
    Fax=F
    Scan=F
    usb_SER=VN50B02739
    usb_HWID=03f0&be2a
> HP LaserJet M16a (435CA7): _http._tcp TXT record:
> HP LaserJet M16a (435CA7): _ipp-usb._tcp TXT record:
  DNS-SD: HP LaserJet M16a (435CA7) (USB): trying
  USB[1]: connection released, 0 in use: --- --- ---
< HTTP[001]: done with response body
  DNS-SD: FQDN: "linux.local"
  DNS-SD: FQDN: "linux.local"->"localhost"
  DNS-SD: +subtype: "_universal._sub._ipp._tcp"
+ DNS-SD: HP LaserJet M16a (435CA7) (USB): publishing requested
  DNS-SD: HP LaserJet M16a (435CA7) (USB): AVAHI_ENTRY_GROUP_REGISTERING
  DNS-SD: HP LaserJet M16a (435CA7) (USB): AVAHI_ENTRY_GROUP_ESTABLISHED
  DNS-SD: HP LaserJet M16a (435CA7) (USB): published
  auth: operation requested: print (HTTP POST /ipp/print)
  auth: address check:
    client-addr ::1 local=true
    server-addr ::1 local=true
  auth: client UID=-1 (auth rules don't use UID)
  auth: UID -1 resolved:
    user names:  *
    group names: *
  auth: allowed operations: config,fax,print,scan
  auth: access granted
> HTTP[002]: POST http://localhost:60000/ipp/print
> HTTP[002]: request body: got 173 bytes; EOF
> HTTP[002]: body is small (173 bytes), prefetched before sending
  USB[2]: connection allocated, 1 in use: --- --- a--
  HTTP[002]: connection 2 allocated
  USB[2]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[002]: POST http://localhost:60000/ipp/print - 200 OK
  USB[2]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[002]: response body: got 45675 bytes; EOF
  USB[2]: connection released, 0 in use: --- --- ---
< HTTP[002]: done with response body
  auth: operation requested: config (HTTP GET /ipp/strings/en-us)
  auth: address check:
    client-addr ::1 local=true
    server-addr ::1 local=true
  auth: client UID=-1 (auth rules don't use UID)
  auth: UID -1 resolved:
    user names:  *
    group names: *
  auth: allowed operations: config,fax,print,scan
  auth: access granted
> HTTP[003]: GET http://localhost:60000/ipp/strings/en-us
> HTTP[003]: body is empty, sending as is
  USB[0]: connection allocated, 1 in use: a-- --- ---
  HTTP[003]: connection 0 allocated
> HTTP[003]: request body: got 0 bytes; EOF
  USB[0]: zero-size read
  ...(此处省略大量 zero-size read)
< HTTP[003]: GET http://localhost:60000/ipp/strings/en-us - 200 OK
< HTTP[003]: response body: got 197 bytes; EOF
  USB[0]: connection released, 0 in use: --- --- ---
< HTTP[003]: done with response body

这段输出信息量很大。在LLM的帮助下,发现其关键内容如下:

  1. 设备识别+ Found new device. VID:PID = 03f0:be2a,打印机被正确识别,序列号为 VN50B02739,基本能力为 print,http
  2. USB 接口协议 :三个被标记为 * 的接口全部是 Class 7, SubClass 1, Protocol 4------这正是 IPP over USB 的标志。如果打印机使用传统 USB 批量传输,Protocol 应该是 1 或 2。
  3. IPP 服务地址ipp-usblocalhost:60000 上监听,提供 /ipp/print 端点。
  4. 通信验证 :可以看到三次 HTTP 请求均返回 200 OK------POST 到 /ipp/print 发送了打印数据,GET 到 /ipp/strings/en-us 获取了打印机描述信息,数据通道完全畅通。
  5. 扫描功能 :GET 到 /eSCL/ScannerCapabilities 返回了 404 Not Found,说明 M14-M17 不支持 eSCL 扫描(与 TXT 记录中的 Scan=F 一致)。
  6. DNS-SD 广播ipp-usb 通过 Avahi 发布了 DNS-SD 服务,其中 TXT 记录包含了打印机的完整能力信息。特别注意 Duplex=F,确认该型号硬件不支持双面打印。另外可以看到打印机的内部型号标识为 HP LaserJet M16a(M14-M17 系列的子型号)。
  7. 认证机制ipp-usb 对来自 localhost::1)的请求自动放行,允许 config,fax,print,scan 操作。

问题的根本原因已经明确:KDE 桌面在首次添加打印机时,CUPS 自动选择了 HPLIP 的 USB 后端(设备 URI 为 hp:/usb/HP_LaserJet_M14-M17?serial=...),而该打印机需要通过 ipp-usb 提供的 IPP 通道进行通信。

根据LLM分析,我按以下步骤操作:

  1. 让 systemd 重新接管 ipp-usb
bash 复制代码
systemctl start ipp-usb
  1. 删除之前通过 HPLIP 创建的错误打印队列:
bash 复制代码
sudo lpadmin -x HP_LaserJet_M14-M17
  1. 使用 ipp-usb 提供的 IPP 地址重新添加打印机,并指定 everywhere 驱动:
bash 复制代码
sudo lpadmin -p HP_LaserJet_M14-M17 \
  -v "ipp://localhost:60000/ipp/print" \
  -E \
  -m everywhere
  • -E 参数表示立即启用打印机并接受打印任务。
  • -m everywhere 指定使用 CUPS 内置的 IPP Everywhere 驱动,它会通过 IPP 协议自动向打印机查询支持的能力(纸张尺寸、分辨率、PDL 等),无需手动安装 PPD 文件。这与 HPLIP 需要预置 PPD 的方式形成了鲜明对比。
  1. 发送测试页验证:
bash 复制代码
echo "Hello from ipp-usb!" | lp -d HP_LaserJet_M14-M17

打印机成功出纸,问题解决了......一半。还有双面打印呢?

事实上,打印选项中缺失双面打印并非配置问题。通过 ipp-usb debug 输出的 DNS-SD TXT 记录可以确认 Duplex=F,即 HP LaserJet M14-M17 不具备自动双面打印单元。在 Windows 上,其是通过软件层面分两次打印奇数页和偶数页,结合手动翻面完成的。

细细一想,还有一个最大的问题。为什么 HPLIP 的 USB 后端不适配自家的打印机?

原来,在 USB 规范中,打印机接口属于 Class 7(打印设备),但协议编号区分了两种完全不同的通信方式:

协议编号 名称 通信方式 代表打印机
Protocol 1 / 2 传统 USB 批量传输 CUPS → usblp 或 HPLIP → USB bulk 端点 → 打印机 早期 HP LaserJet(如 P1102、M1132)
Protocol 4 IPP over USB CUPS → IPP 协议 → ipp-usb 守护进程 → USB → 打印机 HP LaserJet M14-M17 等 IPP Everywhere 打印机

ipp-usb debug 的输出中可以明确看到 M14-M17 的 USB 接口全部使用 Protocol 4:

复制代码
  USB interfaces:
    Config Interface Alt Class SubClass Proto
       1       0      0   7      1       2
       1       1      0   255    4       1
*      1       1      1   7      1       4    ← IPP over USB
       1       2      0   255    4       1
*      1       2      1   7      1       4    ← IPP over USB
       1       3      0   255    4       1
*      1       3      1   7      1       4    ← IPP over USB

HPLIP 的 USB 后端基于 IEEE-1284.4 协议(对应 USB 接口的 Protocol 1/2/3),通过 libusb 直接向 USB bulk 端点发送原始打印数据(PCL/PWG 光栅),绕过了 IPP 协议层。这对传统打印机没有问题,但 M14-M17 使用的是 Protocol 4(IPP over USB),期望收到的是标准 IPP 请求。当它收到一堆裸数据时,只能闪烁两下指示灯表示"收到了,但看不懂",然后丢弃。

HP 选择新打印机采用 IPP over USB 协议的原因在于,这是整个打印行业的趋势。传统模式下每家厂商都有自己的 USB 通信协议和专有驱动,导致 Linux 用户经常遇到新打印机无法使用的问题。为解决这一痛点,业界推出了 IPP Everywhere 标准------打印机像一台网络服务器一样,通过标准 HTTP/IPP 协议对外提供服务,任何支持 IPP 的客户端都可以直接使用,无需专有驱动。HP 作为该标准的推动者之一,从 2020 年前后开始在新打印机上逐步采用这一方案。

那么 HPLIP 为什么没有跟进适配呢?事实上 HPLIP 团队早在 2020 年发布的 3.20.11 版本中就已经注意到了 IPP 打印机的存在,但将其标注为 Known issues("hp-toolbox will not work for ippusbxd printers"),而非着手适配。此后直到 2025 年 11 月发布的最新版本 3.25.8,HPLIP 的更新内容始终只包含新增打印机型号的 PPD 文件和发行版兼容性,从未对 USB 后端进行架构性升级以支持 IPP over USB 协议。OpenPrinting 维护的 hplip-printer-app 项目在文档中也明确确认了这一点:HPLIP 的 USB 后端至今仍使用 IEEE-1284.4 协议。

HPLIP 自带了一个 HPLIP.conf 配置文件,会将所有 HP 设备加入黑名单,从而阻止 ipp-usb 访问这些设备。这意味着 HPLIP 不仅没有适配 IPP over USB,还在主动排斥 ipp-usb 的工作。所幸,多数 Linux 发行版在打包时会移除该配置文件。从发行版仓库安装的 HPLIP 通常不受此影响。

这个过渡期对 Linux 用户来说体验并不平滑:CUPS 和 KDE 的自动发现机制仍然会优先匹配 HPLIP 驱动,导致用户在不知情的情况下走了弯路。如果你的打印机也是较新的 HP 型号且遇到了类似的"打印完成但无反应"问题,建议优先检查 ipp-usb 的运行状态以及 CUPS 打印队列所使用的设备 URI 是否指向了正确的 IPP 端点。