OpenWRT之网络打印机

HP打印扫描一体机的共享设置

背景

手上有一个HP DeskJet 2332 打印扫描一体机,当初为了孩子上网课买的。家里有个打印机还是很方便的,同时扫描仪也偶尔会用一用,比如扫描证件等。

但是打印机这东西比较大,放哪里是个大问题,放哪里都占地方,而且容易吃灰。

前面介绍过我的AIO家庭服务器,于是我决定将打印机和服务器放一起,再通过网络共享出来。说干就干。

由于ESXi本身不支持打印机,所以只能将打印机交给其中一台虚拟机来管理并共享。首先我就想到了群晖,但从DSM 6.2开始打印机共享服务就停止支持。实测DSM7.1共享打印机确实无法使用,所以现在剩下的选择就是OpenWRT和Windows。下面我们就看看OpenWRT共享打印机怎么样吧。

相关协议

工欲善其事,必先利其器。所以在工作之前,我们先了解一下网络打印机相关协议。

网络打印协议

LPD/TCP/515

LPD是“行式打印机后台程序”协议的缩写,该协议监听TCP 515端口,可以通过CLI使用“lpr”进行访问。为了打印,客户端需要发送一个作业控制文件和包含要打印的数据文件。

IPP/TCP/631

IPP是基于HTTP的扩展协议,因此它继承了HTTP协议所有的安全功能,如基本身份验证和SSL/TLS加密。要提交打印作业,用户需要发送HTTP POST请求到IPP服务器,该服务器监听TCP 631端口,任何人都知道CUPS是IPP协议的一个实现,它是许多Linux发行版和macOS X中的默认打印系统。

HP Jetdirect - Socket/TCP/9100

也被称为“raw printing”,因为它使用TCP 9100端口进行网络打印操作,通常在CUPS和Windows系统中使用。与LPD,IPP和SMB协议需要使用打印机控制语言才能执行打印操作相比,通过9100端口发送的所有数据都由打印设备直接处理,并直接将打印结果反馈到客户端,包括状态和错误消息。因此我们可以通过该方法来直接访问打印机控制语言的结果!

SMB/TCP/445

SMB(服务器信息块)是应用层网络协议,通常在Windows上使用。该协议监听TCP 445端口,经常用于网络中的共享文件和打印机。

打印机控制语言

SNMP/UDP/161

SNMP-“简单网络管理协议”,该协议监听UDP 161端口,用于管理网络组件。

PJL

PJL是“Printer Job Language”的简称,该控制语言可用于操纵常规设置,也可以永久更改。在许多控制语言中,供应商往往只支持PJL控制语言中的部分命令,并根据打印机的需要自行添加专有的功能。

页面描述语言 - PDL

PostScript - PS

众所周知,该页面描述语言由Adobe发明,并被广泛用于PDL。PS的能力远不止于定义文档的外观和处理矢量图形。

PCL

PCL是各种供应商和设备都支持的极简页面描述语言,该页面描述语言不直接访问底层文件系统。

零配置网络

我觉得有必要介绍一个新概念。

零配置网络 (Zero-configuration networking),也就是不需要手动干预或特殊配置,就可以使用相关的网络服务。

我们在设置打印机共享时,需要在协议和软件等方面考虑到对零配置网络的支持,让客户端可以简单而直接地使用该打印机。

准备工作

我们将在OpenWRT上设置打印机并通过网络共享,在此之前我们需要做一些准备工作。

macOS共享打印机

首先将打印机连接到macOS上,通过‘HP Easy Start.app’安装好驱动和‘HP Easy Scan’,测试好打印与扫描功能。然后在网络上共享此打印机。 2023-05-09-14-35-23@2x

在OpenWRT上运行以下命令获取打印机设置参数等信息,后面将用到。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
ubus call umdns update 
ubus call umdns browse 

...
	"_ipp._tcp": {
		"HP DeskJet 2300 series @ MacMini": {
			"txt": "txtvers=1",
			"txt": "qtotal=1",
			"txt": "rp=printers/HP_DeskJet_2300_series",
			"txt": "ty=DeskJet 2300 series",
			"txt": "adminurl=https://MacMini.local.:631/printers/HP_DeskJet_2300_series",
			"txt": "note=MacMini",
			"txt": "priority=0",
			"txt": "product=(HP Deskjet 2300 series)",
			"txt": "pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/pwg-raster",
			"txt": "UUID=013924c6-107f-3d35-76ac-899ec841334f",
			"txt": "TLS=1.2",
			"txt": "Color=T",
			"txt": "Scan=T",
			"txt": "printer-state=3",
			"txt": "printer-type=0x480900E",
			"port": 631
		}
	},
	"_ipps._tcp": {
		"HP DeskJet 2300 series @ MacMini": {
			"txt": "txtvers=1",
			"txt": "qtotal=1",
			"txt": "rp=printers/HP_DeskJet_2300_series",
			"txt": "ty=DeskJet 2300 series",
			"txt": "adminurl=https://MacMini.local.:631/printers/HP_DeskJet_2300_series",
			"txt": "note=MacMini",
			"txt": "priority=0",
			"txt": "product=(HP Deskjet 2300 series)",
			"txt": "pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/pwg-raster",
			"txt": "UUID=013924c6-107f-3d35-76ac-899ec841334f",
			"txt": "TLS=1.2",
			"txt": "Color=T",
			"txt": "Scan=T",
			"txt": "printer-state=3",
			"txt": "printer-type=0x480900E",
			"port": 631
		}
	},
