turboYI 发表于 2021-8-21 17:18

Padavan插入HP的GDI打印机时自动发送固件的脚本

本帖最后由 turboYI 于 2021-8-22 12:51 编辑

我们用无线路由器共享打印机,最容易遇到打印服务开启了,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论坛的的代码编辑器模块会删除缩进,看起来很不爽,后面放一个源代码图片。脚本文件可以从附件下载,解压后用记事本打开复制代码。脚本运行正确的话,运行 cat /etc/mdev.conf 可以看到里面有 usb/lp 0:0 0660 */etc/storage/usblp_hotplug.sh $MDEV $ACTION 这一行。见后面的附图。

本脚本从 http://oleg.wl500g.info/hplj 下载固件文件。我从网上搜索到了这个分享了HP的GDI打印机固件的网站,感谢这个网站的主人为我们提供了方便!





邪恶海盗 发表于 2021-8-21 19:34

我记得之前谁提到过在路由上热插拔后会找不到打印机,然后他写了个脚本每10秒还是多长时间自动检测并连接打印机...

5566hyc 发表于 2021-8-21 20:20

谢谢分享!学习学习!

turboYI 发表于 2021-8-21 22:04

邪恶海盗 发表于 2021-8-21 19:34
我记得之前谁提到过在路由上热插拔后会找不到打印机,然后他写了个脚本每10秒还是多长时间自动检测并连接打 ...

    那种办法我原来也用过,但是轮询明显不如事件驱动好。
    现在这个脚本是利用linux的mdev的热插拔机制写的,只在系统开机时或插上打印机时调用一次。发送固件给打印机后,打印机会启动自检,因此可以用两个步骤来测试:
    步骤一:把脚本添加进去后保存重启路由器,如果这时路由器是插了打印机的,启动后能听到打印机的自检声。
    步骤二:从路由器上拔掉打印机USB插头,等几秒再插回去,也会再次听到打印机的自检声。

luang4089 发表于 2021-8-22 00:16

尝试了好几次,没有成功呢,开机有反应,重新插拔没有反应了

turboYI 发表于 2021-8-22 10:29

luang4089 发表于 2021-8-22 00:16
尝试了好几次,没有成功呢,开机有反应,重新插拔没有反应了

我大致分析一下。
如果路由器开机时能听到打印机自检声,说明生成的 /var/usblp_hotplug.sh 脚本是能正常工作的。
重新拔插USB插头后没有反应,说明系统没有发现设备硬件有改动。这可能是mdev热插拔处理程序没有起作用,可以查看 /etc/mdev.conf 配置文件,看里面是否有由 /var/usblp_hotplug.sh 脚本接管。
padavan原来 mdev.conf 文件内容如下:
# <device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]
sd 0:0 0660 */sbin/mdev_sd $MDEV $ACTION
sd 0:0 0660 */sbin/mdev_sd $MDEV $ACTION
usb/lp 0:0 0660 */sbin/mdev_lp $MDEV $ACTION
sg 0:0 0660 @/sbin/mdev_sg $MDEV $ACTION
sr 0:0 0660 @/sbin/mdev_sr $MDEV $ACTION
weth 0:0 0660 */sbin/mdev_net $MDEV $ACTION
wwan 0:0 0660 */sbin/mdev_net $MDEV $ACTION
cdc-wdm 0:0 0660 */sbin/mdev_wdm $MDEV $ACTION
ttyUSB 0:0 0660 */sbin/mdev_tty $MDEV $ACTION
ttyACM 0:0 0660 */sbin/mdev_tty $MDEV $ACTION
video 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:0 0660 */sbin/mdev_lp $MDEV $ACTION
usb/lp就是对应USB接口上的打印机设备,对应的热插拔处理程序是 /sbin/mdev_lp。mdev_lp是不能修改的系统文件。
我在1楼的脚本里,用了这样的命令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后复制脚本,避免字符错漏。


还有,脚本能在我的路由器上完美运行,并不能证明它能适应所有。希望试用过的朋友,回复一下路由器型号、Padavan的版本号、打印机型号和运行效果等信息,这才能促进我们来完善它。

luang4089 发表于 2021-8-22 15:05

turboYI 发表于 2021-8-22 10:29
我大致分析一下。
如果路由器开机时能听到打印机自检声,说明生成的 /var/usblp_hotplug.sh 脚本是能正 ...

非常感谢,用的最新版本H大固件已经测试成功,我的P1007,03f0-4817对应型号是p1007,自己修改了
另外第一次用可能需要重新启动路由器的打印机服务,可以解决未知不连机问题
我的测试过程中新版本热插拔偶尔不起作用,重启打印机可以自动解决,用时间测试吧,希望有个专用的固件就更好了

