Padavan插入HP的GDI打印机时自动发送固件的脚本
我们用无线路由器共享打印机,最容易遇到打印服务开启了,Windows下驱动也按教程正确安装了,但就是打印不正常的问题。我把我的解决办法总结一下,供大家参考。
有些广受欢迎的打印机,如我的HP Laserjet 1020,是所谓的GDI打印机,主要用于Windows系统。这种打印机设计时就简化了固件,ROM里根本没有真正干活的程序。打印机开机之后,必须由计算机把固件传过来安装到内存后,才能正常工作。在Windows系统里,打印机驱动程序就会自动做这个事。Windows支持热插拔技术,就算主机先开机工作,打印机后开机,Windows系统也会识别到USB口接入了打印机,进而发送固件给打印机。打印机在接收到固件后进行启动,这时我们会听到明显的自检轰鸣声。
但GDI打印机一般只提供了Windows下的驱动,将他们连接到Linux主机上并正常工作可不容易。有一些开源项目提供了Linux下的打印机驱动,配合CUPS打印服务器,就能让Debian、Radhat正常打印。最有名的开源项目是foo2zjx,里面的/osx-hotplug/osx-hplj-hotplug.m文件定义了九种HP打印机硬件特征码和对应的固件。阅读源代码,其中的0x03f0, 0x2b17, “/usr/share/foo2zjs/firmware/sihp1020.dl”,对应的就是HP Laserjet 1020打印机,它的固件文件名为sihp1020.dl。这些固件可以自己编译生成,也能在网上(http://oleg.wl500g.info/hplj/)下载到现成的。
我们通常只是用Openwrt或Padavan做一个小型的打印服务器。客户机的Windows系统本来就有驱动,所以这里只探索如何在GDI打印机热插入时,作为打印服务器的路由器能识别到打印机并发送固件,让打印机能正常工作。
查资料得知,Padavan用mdev来提供硬件热插拔支持。我用RT-N56U路由器(Padavan版本为3.4.3.9-099_20-10-2),经过不断实验,写了一个SHELL脚本,基本上实现了:
1. 读取设备特征,确定打印机型号,从网上下载对应的固件文件(对应 foo2zjx 里的九种HP打印机)。
2. 开机时发现连接了打印机,就发送固件给打印机。
3. 开机后插入打印机,系统能发现并发送固件给打印机。
把下面代码加入到“在路由器启动后执行”脚本的末尾,保存重启就可以了。
# 准备打印机热插拔时安装固件(从网上下载固件) turboYI 20210821
cat > “/var/usblp_hotplug.sh” <<-\EOF #!/bin/sh set -e HPLJSITE=http://oleg.wl500g.info/hplj LOGFILE=/var/usblp_hotplug.log FIRMWARE= if [ $# -eq 3 ]; then #这里用于开机时调用 DEVNAME=$1 ACTION=$2 DEVD=$3/../../.. else DEVD=/sys${DEVPATH}/../../.. fi if [ -f $DEVD/product ]; then product=`cat $DEVD/product` vid=`cat $DEVD/idVendor` pid=`cat $DEVD/idProduct` case $vid-$pid in 03f0-0517) FIRMWARE=sihp1000.dl ;; 03f0-1317) FIRMWARE=sihp1005.dl ;; 03f0-4117) FIRMWARE=sihp1018.dl ;; 03f0-2b17) FIRMWARE=sihp1020.dl ;; 03f0-3d17) FIRMWARE=sihpP1005.dl ;; 03f0-3e17) FIRMWARE=sihpP1006.dl ;; 03f0-4817) FIRMWARE=sihpP1005.dl ;; 03f0-4917) FIRMWARE=sihpP1006.dl ;; 03f0-3f17) FIRMWARE=sihpP1505.dl ;; esac if [ $FIRMWARE ]; then if [ ! -f /var/$FIRMWARE ]; then curl -o /var/$FIRMWARE $HPLJSITE/$FIRMWARE fi if [ -c /dev/$DEVNAME -a $ACTION = ‘add’ ]; then echo “$(date “+%Y-%m-%d %H:%M:%S”) : Sending $product firmware to $DEVNAME” > $LOGFILE
cat /var/$FIRMWARE > /dev/$DEVNAME
echo “$(date “+%Y-%m-%d %H:%M:%S”) : done.” >> $LOGFILE
fi
fi
fi
#调用Padavan原处理程序
if [ $# -eq 2 ]; then
/sbin/mdev_lp $MDEV $ACTION
fi
EOF
chmod a+x /var/usblp_hotplug.sh
sed -i ‘s/\/sbin\/mdev_lp/\/var\/usblp_hotplug.sh/’ /etc/mdev.conf
# 启动时如果检查到了打印机,就安装固件
if [ -c /dev/usb/lp0 ]; then
devpath=`find /sys/devices/platform/ehci-platform/ -name ‘lp0’ | grep ‘usb/lp0’`
if [ $? = 0 ]; then
/var/usblp_hotplug.sh usb/lp0 add $devpath
fi
fi
脚本文件下载:turboYI_mdev_usb_lp,解压后用记事本打开复制代码。
脚本运行正确的话,运行 cat /etc/mdev.conf 可以看到里面有 usb/lp[0-9] 0:0 0660 */etc/storage/usblp_hotplug.sh $MDEV $ACTION 这一行。
本脚本从 http://oleg.wl500g.info/hplj 下载固件文件。我从网上搜索到了这个分享了HP的GDI打印机固件的网站,感谢这个网站的主人为我们提供了方便!
如果路由器开机时能听到打印机自检声,说明生成的 /var/usblp_hotplug.sh 脚本是能正常工作的。
重新拔插USB插头后没有反应,说明系统没有发现设备硬件有改动。这可能是mdev热插拔处理程序没有起作用,可以查看 /etc/mdev.conf 配置文件,看里面是否有由 /var/usblp_hotplug.sh 脚本接管。
padavan原来 mdev.conf 文件内容如下:
#
sd[a-z] 0:0 0660 */sbin/mdev_sd $MDEV $ACTION
sd[a-z][0-9] 0:0 0660 */sbin/mdev_sd $MDEV $ACTION
usb/lp[0-9] 0:0 0660 */sbin/mdev_lp $MDEV $ACTION
sg[0-9] 0:0 0660 @/sbin/mdev_sg $MDEV $ACTION
sr[0-9] 0:0 0660 @/sbin/mdev_sr $MDEV $ACTION
weth[0-9] 0:0 0660 */sbin/mdev_net $MDEV $ACTION
wwan[0-9] 0:0 0660 */sbin/mdev_net $MDEV $ACTION
cdc-wdm[0-9] 0:0 0660 */sbin/mdev_wdm $MDEV $ACTION
ttyUSB[0-9] 0:0 0660 */sbin/mdev_tty $MDEV $ACTION
ttyACM[0-9] 0:0 0660 */sbin/mdev_tty $MDEV $ACTION
video[0-9] 0:0 0660
null 0:0 0666
zero 0:0 0666
full 0:0 0666
random 0:0 0666
urandom 0:0 0444
里面的关键行是
usb/lp[0-9] 0:0 0660 */sbin/mdev_lp $MDEV $ACTION
usb/lp[0-9]就是对应USB接口上的打印机设备,对应的热插拔处理程序是 /sbin/mdev_lp。mdev_lp是不能修改的系统文件。
上面的脚本里,用了这样的命令
sed -i ‘s/\/sbin\/mdev_lp/\/var\/usblp_hotplug.sh/’ /etc/mdev.conf
把usb/lp的默认处理程序修改成了我写的 /var/usblp_hotplug.sh 脚本,实现了接管——每当系统插入了USB打印机,就会执行。 /var/usblp_hotplug.sh 脚本的用途就是检测打印机型号,下载和发送正确的固件给打印机。
你可以用下面附件图片的的办法查看一下/etc/mdev.conf,是不是有这一行。如果没有,就核对一下`sed `那一句是否正确。插入脚本时,最好是下载附件解压后,用记事本打开turboYI_mdev_usb_lp.sh后复制脚本,避免字符错漏。
路由器和hp1020打印机同时开机的话,有可能是脚本运行的时候还没有检测到HP1020打印机,所以加载不了驱动。可以试一试给开机发送固件的代码套一个连续检测20秒的循环
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
if [ -c /dev/usb/lp0 ]; then
devpath=`find /sys/devices/platform/ehci-platform/ -name ‘lp0’ | grep ‘usb/lp0’`
if [ $? = 0 ]; then
/var/usblp_hotplug.sh usb/lp0 add $devpath
exit
fi
fi
sleep 1
done