...

由此可看出,macOS通过IPP协议共享此打印机,端口为TCP/631。测试发现在Windows下,也可以直接发现该打印机,无需繁琐的设置。我们在OpenWRT下共享打印的目标也是如此。

Windows共享打印机

打开 控制面板 - 硬件和声音 - 查看设备和打印机 - 右键选中的打印机 - 打印机属性 - 共享

2023-05-09-13-43-53@2x

使用umdns和avahi均无法发现此打印机,这完全不符合我们的需求。忽略Windows打印机共享吧,我们就参照macOS设置来共享网络打印机。

OpenWRT 连接打印机

现在我们可以把打印机连接到OpenWRT了,如果你的OpenWRT使用的是物理机,直接把打印机连接到USB接口即可。如果你使用的是ESXi虚拟机,还需要做好USB设备直通。

把打印机连接到ESXi主机,然后ssh进入ESXi主机

1
2
3
4
5
6
7
8
# 查看USB设备,确认打印机已经连接
lsusb 

# 查看usbarbitrator的状态
chkconfig usbarbitrator --list

# 启动usbarbitrator服务
/etc/init.d/usbarbitrator start

直通USB打印机给OpenWRT虚拟机,ESXi - 虚拟机 - OpenWRT - 编辑 - 添加其他设备 - USB设备

2023-05-09-16-33-55@2x

打印机共享

p910nd是OpenWRT默认的打印机管理服务,使用Jetdirect/AppSocket - TCP/9100协议。

安装p910nd

1
opkg install luci-app-p910nd-zh-cn kmod-usb-printer

刷新luci,点击 服务 - ‘p910nd - Printer Server’,接下来就可以配置打印机了。

==> 警告:首次使用p910nd,不要使用luci配置界面,生成的配置文件有乱码。或者,自己手动修改乱码部分。

配置 - part1

连接USB打印机

1
2
3
4
5
6
# 查看打印机是否正常接入
dmesg | grep "USB.*printer"
[  412.684910] usblp 1-1:1.1: usblp0: USB Bidirectional printer dev 2 if 1 alt 0 proto 2 vid 0x03F0 pid 0x3654

# 查看打印机路径,一般都是/dev/usb/lp0
ls /dev/usb/lp* 

配置p910nd

2023-05-09-15-32-50@2x

  1. 勾选
  2. 设置一栏填写刚刚找到的打印机路径,一般都是/dev/usb/lp0
  3. 接口这里不用管,设置了也是乱码,等会直接编译配置文件
  4. 默认9100,也可以使用9101等
  5. 双向模式

保存并应用,然后手动修改配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
vim /etc/config/p910nd

config p910nd
    option enabled '1'
    option device '/dev/usb/lp0'
    option bind '10.10.10.1'
    option port '0'
    option runas_root '0'
    option bidirectional '1'

# 重载p910nd
/etc/init.d/p910nd reload 

接下来,我们在macOS或Windows中就可以通过IP地址添加当前打印机了,然后打印测试页,确认打印机已经工作正常。

配置 - part2 - mDNS

虽然已经可以通过IP添加打印机,但是这样很不方便,每台机器都需要手动添加IP地址和协议等,对专业人士来说没什么,但对一般用户来说,这还是有些困难的。设置不当的话,打印机还不能正常工作。

p910nd支持mDNS,之前我们做准备工作时获取到的打印机信息这里就要用上了,但p910nd支持的参数比较少,多余的全添加到’mdns_mdl’里面吧。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
vim /etc/config/p910nd 

config p910nd
    option enabled '1'
    option device '/dev/usb/lp0'
    option bind '10.10.10.1'
    option port '0'
    option bidirectional '1'
    option runas_root '0'
    option mdns '1'
    # Human-readable location
    option mdns_note 'iHome'
    # Human-readable printer make and model
    option mdns_ty 'DeskJet 2300 series'
    # Post-Script product string, including parenthesis
    option mdns_product '(HP Deskjet 2300 series)'
    # IEEE-1284 Device ID MANUFACTURER/MFG string
    option mdns_mfg ''
    # IEEE-1284 Device ID MODEL/MDL string
    option mdns_mdl 'HP DeskJet 2332,txtvers=1,qtotal=1,priority=0,Color=T,Scan=T,printer-type=0x480900E,pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/pwg-raster'
    # IEEE-1284 Device ID COMMAND SET/CMD string
    option mdns_cmd ''

这里,我们还需要手动修复一下p910nd打印机名称显示问题

重启umdns和p910nd服务

1
2
/etc/init.d/p910nd restart 
/etc/init.d/umdns restart 

现在我们不需要任何配置就可以直接看到此网络打印机了,无须设置,直接点击添加打印机就可以使用了。 2023-05-09-16-17-41@2x

