Saturday, June 26, 2010

Advanced Printer Sharing with hotplug

Hotplug is a set of scripts running upon certain predefined conditions. On today's Linux system, hotplug can do many things from auto mounting USB drive, pairing bluetooth devices to network configuration.

Seldom mentioned, but DD-WRT does offer (very preliminary) hotplug support. With almost no info on the web, the job is done by digging though DD-WRT's source code and various Linux documents.

  1. Replace DD-WRT's event handler with our own
    By default, DD-WRT registers /sbin/hotplug to handle all hotplug requests but the program, /sbin/hotplug doesn't follow standard hotplug rules, and, per my understanding, is a dummy and does nothing at all. So let's replace it with our own

    Create a startup script /opt/etc/init.d/hotplugd with only one line:

    echo /opt/sbin/hotplug > /proc/sys/kernel/hotplug

    Then set it to run upon start up
    chmod a+x /opt/etc/init.d/hotplugd
    ln -s /opt/etc/init.d/hotplugd /opt/etc/init.d/S95hotplugd

    run
    /opt/etc/init.d/hotplugd
    and check the result:
    cat /proc/sys/kernel/hotplug

    The output should be /opt/sbin/hotplug, which is our new event handler.

  2. Test drive hotplug
    So how does the hotplug work? below script will give you some idea to start with:
    Create /opt/sbin/hotplug with following:

    #!/bin/sh

    #For Debugging
    echo "Customized hotplug" >> /tmp/hotplug.log
    echo -------------$(date)----------- >> /tmp/hotplug.log
    set >> /tmp/hotplug.log

    set it as executable
    chmod a+x /opt/sbin/hotplug

    Unplug the printer, wait few seconds and plug the printer back.  Check the log by typing:
    cat /tmp/hotplug.log

    You can see there are bunch of environmental variables logged, two of them are worth noting:
    ACTION The value for "ACTION" variable can be "add" or "remove", corresponding to device plugin and removal.
    PRODUCT This is the unique device ID for the USB device, my printer is HP 1020 and value is 3f0/2b17/100.

    In a full Linux system, hotplug is much more complex. My script is a quick dirty hack but should be sufficient to handle USB printers.

  3. Configure hotplug to upload firmware to the printer
    Some GDI printer(aka Windows printer) will require extra work on Linux. Below is an example of my HP Laserjet 1020 but also applies to other HP laser printers like 1000, 1005, 1018, P1005, P1008, P1505 etc..
    You'll need two things to start with:
    The printer's firmware -- this must be in the printer before printing. Some of popular HP printers' can be downloaded from http://oleg.wl500g.info/hplj/
    usb_printerid -- this is used to detect if the firmware is already in place to prevent duplicated firmware uploading. Above link has one but that's for Broadcom devices. So I compile one for Atheros routers. Download here. Extract and put it to the router(samba, ftp or WinSCP).

    Assume we have the firmware in /opt/usr/local/lib/ and usb_printerid in /opt/usr/local/bin/, run
    chmod a+x /opt/usr/local/bin/usb_printerid

    And finally, here is the full script /opt/sbin/hotplug

    #!/bin/sh

    #For Debugging
    #echo "Customized hotplug" >> /tmp/hotplug.log
    #echo -------------$(date)----------- >> /tmp/hotplug.log
    #set >> /tmp/hotplug.log

    P910ND='/opt/usr/sbin/p910nd'
    PRINTERID='/opt/usr/local/bin/usb_printerid'
    FIRMWARE='/opt/usr/local/lib/sihp1020.dl'
    #replace it with your printer's firmware.

    if [ $DEVTYPE == 'usb_device' ] && [ $PRODUCT == '3f0/2b17/100' ]; then
    #replace with your printer's device id.
      if [  $ACTION == 'add' ]; then
        #check and upload firmware
        ${PRINTERID} /dev/usb/lp0 | grep -q FWVER || cat ${FIRMWARE} > /dev/usb/lp0
        #kill and restart p910nd
        kill -9 $(pidof p9100d)
        ${P910ND}  -b -f /dev/usb/lp0 0
      fi

      if [ $ACTION == 'remove' ]; then
        #printer removed, lets stop p910nd
        kill -9 $(pidof p9100d)
      fi
    fi

    The above script will upload firmware to printer then start p910nd daemon upon printer plug-in and stop p910nd when it's removed.

  4. Modified p910nd startup script
    With above script, DD-WRT will automatically configure the printer after the router is fully booted. However, similar approach has to be done during startup as the hotplug does not take effect at that moment.
    For unknown reasons, DD-WRT will NOT create /dev/usb/lp0 for printer even we have printer support enabled. As a result, we can't use this device node to detect the printer's presence.

    Here is a modified version of /opt/etc/init.d/p910nd startup script.

    source /mnt/root/.profile

    mkdir -m 755 -p /dev/usb
    mknod -m 660 /dev/usb/lp0 c 180 0
    sleep 1

    P910ND='/opt/usr/sbin/p910nd'
    PRINTER_ID='/opt/usr/local/bin/usb_printerid'
    FIRMWARE='/opt/usr/local/lib/sihp1020.dl'
    #replace with yours
    PNAME='LaserJet'
    #printer name id string, see below

    i=$(find /sys/devices/platform/ -name product -exec cat {} \; | grep -c ${PNAME})

    if [ $i != '0' ]; then
         ${PRINTER_ID} /dev/usb/lp0 | grep -q FWVER || cat ${FIRMWARE} > /dev/usb/lp0
         kill -9 `pidof p9100d`
         ${P910ND}  -b -f /dev/usb/lp0 0
    fi

    Notice the PNAME='LaserJet' line. The 'LaserJet" is part of the printer's name and can be used to check if the printer is plugged. To determine yours, run

    find /sys/devices/platform/ -name product -exec cat {} \;

    The result looks like that:
    HP LaserJet 1020 #printer
    DataTravelerMini #USB flash drive
    Atheros AR91xx built-in EHCI controller #USB controller

After that, follow the previous tutorial to install printer in Windows if you haven't done so. Now enjoy the convenience of hotplug.

6 comments:

Anonymous said...

I searched thru the web just for this bit of info - could not find anywhere....
Thanks a lot.
I use dd-wrt on Asus router. I needed to send my FW to my GDI printer (HP LaserJet 1018) the hotplug way....
Keep up the good work.
BTW, your blog is so methodical as opposed to dd-wrt site which is full of confusing/contradictory/obsolete information.
Regards.

Anonymous said...

I am using your script to automatically start and kill samba once my hard disk is attached to the router. Mounting the partitions via hotplug and killing samba on remove works fine.
Unfortunately, the script fails to run samba for some reason. I am using the command "smbd -s /opt/etc/samba/smb.conf" from your previous tutorial. The command works fine from command line but not from within the script. I also tried using the absolute path to the smbd binary with no success. Any ideas?

Anonymous said...

I found out that when using id in the hotplug-script the entry "groups" is missing:

#normal output:
root $ id
uid=0(root) gid=0(root) groups=0(root)

#from script:
uid=0(root) gid=0(root)

I guess that is an issue for Samba. Can this be fixed?

go4download said...

have found an expert..wonderful and you have resolved my issue
hp laserjet 1020

HP LaserJet 1020 said...

GDI printer(aka Windows printer) will require extra work on Linux. Below is an example of my HP Laserjet 1020 but also applies to other HP laser printers like 1000, 1005, 1018, P1005, P1008, P1505 etc..

Apk Galaxy said...

Nice Thanks Alot For sharing

Post a Comment