turboYI 发表于 2021-8-22 21:50

luang4089 发表于 2021-8-22 15:05
非常感谢,用的最新版本H大固件已经测试成功,我的P1007,03f0-4817对应型号是p1007,自己修改了
另外第 ...

其实 P1007和P1005用的是同一个固件,P1008和P1006用的也是同一个固件。开源项目foo2zjx里面的/osx-hotplug/osx-hplj-hotplug.m文件定义了硬件特征码和对应的固件。其中有关代码如下:HOTPLUG HotPlug[] =
{
    0x03f0,        0x0517,                "/usr/share/foo2zjs/firmware/sihp1000.dl",
    0x03f0,        0x1317,                "/usr/share/foo2zjs/firmware/sihp1005.dl",
    0x03f0,        0x4117,                "/usr/share/foo2zjs/firmware/sihp1018.dl",
    0x03f0,        0x2b17,                "/usr/share/foo2zjs/firmware/sihp1020.dl",

    0x03f0,        0x3d17,                "/usr/share/foo2xqx/firmware/sihpP1005.dl",
    0x03f0,        0x3e17,                "/usr/share/foo2xqx/firmware/sihpP1006.dl",
    0x03f0,        0x4817,                "/usr/share/foo2xqx/firmware/sihpP1005.dl",
    0x03f0,        0x4917,                "/usr/share/foo2xqx/firmware/sihpP1006.dl",
    0x03f0,        0x3f17,                "/usr/share/foo2xqx/firmware/sihpP1505.dl",
    0,                0,                NULL,        // Must be last
};我又找了个极路由3+Padavan3.4.3.9-099_21-08-14上试了HP Laserjie 1020,热插拔后能正常发送固件。
也希望又高人能解释有的机型有时会无法热插拔后发送固件的原因,并给出解决办法。如果有稳定的解决办法,就可以推荐老大们做成插件放到固件里了。

w7x8x 发表于 2021-8-28 18:12

turboYI 发表于 2021-8-22 21:50
其实 P1007和P1005用的是同一个固件,P1008和P1006用的也是同一个固件。开源项目foo2zjx里面的/osx-hotpl ...

请问高手,柯尼卡美能达打印机bizhub185 ,也是GDI打印机,有没有可能?

panda-soft 发表于 2021-8-29 22:27

canon 2900也是GDI打印机不,这个怎么整?

turboYI 发表于 2021-8-30 14:58

panda-soft 发表于 2021-8-29 22:27
canon 2900也是GDI打印机不,这个怎么整?

注意打印协议和端口,也许可以直接打印的。我身边没有Canon2900,没有办法实验:(

GDI打印机并非都是像HP的那几个机器一样需要热加载固件,纯GDI打印机只是要Windows下的GDI驱动程序来渲染图像,这样能省下需要解析PCL、PostScript等打印语言标准语法的带来的复杂性和存储器开销。

sqbzh 发表于 2021-9-5 23:25

能写个本地的脚本吗?如1020驱动以放在/etc/storage目录里,怕哪天网站挂了

turboYI 发表于 2021-9-6 14:05

sqbzh 发表于 2021-9-5 23:25
能写个本地的脚本吗?如1020驱动以放在/etc/storage目录里,怕哪天网站挂了

我的路由器只有8M,剩余空间装不下固件,才选择即用即下载。如果空间大,就可以把固件保存下来直接用。在脚本的第50、51、55行修改固件的路径到/etc/storage,保存脚本后,重启路由器。等固件下载完,打印机自检后,进路由器保存一下/etc/storage的内容,以后就不会重复下载了。改好的脚本如下:
# 准备打印机热插拔时安装固件(从网上下载固件) turboYI 20210906
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 /etc/storage/$FIRMWARE ]; then
            curl -o /etc/storage/$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 /etc/storage/$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

一般路由器上只会接一台打印机,如果路由器剩余空间很大,而且想以后完全不依赖网络下载固件,可以把7个固件文件全下载保存到/etc/storage/目录里。

linjinya 发表于 2021-9-6 15:40

turboYI 发表于 2021-8-22 10:29
我大致分析一下。
如果路由器开机时能听到打印机自检声,说明生成的 /var/usblp_hotplug.sh 脚本是能正 ...

hp1018 测试正常,非常感谢

loog2009 发表于 2021-9-9 10:34

路由器设置WIFI打印,打印文件一多系统就卡死,很鸡肋,当然用USB链接到路由器,驱动安装到电脑的没啥意思
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: Padavan插入HP的GDI打印机时自动发送固件的脚本