如果你的p910nd配置更改过多次,可能还需要清除本地mDNS缓存,不然会出现多个打印机,把人搞糊涂。

1
2
3
4
5
# macOS
sudo killall -HUP mDNSResponder

# OpenWRT
/etc/init.d/umdns restart 

扫描仪共享

关于sane

在给OpenWRT安装sane之前,我们需要了解一下sane的工作方式,及其与p910nd之间的关系。首先sane和其他服务差不多,加载usb相关驱动,然后为客户端提供服务。但这里有一点需要特别注意的是,sane和p910nd操作的是同一台usb打印机,所以当sane启动时打印机是无法工作的。通过查看/usr/sbin/saned我们会发现,真正的/usr/lib/sane/saned在工作完成后需要恢复打印机的驱动。

所以我们不但要安装saned,同时也需要xinetd来管理sane服务。当有网络连接时启动saned,此时打印机功能失效,等待扫描仪工作结束,saned自动退出,再恢复打印机功能。

如果设置不当,在使用扫描仪之后打印机将失效。 所以,这里提供一条恢复打印机的命令,调试时可以用到。

1
2
3
4
5
6
7
rmmod usblp && modprobe usblp

# 确认打印机是否已经恢复,一旦发现问题,立即使用以上命令恢复打印机
ls /dev/usb/lp0 

# 查看saned是否在后台,如果在后台,打印机功能失效
ps aux | grep saned

安装sane

除了‘sane-daemon’外,这里还需要使用xinet来管理sane服务,当有软件网络连接时,启动sane服务。

1
opkg install sane-daemon sane-frontends xinetd

安装扫描仪驱动

OpenWRT提供的扫描仪驱动较多,这里必不需要安装整个‘sane-backends-all’包,选择自己的扫描仪驱动即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 查找所有扫描仪驱动 
opkg list sane-* 
opkg list *-sane
# OpenWRT中sane驱动可能有两种命名格式,都看一下

# HP DeskJet 2300 series 
opkg install hplip-sane 

# 测试驱动是否正确 
scanimage -L 

device `hpaio:/usb/DeskJet_2300_series?serial=CN291420M6' is a Hewlett-Packard DeskJet_2300_series all-in-one

测试扫描仪

设置Access List - 扫描仪白名单

1
echo "10.10.10.0/24" >> /etc/sane.d/saned.conf 

手动模式启动saned

1
saned -l -e -b 10.10.10.1 -p 6566 -u root -d 5 -o

注意: 一定要以root用户运行,否则saned无法访问驱动。好吧,这本是一个用户权限问题,直接用root用户解决。

1
2
Wed May 10 11:02:49 2023 daemon.err saned[21441]: io/hpmud/musb.c 595: invalid usb_open: Permission denied
Wed May 10 11:02:49 2023 daemon.err saned[21441]: io/hpmud/musb.c 1151: unable to open hp:/usb/DeskJet_2300_series?serial=CN291420M6

使用Windows/SANEWin或其他客户端软件连接测试扫描仪

2023-05-10-10-59-39@2x

** 扫描结束后,以上窗口会自动关闭,但主窗口还在,与saned的连接也还在,一定要手动关闭主窗口,否则saned不会退出。**

==> 默认设置的DPI扫描效果很差,建议设置到300或更高。

好了,到此扫描仪已经算是正常工作了,接下来我们只需要配置好xinetd。

配置saned服务

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
vim /etc/xinetd.d/sane-port

service sane-port
{
	disable     = no
	socket_type = stream
	port        = 6566
	wait        = no
	user        = root
	group       = scanner
	server      = /usr/sbin/saned
}

关于Windows

快到结尾了,如果你按照我的操作执行,你会发现macOS已经可以正常发现和使用打印机,但Windows却不可以。

打开设备和打印机,你会发现一堆乱七八糟的设备,唯独却没有我们的打印机。但通过IP地址却能够添加和使用OpenWRT共享的打印机。这说明Windows是支持p910nd的网络共享协议,只是不支持mDNS的网络发现协议。

那这样就好办了。

  • 方法一:打开Windows的mDNS。打开管理员的Power Shell或CMD,运行以下代码并重启
1
REG ADD "HKLM\Software\Policies\Microsoft\Windows NT\DNSClient" /V "EnableMulticast" /D "1" /T REG_DWORD /F

此方法只适用于Windows 10较新的版本,似乎其mDNS服务有些小问题。

  • 方法二,禁用Windows自带mDNS,再安装Bonjour。这里就不详述了。

好吧,对于Windows来说,似乎没有做到零配置啊。有点小遗憾,但好在用Windows的人比较多,随便问一下就知道怎么添加打印机了。

结束语

接近结束时,我偶然又发现一个新物种VirtualHere,将USB设备通过网络共享,就好像它们在本地使用一样。我原来把打印机连接在服务器上主要就是因为其放在桌上占地方,如果能够远程连接USB设备,那直接使用HP的驱动和软件不是更好?

下次再试试VirtualHere吧。

参考


小酌怡情
Built with Hugo
主题 StackJimmy 设计
访问量 -    访客数 - 人次