Review of an MT-ViKI 2-port automatic KVM switch

Three years ago I bought a two-port KVM (keyboard, video and mouse) switch with the intention of using it to connect my keyboard and monitor to my headless server to investigate a boot-up problem. But I found the cause of the problem quickly and never needed to use the KVM switch, which was sitting on a shelf ever since.

Recently I bought a cheap second-hand desktop machine for another project and, rather than having a second keyboard, mouse and monitor on my desk, I decided to use the spare KVM switch.

Schematic diagram of connections to MT-261KL KVM switch

Schematic diagram of connections to MT-261KL KVM switch.

The KVM switch was manufactured by MT-ViKI Electronic Technology Co., Ltd, a Chinese company that manufactures a range of KVM switches. The model I bought is the MT-261KL-FBA AUTO KVM USB+AUDIO. It has two DE-15 input ports for connection to two computers using the custom cables provided, a DE-15 VGA output port, an audio Line-Out port, a Microphone port and three USB 2.0 ports. Two cables with pigtails were supplied with the switch. At one end of each cable there is a DE-15 (VGA) plug, a pigtail with a USB Type-A plug, a pigtail with a 3.5 mm Line-In plug and a pigtail with a 3.5 mm Microphone plug. All these are for connection to the computer. At the other end of each cable is a DE-15 plug, which is for connection to one of the DE-15 ports labelled PC1 and PC2 on the KVM switch. Video, audio and USB signals are all transferred via this DE-15 plug at the KVM switch end. The device does not require an external power supply unit, so I assume it is powered from either of the two computers’ USB ports.

The two custom cables supplied with the MT-261KL KVM switch

The two custom cables supplied with the MT-261KL KVM switch.

MT-261KL KVM switch with cables connected

MT-261KL KVM switch with cables connected.

Left end of MT-261KL KVM switch with audio sockets

Left end of MT-261KL KVM switch with audio sockets.

VGA, USB, Line Out and Mic plugs of MT-261KL custom cable connected to desktop

VGA, USB, Line Out and Mic plugs of MT-261KL custom cable connected to desktop.

VGA, USB, Line Out and Mic plugs of MT-261KL custom cable connected to laptop

VGA, USB, Line Out and Mic plugs of MT-261KL custom cable connected to laptop.

My USB keyboard and USB mouse are plugged into two of the three USB ports on the KVM switch. I can switch them and the monitor between the two computers either by pressing a push-button on top of the KVM switch or by pressing specific keyboard keys in sequence within 2 seconds of each other:

  • Scroll Lock + Scroll Lock + 1 (or 2) to select PC port directly
  • Scroll Lock + Scroll Lock + Down Arrow to select Next Port
  • Scroll Lock + Scroll Lock + Up Arrow to select Previous Port
  • Scroll Lock + Scroll Lock + S to select Auto Scan
  • Scroll Lock + Scroll Lock + B to toggle Beep On/Off
  • ESC to exit Auto Scan mode

Two LEDs on the KVM switch are used to indicate which computer is currently connected to the keyboard, monitor and mouse. The loud beep that the switch emits when switching from one computer to the other can be disabled if desired.

This switch supports monitor resolutions up to 2048 x 1536, and I’m using 1920 x 1080 in both OSs. Any monitor that supports a VGA connection should work. My monitor happens to be a 23-inch ViewSonic VX2363SMHL which has both VGA and HDMI sockets and cables. Any USB keyboard and mouse should work; I’m using an HP K45 keyboard and a Logitech M90 mouse. My laptop runs Gentoo Linux and the desktop runs Windows 10, and the switch works fine with both machines.

Although the custom cables between the KVM switch and the computers are quite bulky and stiff, I managed to connect everything to the KVM switch with it in a convenient position on my desk. Selecting the computer from the keyboard instead of the push-button on the KVM switch is easier, though. There is somewhat of a ‘cable spaghetti’ on my desk due to all the cables, but I have arranged them as tidily as possible. The audio sockets on my laptop are on the opposite side of the laptop to the VGA socket, which does not help. Fortunately the audio jack plug cables that branch out of the custom cable are just long enough to reach the Headphone and Mic sockets on the laptop.

There is a third USB port on the KVM switch, that I am not using. It would be possible to use this third USB port to connect another USB device (a printer, for example) that could be switched between the two computers. As there is only one USB connection to each computer, the KVM switch must be acting as a USB hub.

I have not yet connected an external microphone to the KVM switch, but I do have my external stereo powered speakers connected to it. The audio from the external speakers connected via the switch is still OK, although some noise is being picked up from all the cables on and under my desk. But I believe that is as much to do with the long thin unshielded audio cable from the powered speakers (Logitech X-140 Multimedia speakers, not of high quality). I suspect a shorter, shielded cable would perform much better.

Anyway, if you ever need a KVM switch that supports a monitor with a VGA port, this model is reasonable. MT-ViKI also make switches that can switch a keyboard, monitor and mouse between more than two computers, and switches with HDMI ports if you want to switch a keyboard, monitor and mouse between computers that do not have VGA ports. By the way, I have no association with the company.

Digital audio fidelity

Take the following two hearing tests while wearing high-quality over-ear headphones connected to a high-quality sound card:

The first tests your ability to hear sound of different frequencies. Older people will be doing well if they can hear up to 15 kHz. A lot of older people can’t even hear up to that; in one ear I can hear 10 kHz and I think I can hear 14 kHz in the other.

The second tests your ability to discern audio quality (quantisation and sample frequency). My score was 33%!

Those tests are eye-openers. My family did a lot better than me, especially the younger members. One of them could hear above 20 kHz in the first test, and scored 100% in the second test (which is exceptional because all the others scored 50%, so even young people struggle to hear a difference).

Even with my poor hearing I can hear how bad a 128 kb/s mp3 music track sounds, but when you get up to 320 kb/s it’s a different matter. In most cases I can’t hear the difference between 320 kb/s and a 16-bit 44.1 kHz Audio CD, and, as the tests in the above links demonstrate, most people struggle to tell the difference too (watch the video ‘Audiophile or Audio-Fooled? How Good Are Your Ears?‘).

Regarding sampling theory, the video ‘Digital Audio: The Line Between Audiophiles and Audiofools‘ is quite good if someone does not understand why 16-bit 44.1 kHz was chosen for Audio CDs. As to finer quantisation and higher frequencies, ‘The Difference Between 24-bit & 16-bit Audio is Inaudible Noise‘.

As to the perennial discussion regarding CD audio versus vinyl audio, an audiophile friend of mine with a life-long passion for hi-fi has an insanely expensive hi-fi system which is integrated throughout his house – including a room designed exclusively for listening to music – and controlled via iPads, with hand-built pre-amps imported from a small, specialist manufacturer. His main speakers alone cost a lot more than most people pay for an expensive sound system. He switched to dedicated music servers with uncompressed (FLAC and WAV) files either purchased directly or copied from well-produced 16-bit 44.1 kHz Audio CDs, and got rid of his expensive top-end record deck.

As for legacy physical media, Audio CDs are more vulnerable than vinyl. Some of the Audio CDs I bought around 20 years ago have already suffered the well-known phenomenon of disc rot despite being carefully kept and handled. Optical discs are rubbish from a longevity point of view. Vinyls, on the other hand, if kept in a controlled environment, will last almost indefinitely: ‘Record collector builds world’s largest vinyl hoard – six million and counting‘.

However, much as I love LP artwork I’d rather have my friend’s digital system any day. Even with my degraded hearing the music it produces sounds fabulous. Not to mention that the slightest click from a dust particle in an LP groove is, to me, akin to nails scraping on a blackboard. Those were the days!

Configuration of the APC UPS Daemon on my Linux server

 

UPS connections in my home network

For obvious reasons my Linux home server supplying NAS and Web services 24/7 is connected to a UPS. The UPS model (now discontinued) I use is a 700VA 230V APC Back-UPS ES-BE700G-UK. It is connected to one of the server’s USB ports via an APC-supplied cable so that the server can interrogate the UPS and so that the UPS can send unsolicited messages to the server (e.g. mains power supply interrupted, mains power supply restored, shut down the server now, and so on). The open-source APC UPS Daemon apcupsd that I installed on the server enables the server to react automatically to UPS events. apcupsd provides a shell script apccontrol and various other shell scripts to act on these events. All these scripts can be customised by the user. As users with an APC UPS that supports this functionality are likely to be interested in configuration of apcupsd, I think it might be useful for me to explain how I configured apcupsd.

An Ethernet switch and an external USB 6 TB HDD (connected to the server for automated daily backups) are in the same room as the server and also connected to the UPS. If my router were in the same room as the server then it would be connected to the same UPS as the server but, as it has to be in a different room next to the broadband provider’s master socket, it is instead connected to a separate mini UPS so that the server can still send e-mails after an interruption to the mains power supply.

Before getting into the configuration of apcupsd, I should mention that I have come across some home users who think the purpose of a UPS is solely to protect against loss of mains supply from the electricity utility company. Whilst that is one of the purposes of a UPS, home users should note that home fuses can blow and RCD consumer units can trip even when there is no interuption to the mains supply to the house from the utility company. So the argument that the local utility company is extremely reliable is not a reason to dispense with a UPS for a server. Well, not unless you are prepared to accept the risk of corruption of the OS and/or users’ data.

It is possible to configure apcupsd to perform a controlled shutdown of a server if the mains power supply to a UPS has been interrupted for a user-specified amount of time or if the UPS battery’s remaining charge has dropped to a user-specified percentage of its full capacity. If desired, it would also be possible to configure apcupsd and a server’s firmware to reboot the server automatically once mains power has been restored to the UPS following an earlier controlled shutdown of the server (see ‘Arranging for Reboot on Power-Up‘ in the APCUPSD User Manual). However, as I am often away from home on work trips and cannot immediately check what has happened, I do not want the server to reboot automatically when there is power to the server, in case the mains power supply is intermittent for whatever reason. Instead, after receiving an e-mail from the server informing me it is shutting down, I would phone home and ask a family member what has happened and, if I were satisfied everything is now OK, I would then ask them to power up the server. Therefore I configured the server’s BIOS not to reboot automatically if there is power to the server after it has been shut down.

Although apcupsd offers a mechanism to tell the UPS to go into hibernation, I am not interested in trying to get the UPS to hibernate once the OS shuts down, because I do not want to risk the UPS going into hibernation before my server has shutdown the OS completely and powered down the server. Furthermore, the server is not the only device powered by the UPS. Therefore, if there were a long delay until the mains power supply to the UPS is restored, the UPS would continue to supply power until its battery is flat. However, it is unlikely the power supply to the UPS would be down for long, so the possibility of draining the battery completely is unlikely once the server has been powered down; power to the UPS will usually be restored before the battery is flat. The power requirement of the tiny Ethernet switch is small and the external USB HDD goes to sleep automatically after a few minutes of inactivity anyway. It is more important that the server is powered down ‘gracefully’.

The mechanism an OS would use to tell a UPS to go into hibernation is the command ‘/sbin/apcupsd --killpower‘, when apcupsd runs the killpower script. My understanding of the intended process is as follows:

  1. The mains supply to the UPS ceases.
  2. The UPS tells apcupsd that the mains supply has ceased.
  3. apcupsd uses $BATTERYLEVEL, $MINUTES, and $TIMEOUT (set in /etc/apcupsd.conf) to determine when to shutdown the OS (the next step below).
  4. apcupsd runs /etc/apcupsd/doshutdown to initiate shutdown of the OS.
  5. After the OS initiates shutdown, apcupsd (which runs /etc/apcupsd/killpower) tells the UPS to go into hibernation. I think the message to tell the UPS to hibernate is sent $KILLDELAY seconds after /etc/apcupsd/doshutdown runs, where $KILLDELAY is user-configurable. In the case of Gentoo Linux, the apcupsd.powerfail init script (if the user has enabled it) tries to put the UPS into hibernation when the OS is in Runlevel 0 and the OS has almost completed shutting down (the file systems have already been mounted Read-Only).

The message telling the UPS to hibernate can be disabled by setting KILLDELAY=0 in /etc/apcupsd.conf, which I have done. And, just to be sure, I also modified the script /etc/apcups/killpower to do the same thing as the script /etc/apcupsd/doshutdown, and I configured the server’s BIOS not to boot automatically when power is supplied to the server.

I think my caution and disabling of killpower are justified, as the APCUPSD User Manual states:

KILLDELAY time in seconds
If KILLDELAY is set, apcupsd will continue running after a shutdown has been requested, and after the specified time in seconds, apcupsd will attempt to shut off the UPS the power. This directive should normally be disabled by setting the value to zero, but on some systems such as Win32 systems apcupsd cannot regain control after a shutdown to force the UPS to shut off the power. In this case, with proper consideration for the timing, the KILLDELAY directive can be useful. Please be aware, if you cause apcupsd to kill the power to your computer too early, the system and the disks may not have been properly prepared. In addition, apcupsd must continue running after the shutdown is requested, and on Unix systems, this is not normally the case as the system will terminate all processes during the shutdown.

The as-installed configuration file apcupsd.conf contained the following settings:

$ grep -v "^#\|^;\|^$" /etc/apcupsd/apcupsd.conf.original
UPSCABLE smart
UPSTYPE apcsmart
DEVICE /dev/ttyS0
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd
PWRFAILDIR /etc/apcupsd
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 5
MINUTES 3
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 0
STATFILE /var/log/apcupsd.status
LOGSTATS off
DATATIME 0

The purposes of BATTERYLEVEL, MINUTES and TIMEOUT are explained in the configuration file’s comments:

[...]
#
# Note: BATTERYLEVEL, MINUTES, and TIMEOUT work in conjunction, so
# the first that occurs will cause the initation of a shutdown.
#

# If during a power failure, the remaining battery percentage
# (as reported by the UPS) is below or equal to BATTERYLEVEL,
# apcupsd will initiate a system shutdown.
BATTERYLEVEL 30
# Was 10 but I changed it to 30.

# If during a power failure, the remaining runtime in minutes
# (as calculated internally by the UPS) is below or equal to MINUTES,
# apcupsd, will initiate a system shutdown.
MINUTES 10
# Was 3 but I changed it to 10.

# If during a power failure, the UPS has run on batteries for TIMEOUT
# many seconds or longer, apcupsd will initiate a system shutdown.
# A value of 0 disables this timer.
#
#  Note, if you have a Smart UPS, you will most likely want to disable
#    this timer by setting it to zero. That way, you UPS will continue
#    on batteries until either the % charge remaing drops to or below BATTERYLEVEL,
#    or the remaining battery runtime drops to or below MINUTES.  Of course,
#    if you are testing, setting this to 60 causes a quick system shutdown
#    if you pull the power plug.
#  If you have an older dumb UPS, you will want to set this to less than
#    the time you know you can run on batteries.
TIMEOUT 0

[...]

 

Lead-acid batteries degrade faster if they are allowed to become flat or nearly flat, so I changed the battery level percentage to 30 instead of 10. I also changed the remaining runtime (as calculated by the UPS) from 3 minutes to 10 minutes. The resulting contents of apcupsd.conf are as follows:

$ grep -v "^#\|^;\|^$" /etc/apcupsd/apcupsd.conf
UPSNAME ES700
UPSCABLE usb
UPSTYPE usb
DEVICE
POLLTIME 60
LOCKFILE /var/lock
SCRIPTDIR /etc/apcupsd
PWRFAILDIR /etc/apcupsd
NOLOGINDIR /etc
ONBATTERYDELAY 6
BATTERYLEVEL 30
MINUTES 10
TIMEOUT 0
ANNOY 300
ANNOYDELAY 60
NOLOGON disable
KILLDELAY 0
NETSERVER on
NISIP 127.0.0.1
NISPORT 3551
EVENTSFILE /var/log/apcupsd.events
EVENTSFILEMAX 10
UPSCLASS standalone
UPSMODE disable
STATTIME 300
STATFILE /var/log/apcupsd.status
LOGSTATS off
DATATIME 0

I also edited the apccontrol script to: a) fix a typo in a message in the script; b) comment out the command to reboot the server; c) comment out the command to shutdown the server (as my version of the doshutdown script performs that task):

$ diff /etc/apcupsd/apccontrol /etc/apcupsd/apccontrol.original 
90c90
<       echo "Battery power exhausted on UPS ${2}. Doing shutdown." | ${WALL}
---
>       echo "Battery power exhaused on UPS ${2}. Doing shutdown." | ${WALL}
103c103
< #     ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
---
>       ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
107c107
< #     ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
---
>       ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
$ cat /etc/apcupsd/apccontrol
#!/bin/sh
#
# Copyright (C) 1999-2002 Riccardo Facchetti 
#
#  for apcupsd release 3.14.10 (13 September 2011) - debian
#
# platforms/apccontrol.  Generated from apccontrol.in by configure.
#
#  Note, this is a generic file that can be used by most
#   systems. If a particular system needs to have something
#   special, start with this file, and put a copy in the
#   platform subdirectory.
#

#
# These variables are needed for set up the autoconf other variables.
#
prefix=/usr
exec_prefix=${prefix}

APCPID=/var/run/apcupsd.pid
APCUPSD=/sbin/apcupsd
SHUTDOWN=/sbin/shutdown
SCRIPTSHELL=/bin/sh
SCRIPTDIR=/etc/apcupsd
WALL=wall

#
# Concatenate all output from this script to the events file
#  Note, the following kills the script in a power fail situation
#   where the disks are mounted read-only.
# exec >>/var/log/apcupsd.events 2>&1

#
# This piece is to substitute the default behaviour with your own script,
# perl, or C program.
# You can customize every single command creating an executable file (may be a
# script or a compiled program) and calling it the same as the $1 parameter
# passed by apcupsd to this script.
#
# After executing your script, apccontrol continues with the default action.
# If you do not want apccontrol to continue, exit your script with exit 
# code 99. E.g. "exit 99".
#
# WARNING: the apccontrol file will be overwritten every time you update your
# apcupsd, doing `make install'. Your own customized scripts will _not_ be
# overwritten. If you wish to make changes to this file (discouraged), you
# should change apccontrol.sh.in and then rerun the configure process.
#
if [ -f ${SCRIPTDIR}/${1} -a -x ${SCRIPTDIR}/${1} ]
then
    ${SCRIPTDIR}/${1} ${2} ${3} ${4}
    # exit code 99 means he does not want us to do default action
    if [ $? = 99 ] ; then
        exit 0
    fi
fi

case "$1" in
    killpower)
        echo "Apccontrol doing: ${APCUPSD} --killpower on UPS ${2}" | ${WALL}
        sleep 10
        ${APCUPSD} --killpower
        echo "Apccontrol has done: ${APCUPSD} --killpower on UPS ${2}" | ${WALL}
    ;;
    commfailure)
        echo "Warning communications lost with UPS ${2}" | ${WALL}
    ;;
    commok)
        echo "Communications restored with UPS ${2}" | ${WALL}
    ;;
#
# powerout, onbattery, offbattery, mainsback events occur
#   in that order.
#
    powerout)
    ;;
    onbattery)
        echo "Power failure on UPS ${2}. Running on batteries." | ${WALL}
    ;;
    offbattery)
        echo "Power has returned on UPS ${2}..." | ${WALL}
    ;;
    mainsback)
        if [ -f /etc/apcupsd/powerfail ] ; then
           printf "Continuing with shutdown."  | ${WALL}
        fi
    ;;
    failing)
        echo "Battery power exhausted on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    timeout)
        echo "Battery time limit exceeded on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    loadlimit)
        echo "Remaining battery charge below limit on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    runlimit)
        echo "Remaining battery runtime below limit on UPS ${2}. Doing shutdown." | ${WALL}
    ;;
    doreboot)
        echo "UPS ${2} initiating Reboot Sequence" | ${WALL}
#       ${SHUTDOWN} -r now "apcupsd UPS ${2} initiated reboot"
    ;;
    doshutdown)
        echo "UPS ${2} initiated Shutdown Sequence" | ${WALL}
#       ${SHUTDOWN} -h now "apcupsd UPS ${2} initiated shutdown"
    ;;
    annoyme)
        echo "Power problems with UPS ${2}. Please logoff." | ${WALL}
    ;;
    emergency)
        echo "Emergency Shutdown. Possible battery failure on UPS ${2}." | ${WALL}
    ;;
    changeme)
        echo "Emergency! Batteries have failed on UPS ${2}. Change them NOW" | ${WALL}
    ;;
    remotedown)
        echo "Remote Shutdown. Beginning Shutdown Sequence." | ${WALL}
    ;;
    startselftest)
    ;;
    endselftest)
    ;;
    battdetach)
    ;;
    battattach)
    ;;
    *)  echo "Usage: ${0##*/} command"
        echo "       warning: this script is intended to be launched by"
        echo "       apcupsd and should never be launched by users."
        exit 1
    ;;
esac

I made sure the /etc/apcupsd/hosts.conf file specifies the daemon is monitoring the server:

$ grep -v "^#\|^;\|^$" hosts.conf 
MONITOR 127.0.0.1 "Local Host"

I configured the scripts in /etc/apcupsd/ as shown in the listings below (I have obscured my e-mail address for security reasons). Note that the firewall for my server is a virtual machine (with hostname serverfw) on the server, hence the additional command to shutdown the virtual machine too.

$ cat /etc/apcupsd/annoyme 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# starts sending out 'annoy me' messages.
#
cat /home/fitzcarraldo/apcups/ups-email-annoyme.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-annoyme.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS is sending 'annoy me' messages - investigate now.

 

$ cat /etc/apcupsd/changeme 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery should be replaced.
#
cat /home/fitzcarraldo/apcups/ups-email-changeme.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-changeme.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS battery needs to be changed.

 

$ cat /etc/apcupsd/commfailure 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# loses contact with the UPS (i.e. the serial connection is not responding).
#
cat /home/fitzcarraldo/apcups/ups-email-commfailure.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-commfailure.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Host has lost communication to the UPS.

 

$ cat /etc/apcupsd/commok 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# restores contact with the UPS (i.e. the serial connection is restored).
#
cat /home/fitzcarraldo/apcups/ups-email-commok.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-commok.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Host to UPS communication has resumed.

 

$ cat /etc/apcupsd/doreboot 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# requests a reboot. We do nothing - the APC must not request a reboot.
#
# This script should never be run, as I commented it out in apccontrol.
cat /home/fitzcarraldo/apcups/ups-email-doreboot.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-doreboot.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS has requested a reboot - doing nothing.

 

$ cat /etc/apcupsd/doshutdown 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that a  shutdown is needed.
#
cat /home/fitzcarraldo/apcups/ups-email-doshutdown.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-doshutdown.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS requested shutdown, shutting down the systems.

The server has to be powered up manually after it has powered down.
It will not boot automatically when the mains power supply is restored.

 

$ cat /etc/apcupsd/emergency 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that an emergency shutdown is needed.
#
cat /home/fitzcarraldo/apcups/ups-email-emergency.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-emergency.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS emergency shutdown requested, shutting down the systems.

 

$ cat /etc/apcupsd/failing 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery charge is below the minimum level.
#
cat /home/fitzcarraldo/apcups/ups-email-failing.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-failing.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS battery is failing, shutting down the systems.

 

$ cat /etc/apcupsd/killpower 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol before
# apcupsd kills the power in the UPS. You probably
# need to edit this to mount read-only /usr and /var,
# otherwise apcupsd will not run.
#
cat /home/fitzcarraldo/apcups/ups-email-killpower.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-killpower.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The APC daemon is powering off the UPS - shutting down the systems.

Actually the APC daemon does not power off the UPS since I edited
/etc/apcupsd/killpower so that it only performs the same actions
as /etc/apcupsd/doshutdown, namely 'shutdown -h now'. This means
the UPS continues to supply output power until the battery has
run down completely if there is a long delay until the mains power
supply is restored. The server has to be powered up manually if
it has powered down; it will not boot automatically when the mains
power supply is restored.

 

$ cat /etc/apcupsd/loadlimit 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the remaining battery charge is below the min threshold.
#
cat /home/fitzcarraldo/apcups/ups-email-loadlimit.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-loadlimit.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

UPS battery charge below threshold, shutting down the systems.

 

$ cat /etc/apcupsd/mainsback 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the mains has returned with /etc/apcupsd/powerfail
# file created.
#
cat /home/fitzcarraldo/apcups/ups-email-mainsback.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-mainsback.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Mains back on UPS.

 

$ cat /etc/apcupsd/offbattery 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when the
# UPS goes back on to the mains after a power failure.
#
cat /home/fitzcarraldo/apcups/ups-email-offbattery.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-offbattery.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power resumed to UPS. No longer running on batteries.

 

$ cat /etc/apcupsd/onbattery 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when the UPS
# goes on batteries.
#
cat /home/fitzcarraldo/apcups/ups-email-onbattery.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-onbattery.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power failure on UPS. Running on batteries.

 

$ cat /etc/apcupsd/powerout 
#!/bin/sh
cat /home/fitzcarraldo/apcups/ups-email-powerout.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-powerout.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Power out on UPS.

 

$ cat /etc/apcupsd/remoteshutdown 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# is being shut down remotely - should never happen so do nothing.
#
cat /home/fitzcarraldo/apcups/ups-email-remoteshutdown.txt | /usr/sbin/sendmail -4 -t
exit 0
$ cat ~/apcups/ups-email-remoteshutdown.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

Remote UPS shutdown requested - do nothing but investigate.

 

$ cat /etc/apcupsd/runlimit 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the remaining battery run time is below the threshold.
#
cat /home/fitzcarraldo/apcups/ups-email-runlimit.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-runlimit.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS remaining run time is below limit, shutting down the systems.

 

$ cat /etc/apcupsd/timeout 
#!/bin/sh
#
# This shell script if placed in /etc/apcupsd
# will be called by /etc/apcupsd/apccontrol when apcupsd
# detects that the battery run time limit has been exceeded.
#
cat /home/fitzcarraldo/apcups/ups-email-timeout.txt | /usr/sbin/sendmail -4 -t
sudo -u fitzcarraldo ssh serverfw sudo shutdown -h now
sleep 30
shutdown -h now
exit 0
$ cat ~/apcups/ups-email-timeout.txt
To: fitzcarraldo@xxxxx.com
From: fitzcarraldo@xxxxx.com
Subject: Important message about Back-UPS ES 700

The UPS run time limit is exceeded, shutting down the systems

 

$ cat /etc/apcupsd/ups-monitor
#!/bin/sh
case "$1" in
        poweroff | killpower)
                if [ -f /etc/apcupsd/powerfail ]; then
                        echo ""
                        echo -n "apcupsd: Ordering UPS to kill power... "
                        /etc/apcupsd/apccontrol killpower
                        echo "done."
                        echo ""
                        echo "Please ensure the UPS has powered off before rebooting."
                        echo "Otherwise, the UPS may cut the power during the reboot!"
                        echo ""
                fi
        ;;
        *)
        ;;
esac
exit 0

 

How to prevent CUPS omitting the bottom of the CUPS Printer test page

This is something that has been bugging me for years but I never bothered to look into it until now. When I set up a printer using CUPS Administration and then print a test page, for some printers the bottom of the test page image is cut off, as shown in the scanned image below. Also, the left side of the test page image is too close to the left side of the sheet of paper. This happens when I use the Gutenprint printer drivers, although I do not know if that is a coincidence. The CUPS printer test page (A4 paper) shown below is from a Canon PIXMA MP510 printer using the Gutenprint v5.3.3 driver for that model.

Printer test page printed by CUPS before modifying the Canon PIXMA MP510 PPD file

I had a look at the values of the ImageableArea for A4 paper in the printer’s PPD file, and the as-installed values were as follows:

user $ sudo grep "ImageableArea A4" /etc/cups/ppd/MP510.ppd
*ImageableArea A4/A4:   "0.000 0.000 595.000 842.000"

I then edited the PPD file and changed the x,y coordinates of the bottom left of the imageable area from 0,0 to 10,3 for A4 paper so the file now contains the following:

user $ sudo grep "ImageableArea A4" /etc/cups/ppd/MP510.ppd
*ImageableArea A4/A4:   "10.000 3.000 595.000 842.000"

It is necessary to restart CUPS when a change is made to the PPD file:

Gentoo Linux installation using OpenRC

user $ sudo rc-service cupsd restart

Lubuntu 20.10 installation using systemd

user $ sudo systemctl restart cups

Now the ‘Printer test page’ printed by CUPS looks like this:

Printer test page printed by CUPS after modifying the Canon PIXMA MP510 PPD file

Much better.
 
 
ADDENDUM (2 May 2021): I have discovered that the ImageableArea is not the only factor…

I also have a Canon PIXMA MP560 printer, and I printed a CUPS ‘Printer test page’ on that using the Gutenprint v5.3.3 driver for the Canon PIXMA MP560. A scan of the printed test page is shown below:

Printer test page printed by CUPS before modifying the Canon PIXMA MP560 PPD file

The as-installed values of the ImageableArea for A4 paper in the printer’s PPD file were as follows:

user $ sudo grep "ImageableArea A4" /etc/cups/ppd/Canon_MP560_Wi-Fi.ppd
*ImageableArea A4/A4:   "0.000 0.000 595.000 842.000"

Unlike the original test page for the Canon PIXMA MP510, the vertical lines on the left and right sides of the test image are more or less equidistant from the edges of the paper. However, as with the original test page for the Canon PIXMA MP510, the bottom line of the test page was missing. So I tried editing the y coordinate of the bottom left of the ImageableArea in the PPD file for the Canon PIXMA MP560. However, whatever value I used for the y coordinate of the bottom left of the test image, the bottom line was never printed.

I then looked at the contents of the file /etc/cups/printers.conf and found that the configuration for the Canon PIXMA MP510 included a line ‘Option fitplot True‘ whereas the configuration for the Canon PIXMA MP560 did not:

# Printer configuration file for CUPS v2.3.3
# Written by cupsd
# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING
NextPrinterId 3
<Printer Canon_MP560_Wi-Fi>
PrinterId 2
UUID urn:uuid:428a074e-0e81-3ba3-7789-f8050da82c5a
Info Canon MP560 Wi-Fi
Location My office upstairs
MakeModel Canon PIXMA MP560 - CUPS+Gutenprint v5.3.3
DeviceURI lpd://192.168.1.78/lpt1
State Idle
StateTime 1619978009
ConfigTime 1619880075
Type 36892
Accepting Yes
Shared No
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy retry-job
</Printer>
<DefaultPrinter MP510>
PrinterId 1
UUID urn:uuid:0a2a12b5-ea49-33eb-572a-341c1af02f7e
Info Canon MP510
Location aspirexc600
MakeModel Canon MP510 series - CUPS+Gutenprint v5.3.3
DeviceURI usb://Canon/MP510?serial=934631&interface=1
State Idle
StateTime 1619662185
ConfigTime 1619628669
Type 36876
Accepting Yes
Shared Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy retry-job
Option fitplot True
</DefaultPrinter>

 
So I stopped the CUPS service, edited the file to add the line ‘Option fitplot True‘ for the Canon PIXMA MP560, and restarted the CUPS service:

user $ sudo systemctl stop cups
user $ sudo nano /etc/cups/printers.conf
user $ sudo systemctl start cups

The file now looks like this:

# Printer configuration file for CUPS v2.3.3
# Written by cupsd
# DO NOT EDIT THIS FILE WHEN CUPSD IS RUNNING
NextPrinterId 3
<Printer Canon_MP560_Wi-Fi>
PrinterId 2
UUID urn:uuid:428a074e-0e81-3ba3-7789-f8050da82c5a
Info Canon MP560 Wi-Fi
Location My office upstairs
MakeModel Canon PIXMA MP560 - CUPS+Gutenprint v5.3.3
DeviceURI lpd://192.168.1.78/lpt1
State Idle
StateTime 1619978009
ConfigTime 1619880075
Type 36892
Accepting Yes
Shared No
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy retry-job
Option fitplot True
</Printer>
<DefaultPrinter MP510>
PrinterId 1
UUID urn:uuid:0a2a12b5-ea49-33eb-572a-341c1af02f7e
Info Canon MP510
Location aspirexc600
MakeModel Canon MP510 series - CUPS+Gutenprint v5.3.3
DeviceURI usb://Canon/MP510?serial=934631&interface=1
State Idle
StateTime 1619662185
ConfigTime 1619628669
Type 36876
Accepting Yes
Shared Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
OpPolicy default
ErrorPolicy retry-job
Option fitplot True
</DefaultPrinter>

 

I have the ImageableArea for A4 paper configured as follows in the Canon PIXMA MP560 PPD file for the Gutenprint v5.3.3 driver (I had to increase the y coordinate of the bottom left of the area to 2.000 in order for the bottom line to be printed):

user $ sudo grep "ImageableArea A4" /etc/cups/ppd/Canon_MP560_Wi-Fi.ppd
*ImageableArea A4/A4:   "0.000 2.000 595.000 842.000"

After restarting the CUPS service I printed another CUPS Printer test page and the result is shown below. As you can see, the bottom line is now printed.

Printer test page printed by CUPS after modifying the Canon PIXMA MP560 PPD file

So, if the outline of the CUPS Printer test page is not centred or is missing one or more of the lines, first adjust the ImageableArea for the paper size on which the test page is being printed, and, if that does not result in success, check if ‘Option fitplot‘ exists for the printer in the file /etc/cups/printers.conf and that it is set to ‘True‘.

Using open-plc-utils in Linux with Powerline (HomePlug) adapters

According to the open-plc-utils documentation, open-plc-utils supports INT6000, INT6300, INT6400, AR6410, QCA7000, AR7400 and AR7420 and later Powerline products from Qualcomm Atheros. ‘INT’ stands for ‘Intellon’, which was acquired by Atheros in 2009. ‘AR’ stands for ‘Atheros’, which was acquired by Qualcomm in 2011. ‘QCA’ stands for ‘Qualcomm Atheros’.

The open-plc-utils command int6k supports legacy chipsets INT6000, INT6300 and INT6400.

The open-plc-utils command plctool supports QCA6410, QCA7000 and QCA7420 chipsets.

The open-plc-utils command amptool supports AR7400 and QCA7450 chipsets.

I have used open-plc-utils successfully with the following Powerline products:

  • NETGEAR XAVB1301-100UKS (uses AR6405 chipset).
  • NETGEAR XAVB5221-100UKS (uses QCA7420 chipset).
  • TP-Link TL-PA4010 (uses QCA7420 chipset).
  • TP-Link TL-PA4010P (uses QCA7420 chipset).
  • TP-Link TL-PA4020P (uses QCA7420 chipset).

For example, I used open-plc-utils to update the chipset firmware in my TP-Link Powerline adapters, as explained in my earlier post ‘Updating the Powerline adapters in my home network‘.

Below I summarise how I install open-plc-utils in Linux and how I use them to interrogate the Powerline adapters in my home network.

1. Download the open-plc-utils source code

user $ cd
user $ wget https://github.com/qca/open-plc-utils/archive/refs/heads/master.zip
user $ unzip master.zip # (This creates ~/open-plc-utils-master directory.)

2. Install plc-utils

user $ cd ~/open-plc-utils-master/
user $ cat README # Tells you how to install/uninstall plc-utils.
user $ sudo make
user $ sudo make install
user $ sudo make manuals

3. Bookmark the documentation index pages in your Web browser

user $ cd ~/open-plc-utils-master/docbook

Bookmark file:///home/<username>/open-plc-utils-master/docbook/index.html

Bookmark file:///home/<username>/open-plc-utils-master/docbook/toolkit.html

4. Use open-plc-utils commands to interrogate the adapters in the network

One example of the many possible commands:

user $ plcstat -t -i eno1 # eno1 is the Ethernet interface on this computer.
 P/L NET TEI ------ MAC ------ ------ BDA ------ TX  RX  CHIPSET FIRMWARE
 LOC STA 038 11:11:11:11:11:11 88:88:88:88:88:88 n/a n/a QCA7420 MAC-QCA7420-1.5.0.26-02-20200114-CS
 REM STA 003 33:33:33:33:33:33 55:55:55:55:55:55 277 268 QCA7420 MAC-QCA7420-1.5.0.26-02-20200114-CS
 REM CCO 004 22:22:22:22:22:22 FF:FF:FF:FF:FF:FF 009 009 QCA7420 MAC-QCA7420-1.5.0.26-02-20200114-CS

(For security reasons, in the output above I have edited the MAC addresses of the three adapters, and the BDA of the two STAs. The BDA of the CCO adapter, which is automatically selected, really is displayed as FF:FF:FF:FF:FF:FF though.)

  • LOC = ‘Local’, i.e. the Powerline adapter connected to this computer.
  • REM = ‘Remote’, i.e. the other Powerline adapters in the network.
  • CCO = ‘Central Coordinator’, i.e. the automatically selected Powerline adapter acting as the coordinator of the Powerline adapters in this network.
  • STA = ‘Station’, i.e. the Powerline adapters being coordinated by the CCO.
  • MAC = The MAC address of the adapter.
  • BDA = ‘Bridged Destination Address’ (see the Powerline specifications for the meaning).
  • TX/RX = the transmission/reception rate in Mbps of the adapter.
  • CHIPSET = Atheros Qualcomm chipset type.
  • FIRMWARE = Atheros Qualcomm chipset firmware version.

For other open-plc-utils commands, consult the documentation in a Web browser.

5. Optional: Create a Bash script to interrogate Powerline adapters in your network

user $ cd
user $ nano ~/homeplug.sh
user $ chmod +x ~/homeplug.sh

homeplug.sh

#!/bin/bash
#
# This script is to interrogate a network to find the details of the Powerline
# HomePlug wall adapters in the network. It uses open-plc-utils tools:
# https://github.com/qca/open-plc-utils
# See https://github.com/qca/open-plc-utils/blob/master/README for
# instructions on how to install (and uninstall) the tools.
# Therefore this script is limited to the chipsets that open-plc-utils supports:
# https://github.com/qca/open-plc-utils/blob/master/plc/chipset.h
#
# The command int6k supports legacy chipsets INT6000, INT6300 and INT6400.
# The command plctool supports QCA6410, QCA7000 and QCA7420 devices.
# The command amptool supports chipsets AR7400 and QCA7450.
# NETGEAR XAVB1301-100UKS uses AR6405. NETGEAR XAVB5221-100UKS uses QCA7420.
# TP-Link TL-PA4010, TL-PA4010P and TL-PA4020P use QCA7420.
#
echo "================================================================================"
# Specify the interface on this PC connected to a HomePlug device:
export PLC=$( ifconfig | head -1 | cut -d ":" -f1 )
echo
echo -n "The Ethernet interface on this PC is: "
echo $PLC
echo
echo "================================================================================"
echo
#
# Step 1. Send VS_SW_VER to local device to determine its MAC address and device type.
#
MACINT6K=$( int6k -qr | awk -F ' ' '{print $2}' )
MACPLCTOOL=$( plctool -qr | awk -F ' ' '{print $2}' )
if [[ $MACINT6K != $MACPLCTOOL ]]
then
  echo "Unable to determine MAC address of local HomePlug wall adapter."
  exit
else
  MAC=$MACINT6K
fi
echo "Details for the HomePlug wall adapter connected to this computer:"
echo
if [ $( int6k -qI $MAC | wc -l ) -lt 2 ]
then
  plctool -m $MAC
  plctool -qI $MAC
  echo
  CHIPSET=$( plctool -qr $MAC | awk -F ' ' '{print $3}' )
  echo -n "Chipset: "
  echo $CHIPSET
  CHIPSETTYPE=2
else
  int6k -m $MAC
  int6k -qI $MAC
  echo
  CHIPSET=$( int6k -qr $MAC | awk -F ' ' '{print $3}' )
  echo -n "Chipset: "
  echo $CHIPSET
  CHIPSETTYPE=1
fi
echo
echo "================================================================================"
#
# Step 2. Send VS_NW_INFO (int6k -m or plctool -m, depending on device type)
# to local MAC address to find MAC addresses of the other devices.
#
if [[ $CHIPSETTYPE == 2 ]]
then
  plctool -qm $MAC | grep MAC | cut -d " " -f3 > maclist.txt
elif [[ $CHIPSETTYPE == 1 ]]
then
  int6k -qm $MAC | grep MAC | cut -d " " -f3 > maclist.txt
else
  echo "Unable to determine chipset of the local HomePlug wall adapter."
  exit
fi
#
# Step 3. Send VS_SW_VER (int6k -r or plctool -r, depending on device type) to
# each device to find the device type of each.
#
echo -n "" > chipsetlist.txt
while read -r MAC
do
  if [ $( int6k -qI $MAC | wc -l ) -lt 2 ]
  then
    CHIPSET=$( plctool -qr $MAC | awk -F ' ' '{print $3}' )
    echo $CHIPSET >> chipsetlist.txt
  else
    CHIPSET=$( int6k -qr $MAC | awk -F ' ' '{print $3}' )
    echo $CHIPSET >> chipsetlist.txt
  fi
done < maclist.txt
#
# Step 4. Send VS_NW_INFO (int6k -m or plctool -m, depending on device type) to
# each device to determine full PHY Rate.
#
echo
echo "Details for the other HomePlug wall adapters in the network"
echo "(adapters in Power Saving Mode are not shown):"
while read -r MAC && read -r CHIPSET <&3
do
  echo
  if [ $( int6k -qI $MAC | wc -l ) -lt 2 ]
  then
    plctool -m $MAC
    plctool -qI $MAC
  else
    int6k -m $MAC
    int6k -qI $MAC
  fi
  echo
  echo -n "Chipset: "
  echo $CHIPSET
  echo
  echo "--------------------------------------------------------------------------------"
done <maclist.txt 3<chipsetlist.txt
rm maclist.txt chipsetlist.txt
echo
echo "Some of the abbreviations are listed below, but refer to the open-plc-utils"
echo "documentation for more details. (Also see http://www.homeplug.org/ for"
echo "detailed HomePlug specifications)"
echo
echo "BDA   Bridged Destination Address"
echo "CCo   Central Coordinator"
echo "DAK   Device Access Key"
echo "MDU   Multiple Dwelling Unit"
echo "NID   Network Identifier"
echo "NMK   Network Membership Key"
echo "PIB   Parameter Information Block"
echo "SNID  Short Network Identifier"
echo "STA   Station"
echo "TEI   Terminal Equipment Identifier"
echo
exit

 
Run homeplug.sh to see details of Powerline adapters with Qualcomm Atheros chipsets in the network:

user $ ./homeplug.sh

N.B. Adapters in Power Saving Mode are not detected, so, if you want to see details of all Powerline adapters on the network, make sure none of the adapters are in Power Saving Mode before you run the script.

Below is the script’s output for my home network with the following three TP Link Powerline adapters currently connected to wall power sockets:

  • TP-Link TL-PA4010P(UK) VER:5.0 (one device)
  • TP-Link TL-PA4010(UK) VER:3.0 (two devices)

I also own the following Powerline adapters, which are currently not plugged in to wall power sockets, but this script would detect them if they were plugged in (as I have seen previously):

  • TL-PA4020P(UK) VER:4.0 (one adapter)
  • NETGEAR XAVB1301-100UKS (three adapters)
  • NETGEAR XAVB5221-100UKS (two adapters)
user $ ./homeplug.sh 
================================================================================

The Ethernet interface on this PC is: eno1

================================================================================

Details for the HomePlug wall adapter connected to this computer:

eno1 11:11:11:11:11:11 Fetch Network Information
eno1 11:11:11:11:11:11 Found 1 Network(s)

source address = 11:11:11:11:11:11

        network->NID = 99:99:99:99:99:99:99
        network->SNID = 5
        network->TEI = 38
        network->ROLE = 0x00 (STA)
        network->CCO_DA = 22:22:22:22:22:22
        network->CCO_TEI = 4
        network->STATIONS = 2

                station->MAC = 33:33:33:33:33:33
                station->TEI = 3
                station->BDA = 55:55:55:55:55:55
                station->AvgPHYDR_TX = 279 mbps Primary
                station->AvgPHYDR_RX = 276 mbps Primary

                station->MAC = 22:22:22:22:22:22
                station->TEI = 4
                station->BDA = FF:FF:FF:FF:FF:FF
                station->AvgPHYDR_TX = 009 mbps Primary
                station->AvgPHYDR_RX = 009 mbps Primary

        PIB 0-0 8836 bytes
        MAC 11:11:11:11:11:11
        DAK 66:66:66:66:66:66:66:66:66:66:66:66:66:66:66:66
        NMK 77:77:77:77:77:77:77:77:77:77:77:77:77:77:77:77
        NID 99:99:99:99:99:99:99
        Security level 0
        NET Qualcomm Atheros Enabled Network
        MFG tpver_401115_191120_901
        USR tpver_401115_191120_901
        CCo Auto
        MDU N/A

Chipset: QCA7420

================================================================================

Details for the other HomePlug wall adapters in the network
(adapters in Power Saving Mode are not shown):

eno1 33:33:33:33:33:33 Fetch Network Information
eno1 33:33:33:33:33:33 Found 1 Network(s)

source address = 33:33:33:33:33:33

        network->NID = 99:99:99:99:99:99:99
        network->SNID = 5
        network->TEI = 3
        network->ROLE = 0x00 (STA)
        network->CCO_DA = 22:22:22:22:22:22
        network->CCO_TEI = 4
        network->STATIONS = 2

                station->MAC = 22:22:22:22:22:22
                station->TEI = 4
                station->BDA = FF:FF:FF:FF:FF:FF
                station->AvgPHYDR_TX = 305 mbps Primary
                station->AvgPHYDR_RX = 319 mbps Primary

                station->MAC = 11:11:11:11:11:11
                station->TEI = 38
                station->BDA = 88:88:88:88:88:88
                station->AvgPHYDR_TX = 276 mbps Primary
                station->AvgPHYDR_RX = 279 mbps Primary

        PIB 0-0 8836 bytes
        MAC 33:33:33:33:33:33
        DAK 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 (none/secret)
        NMK 77:77:77:77:77:77:77:77:77:77:77:77:77:77:77:77
        NID 99:99:99:99:99:99:99
        Security level 0
        NET Qualcomm Atheros Enabled Network
        MFG tpver_401013_171025_901
        USR tpver_401013_171025_901
        CCo Auto
        MDU N/A

Chipset: QCA7420

--------------------------------------------------------------------------------

eno1 22:22:22:22:22:22 Fetch Network Information
eno1 22:22:22:22:22:22 Found 1 Network(s)

source address = 22:22:22:22:22:22

        network->NID = 99:99:99:99:99:99:99
        network->SNID = 5
        network->TEI = 4
        network->ROLE = 0x02 (CCO)
        network->CCO_DA = 22:22:22:22:22:22
        network->CCO_TEI = 4
        network->STATIONS = 2

                station->MAC = 33:33:33:33:33:33
                station->TEI = 3
                station->BDA = 55:55:55:55:55:55
                station->AvgPHYDR_TX = 319 mbps Primary
                station->AvgPHYDR_RX = 305 mbps Primary

                station->MAC = 11:11:11:11:11:11
                station->TEI = 38
                station->BDA = 88:88:88:88:88:88
                station->AvgPHYDR_TX = 009 mbps Primary
                station->AvgPHYDR_RX = 009 mbps Primary

        PIB 0-0 8836 bytes
        MAC 22:22:22:22:22:22
        DAK 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 (none/secret)
        NMK 77:77:77:77:77:77:77:77:77:77:77:77:77:77:77:77
        NID 99:99:99:99:99:99:99
        Security level 0
        NET Qualcomm Atheros Enabled Network
        MFG tpver_401013_171025_901
        USR tpver_401013_171025_901
        CCo Auto
        MDU N/A

Chipset: QCA7420

--------------------------------------------------------------------------------

Some of the abbreviations are listed below, but refer to the open-plc-utils
documentation for more details. (Also see http://www.homeplug.org/ for
detailed HomePlug specifications)

BDA   Bridged Destination Address
CCo   Central Coordinator
DAK   Device Access Key
MDU   Multiple Dwelling Unit
NID   Network Identifier
NMK   Network Membership Key
PIB   Parameter Information Block
SNID  Short Network Identifier
STA   Station
TEI   Terminal Equipment Identifier


For security reasons, in the output above I have edited the network membership key, device access key, network identifier and adapter addresses in the above output as follows:

  • I have changed the three MAC addresses of the three adapters to be 11:11:11:11:11:11, 22:22:22:22:22:22 and 33:33:33:33:33:33.
  • I have changed the two BDAs of the two adapters that are Stations (STAs) to be 55:55:55:55:55:55 and 88:88:88:88:88:88.
  • I have changed the DAK of the adapter connected to the computer on which the script was run to be 66:66:66:66:66:66:66:66:66:66:66:66:66:66:66:66.
  • I have changed the NMK of the three adapters to be 77:77:77:77:77:77:77:77:77:77:77:77:77:77:77:77.
  • I have changed the NID of the three adapters to be 99:99:99:99:99:99:99.

Some of the information that can be gleaned from the above output of the script:

  • the adapter with MAC address 22:22:22:22:22:22 has been automatically set as the CCO (Central Coordinator) for the Powerline network, and the other two adapters (MAC addresses 11:11:11:11:11:11 and 33:33:33:33:33:33) are STAs (Stations);
  • the only DAK that can be read is for the adapter connected to the computer;
  • the BDA of the CCO is reported as FF:FF:FF:FF:FF:FF;
  • all three Powerline adapters use the QCA7420 chipset;
  • the two Powerline stations are different models of TP-Link adapter (TP-Link versions ending in ‘401115_191120_901’ and ‘401013_171025_901’); the central coordinator is the same TP-Link model as one of the stations (TP-Link version ending in ‘401013_171025_901’).

Indeed, a TP-Link TL-PA4010P(UK) VER:5.0 adapter is connected to this computer, and the two remote adapters are TP-Link TL-PA4010(UK) VER:3.0, one of which is currently acting as the CCO. Last year I updated the Qualcomm Atheros firmware in all of them (see my 2020 post ‘Updating the Powerline adapters in my home network‘).

Resurrecting my Iomega Zip 100 parallel-port drive – Linux comes to the rescue

Top view of Z100P2 drive with 100 MB Zip disk in front.

Top view of Z100P2 drive with 100 MB Zip disk in front.

Z100P2 drive with disk inserted.

Z100P2 drive with disk inserted.

Rear sockets of Z100P2 drive.

Rear sockets of Z100P2 drive.

Back in 1998 I purchased what was then a state-of-the-art storage medium: an external Iomega Zip 100 drive, which used removable 100 MB ‘SuperFloppy’ disks. Until 2002 I backed up my important files on removable Zip 100 MB disks. Over several years in the 1990s Iomega released various models of the Zip 100 MB drive: internal SCSI; internal IDE; internal ATAPI; external DB-25 IEEE 1284 parallel port; external USB 1.1. I bought the external DB-25 IEEE 1284 parallel port model Z100P2. When affordable CD drives and external hard disk drives started to appear I began using those for backups instead, and the Zip drive and a box full of Zip 100 MB disks had been gathering dust on a shelf at home since I stopped using them in 2002.

Now, I was fairly sure I had copied all the files off those Zip disks all those years ago, but recently I wanted to check the contents and then wipe the disks prior to disposing of them and the drive. The trouble was, I have not owned a computer with a legacy parallel port for many years. This is the story of how I managed to use the Zip 100 drive again after a hiatus of some nineteen years.

Notice that the drive has a second DB-25 port with the icon of a printer above it. That socket is to allow a legacy parallel port printer to be connected (‘daisy chained’) to the computer at the same time as the Zip 100 drive. I have not owned a parallel port printer for many years, so that port is of no interest to me.

By the way, the Iomega Zip 100 drive gained rather a bad reputation because of the so-called click of death, although Iomega stated that it affected less than 0.5 percent of all Jaz and Zip drives. I never experienced this problem with my Zip 100 drive and it is still working.

PART 1 – HARDWARE

Power supply for Z100P2

When I purchased it in 1998, the Zip 100 drive was supplied with a chunky and rather heavy 240 VAC to 5 VDC PSU. However, I gave that away several years ago with an old 250 MB external USB HDD that required a 5 VDC power supply. So my first job was to get a 5 VDC supply for the Zip 100 drive. I decided to buy a USB-to-barrel-plug cable to power the Zip drive from a USB port on a computer. So I purchased a ‘USB to 5V DC power cable compatible with the Iomega Z100P2 ZIP drive’ from Amazon. The LEDs on the drive lit up and the drive briefly made the expected noise when I connected the drive to a computer using this power cable, so I was making progress. If a computer happens to have USB Type-A ports, this turns out to be a much neater approach than having to use a 5 VDC PSU.

5 Volts DC power socket on Z100P2 and barrel connector of the cable that is connected to the computer via USB Type-A at the other end.

5 Volts DC power socket on Z100P2 and barrel connector of the cable that is connected to the computer via USB Type-A at the other end.

 
Failed first attempt: USB to legacy parallel port printer adapters do NOT work with parallel Zip drives!

None of my laptops and desktop machines have the legacy DB-25 parallel port that the Z100P2 drive requires. No problem, I thought to myself, I’ll just buy a ‘USB to Printer DB25 25-Pin Parallel Port Cable Adapter’ – there are umpteen of these adapters available on eBay and Amazon. It wasn’t expensive, but I found out the hard way that these cable adapters usually work with parallel printers but definitely do not work with Iomega Zip 100 drives. So I needed to do one of the following:

  • get a parallel printer interface card for a PCIe slot in my modern desktop machines – and hope it would work with a Z100P2 drive;
  • get a legacy computer with a bidirectional parallel port with a DB-25 socket;
  • get a legacy computer with a PCI slot into which I could insert a legacy parallel printer PCI interface card (assuming I could get hold of one).

Computer with legacy parallel port

I searched eBay and found a second-hand Dell OptiPlex 780 SFF (Small Form Factor) with a legacy DB-25 parallel port (connected to the motherboard rather than to a card in one of its PCI slots), Intel Pentium E5800 CPU (3.20 GHz, 800 Mz FSB), 4 GB of PC3-10600U (1333 MHz) DDR3 DIMM memory and Windows 10 Pro installed with a valid licence. It also has plenty of USB 2.0 Type-A ports, convenient for the USB-to-barrel-plug cable I bought to power the Z100P2 drive. The price was very reasonable indeed, so I bought it in the hope that it would be usable. The vendor assured me that Windows 10 detected the parallel port and no errors were reported, but the vendor had no legacy devices (e.g. parallel port printer) with which to actually test the port. Anyway, as it was so cheap I took a gamble and purchased it, although my research on the Web had already indicated that Windows 10 does not support parallel port Iomega Zip drives. I was thinking I could either try using a virtual machine or just wipe Windows 10 and install Linux on the machine.

The FSB speed of the legacy CPU actually limits the memory speed to 800 MHz, but performance is not too bad. I actually replaced the 4 GB of PC3-10600U memory with 8 GB of PC3-12800U (1600 MHz) memory (Crucial CT51264BD160B.C16FED2) which I purchased for a very good price on eBay, although upgrading to 8 GB of memory was not necessary for the purpose of getting the Zip 100 drive working. I decided to increase the memory because the machine is in a nice condition so I will keep it for future projects, which might need more memory.

By the way, the Dell documentation for the OptiPlex 780 SFF that I downloaded from Dell’s Web site states that the machine can only use 1066 MHz memory modules or 1333 MHz memory modules, and the 1333 MHz memory modules would only be able to have a speed of 1066 MHz. What is not obvious is that the documentation assumes that one of the E6xxx series or E7xxx series Wolfdale-3M CPUs (45 nm) is installed, as the speed of the FSB (Front Side Bus) of those CPUs is 1066 MHz. The earlier Wolfdale-3M CPUs which are installed in some OptiPlex 780 SFF machines have a FSB speed of 800 MHz, so even 1066 MHz memory modules are only going to have a speed of 800 MHz in those machines. The Wolfdale-3M CPU in my Dell machine is an E5800, which has a FSB speed of 800 MHz, so the memory speed is limited to 800 MHz (as confirmed on the BIOS System Setup screen, by the CPU-Z utility program running in Windows 10 (2 x 399.0 MHz), and by the Linux commands ‘sudo dmidecode --type 17‘ and ‘sudo lshw -short -C memory‘). The Crucial CT51264BD160B.C16FED2 PC3-12800 modules work fine in the machine, albeit limited to 800 MHz due to the CPU bus speed. On another note, if you happen to be looking for memory for a Dell OptiPlex 780 SFF, do NOT buy CT51264BD160BJ modules: the ‘J’ stands for ‘high-density’, and high-density modules do not work in this model.

Parallel port settings in the PC BIOS

The refurbished Dell OptiPlex 780 SFF has the following user-selectable options:

  1. Disable = Port is disabled
  2. AT = Port is configured for IBM AT compatibility
  3. PS/2 = Port is configured for IBM PS/2 compatibility
  4. EPP = Enhanced Parallel Port protocol
  5. ECP No DMA = Extended Capability Port protocol with no DMA
  6. ECP DMA 1 = Extended Capability Port protocol with DMA 1
  7. ECP DMA 3 = Extended Capability Port protocol with DMA 3

The BIOS had option ‘PS/2’ selected when I received the machine, which I eventually changed to ‘ECP No DMA’ but I think that was unnecessary.

The BIOS also had the Parallel Port Address set to 378h when I received it, and I left it as that.

Data connection

Fortunately I still had the original parallel cable to connect the Zip drive to a DB-25 parallel port on a computer.

Z100P2 end of cable connected to computer parallel port.

Z100P2 end of cable connected to computer parallel port.

Rear of legacy Dell PC with Z100P2 cable connected to the parallel port, and USB-to-barrel-plug power cable connected to a USB port.

Rear of legacy Dell PC with Z100P2 cable connected to the parallel port, and USB-to-barrel-plug power cable connected to a USB port.

PART 2 – SOFTWARE

First attempt – Failure: Windows XP in a VirtualBox virtual machine

My original intention was to wipe Windows 10 from the Dell machine and install Linux to see if I could get Linux to access the Zip drive. But, on second thoughts, I decided I might have a better chance in Windows because my research on the Web had already indicated that several people had successfully used Iomega Zip 100 parallel-port drives with Windows XP running in a virtual machine under Windows 10. I carefully followed a detailed article on how to do this using VirtualBox (How to use iomega zip 100 with parallel port on a windows 10 computer (so long as you have a free PCI slot)), but the Zip drive would not work with the Dell machine. I tried every BIOS option for the parallel port; I tried allowing Windows XP to install the driver; I installed the last official Iomega issue of the driver for Windows XP. Nothing worked.

Second attempt – Failure: Lubuntu 20.10 in a VirtualBox virtual machine

Then I decided to try installing Linux in a VirtualBox virtual machine under Windows 10. I chose Lubuntu 20.10 because it already has the necessary ppa (for older Zip parallel-port drives like mine) and the imm (for later versions of Zip 100 parallel-port drives than mine) modules built and either could simply be loaded from the command line. But that couldn’t access the drive either. Again, I tried without success every BIOS option for the parallel port.

Third attempt – Success: Live Lubuntu 20.10 on a USB pendrive

I was resigned to wiping Windows 10 and installing a Linux distribution when I had a brainwave: Why not try a Live Linux distribution? I used the mkusb utility to create a persistent installation of Live Lubuntu 20.10 on a USB pendrive (it had to use PC BIOS, as the legacy Dell machine does not support UEFI), booted it and used the command modprobe ppa to load the ppa parallel port driver. Shazam! The drive became device /dev/sdc4 and was auto-mounted as ‘ZIP-100’ in the LXQt file manager window. I can browse all the files on the 100 MB ZIP disks. It’s fast, too. I wish I’d thought of trying that first. I could have reformatted the disks with a Linux filesystem (ext4 or whatever) if I wanted to do that.

I then downloaded from a Debian amd64 repository the binary package for a 1996 Linux GUI utility named ‘jaZip‘ that someone named Jarrod Smith (thank you!) wrote in 1996 for Iomega Jaz and Zip drives, and I installed it easily in the Live Lubuntu 20.10 environment. It works perfectly, allowing me to mount, unmount, lock, unlock and eject Zip 100 MB disks. Linux came to the rescue again. I’m chuffed. Below are details of the steps I took to create a persistent Live USB pendrive with Lubuntu 20.10 with the ability to use my Iomega Z100P2 drive connected to the Dell OptiPlex 780 SFF PC.

By the way, a persistent Live Linux USB pendrive is not essential, it just means you don’t have to manually load the ppa module, re-install jaZip and configure it every time you boot the Live Linux environment.

1. Download the ISO of Lubuntu 20.10 from the official Lubuntu Web site.

2. Use the procedure in the following ‘How To’ article to create a persistent Live pendrive of Lubuntu 20.10 by using the utility mkusb:

Create a persistent Ubuntu USB which boots to RAM

The mkusb windows in that 2016 article are a bit different to those in the version of mkusb (12.3.9) that was installed by following the procedure, but it is fairly obvious what to do. Select the old user interface (Option e: Old User Interface). There is no need to perform the steps in ‘Extra: Boot the Live USB to RAM’ because it is now done automatically for you and added to the GRUB boot menu as an additional option.

3. Once I had created the persistent Live pendrive, I booted it and performed the installation procedure for jaZip, and configured the persistent Live installation. The console output for all these steps is shown below:

lubuntu@lubuntu:~$ sudo apt install libforms2
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  libforms2
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 327 kB of archives.
After this operation, 975 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu groovy/universe amd64 libforms2 amd64 1.2.3-1.4 [327 kB]
Fetched 327 kB in 0s (807 kB/s)  
Selecting previously unselected package libforms2.
(Reading database ... 240052 files and directories currently installed.)
Preparing to unpack .../libforms2_1.2.3-1.4_amd64.deb ...
Unpacking libforms2 (1.2.3-1.4) ...
Setting up libforms2 (1.2.3-1.4) ...
Processing triggers for libc-bin (2.32-0ubuntu3) ...
lubuntu@lubuntu:~$ cd ~/Downloads
lubuntu@lubuntu:~/Downloads$ wget http://ftp.uk.debian.org/debian/pool/main/j/jazip/jazip_0.34-15.1+b2_amd64.deb
--2021-04-14 15:09:15--  http://ftp.uk.debian.org/debian/pool/main/j/jazip/jazip_0.34-15.1+b2_amd64.deb
Resolving ftp.uk.debian.org (ftp.uk.debian.org)... 2001:1b40:5600:ff80:f8ee::1, 78.129.164.123
Connecting to ftp.uk.debian.org (ftp.uk.debian.org)|2001:1b40:5600:ff80:f8ee::1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 81280 (79K) [application/octet-stream]
Saving to: ‘jazip_0.34-15.1+b2_amd64.deb’

jazip_0.34-15.1+b2_amd64.de 100%[===========================================>]  79.38K  --.-KB/s    in 0.08s

2021-04-14 15:09:15 (941 KB/s) - ‘jazip_0.34-15.1+b2_amd64.deb’ saved [81280/81280]

lubuntu@lubuntu:~/Downloads$ sudo dpkg -i jazip_0.34-15.1+b2_amd64.deb
Selecting previously unselected package jazip.
(Reading database ... 240059 files and directories currently installed.)
Preparing to unpack jazip_0.34-15.1+b2_amd64.deb ...
Unpacking jazip (0.34-15.1+b2) ...
Setting up jazip (0.34-15.1+b2) ...
Processing triggers for man-db (2.9.3-2) ...
lubuntu@lubuntu:~/Downloads$ sudo adduser lubuntu floppy
Adding user `lubuntu' to group `floppy' ...
Adding user lubuntu to group floppy
Done.
lubuntu@lubuntu:~/Downloads$ sudo modprobe ppa # Load the parallel port driver for the Zip drive.
lubuntu@lubuntu:~/Downloads$ sudo blkid # Check if the Zip drive has now been detected.
/dev/sda1: LABEL="system" BLOCK_SIZE="512" UUID="BCF27E52F27E10BE" TYPE="ntfs" PARTUUID="6da119a3-01"
/dev/sda2: LABEL="windows" BLOCK_SIZE="512" UUID="527280DF7280C8E5" TYPE="ntfs" PARTUUID="6da119a3-02"
/dev/sdb1: LABEL="usbdata" BLOCK_SIZE="512" UUID="347345C33A9B90D1" TYPE="ntfs" PARTUUID="793c91c2-01"
/dev/sdb3: LABEL_FATBOOT="lub201064" LABEL="lub201064" UUID="7EAA-D59C" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="793c91c2-03"
/dev/sdb4: BLOCK_SIZE="2048" UUID="2020-10-22-14-26-38-00" LABEL="Lubuntu 20.10 amd64" TYPE="iso9660" PTUUID="509643ab-f22d-4d70-8a47-8708c562cbfe" PTTYPE="gpt" PARTUUID="793c91c2-04"
/dev/loop0: TYPE="squashfs"
/dev/sdb5: LABEL="casper-rw" UUID="55459d4d-48f3-4b50-bd9b-3fd71e552bb2" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="793c91c2-05"
/dev/zram0: UUID="073aa55f-241b-4deb-b6a0-907676dfff65" TYPE="swap"
/dev/zram1: UUID="692d4cc6-21fa-48b8-8ef7-948dc13dec53" TYPE="swap"
/dev/sdc4: SEC_TYPE="msdos" LABEL_FATBOOT="ZIP-100" LABEL="ZIP-100" UUID="15F9-2C71" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="726a014e-04"
lubuntu@lubuntu:~/Downloads$ sudo mkdir -p /media/lubuntu/ZIP-100
lubuntu@lubuntu:~/Downloads$ sudo /usr/sbin/jazipconfig
There are currently no entries in /etc/jazip.conf.

Zip devices detected on the system:

  1:  Device /dev/sdc

There are no Jaz devices detected on the system.

Available commands:
 (a)dd an entry listed from detected devices.
 (c)reate an entry from scratch.
 (q)uit without saving.
 (e)xit and save changes.
                           ? a

What mount point? (e.g. /zip) /media/lubuntu/ZIP-100
--------------------------------------------
These are the entries currently selected for /etc/jazip.conf:

  1:   Device /dev/sdc   Mount point /media/lubuntu/ZIP-100

There are no other Zip devices detected on the system.

There are no Jaz devices detected on the system.

Available commands:
 (d)elete an entry from /etc/jazip.conf
 (c)reate an entry from scratch.
 (q)uit without saving.
 (e)xit and save changes.
                           ? e
Creating /etc/jazip.conf
lubuntu@lubuntu:~/Downloads$ cat /etc/jazip.conf
# Configuration file for jaZip
#
# Raw Device         Mount Point                  Read but ignored
  /dev/sdc              /media/lubuntu/ZIP-100                      auto    auto        0 0
lubuntu@lubuntu:~/Downloads$ sudo jazip # Launch jaZip.
ERROR! Couldn't write entry to /etc/mtab.
lubuntu@lubuntu:~/Downloads$ sudo jazip # Launch jaZip.
lubuntu@lubuntu:~/Downloads$ sudo nano /etc/modules # Add ppa so it gets loaded automatically.

 
4. Add a jaZip icon on the Linux Desktop so that you can launch jaZip easily:

4.1 Create the file /home/lubuntu/Desktop/jazip.desktop containing:

[Desktop Entry]
Name=jazip
GenericName=Manage Iomega Jaz and Zip drives
Comment=
Exec=/home/lubuntu/.launch_jazip.sh
Type=Application
Icon=/usr/share/doc/jazip/icons/jazip1.gif
Terminal=false

4.2 Right-click on the icon on the Desktop and tick ‘Trust this executable’.

4.3 Create the file /home/lubuntu/.launch_jazip.sh containing:

#!/bin/bash
lxqt-sudo nohup jazip &

4.4 Make it executable:

lubuntu@lubuntu:~/Downloads$ chmod +x ~/.launch_jazip.sh
jaZip window open on the Lubuntu 20.10 Desktop.

jaZip window open on the Lubuntu 20.10 Desktop.

What a pleasure to find that the ppa module, which has been part of the kernel distribution since sometime in the 1.3.x series, is still available and working in today’s Linux kernels, and that jaZip, a utility program for Linux originally released in 1996 and last updated (as far as I can tell) in the year 2001, still works in today’s Linux to manage hardware that has been obsolete for almost as long.

Using jaZip to mount a Zip disk will mount the disk with ownership root:root. Therefore, if I want to copy files to a Zip disk, instead of using jaZip to mount and unmount the disk I click on the device ‘101 MB Volume’ that appears in the Lists pane of the PCManFM-Qt file manager window after a Zip disk is inserted in the drive. I just use jaZip to eject the Zip disk from the drive after unmounting it by clicking on the Unmount icon in the Lists pane of PCManFM-Qt.

Notes on keyboard configuration in X Windows: Keyboard layout, Modifier Key and Compose Key

Before I dive into X Windows, I need to mention Miguel Farah’s excellent and comprehensive Web pages on keyboard layouts and standards:

http://www.farah.cl/Keyboardery/

There are umpteen articles, blog and forum posts available on the Web covering keyboard configuration for X Windows, but my notes below may be of help to someone. I briefly cover keyboard layout configuration (non-persistent) from the command line in a pseudo terminal in an X Windows session, and also how to make the configuration persist. I also cover how to configure a ‘Modifier Key‘ and a ‘Compose Key‘, two different things.

1. Changing the layout

Look in the file /usr/share/X11/xkb/rules/xorg.lst to find out what settings are available in X Windows. The file is divided into four sections listing the different keyboard models, layouts, variants and options that X Windows allows:

user $ grep "^! " /usr/share/X11/xkb/rules/xorg.lst
! model
! layout
! variant
! option

For example, the following X Windows German-language keyboard layouts are available in the Linux installation I am using now:

user $ awk '/\!\ layout/{flag=1;next}/\!\ variant/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep German
  at              German (Austria)
  de              German
  ch              German (Switzerland)

And the following variants to those three keyboard layouts are available:

user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "at: German"
  nodeadkeys      at: German (Austria, no dead keys)
  sundeadkeys     at: German (Austria, with Sun dead keys)
  mac             at: German (Austria, Macintosh)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "de: German"
  deadacute       de: German (dead acute)
  deadgraveacute  de: German (dead grave acute)
  nodeadkeys      de: German (no dead keys)
  T3              de: German (T3)
  dvorak          de: German (Dvorak)
  sundeadkeys     de: German (with Sun dead keys)
  neo             de: German (Neo 2)
  mac             de: German (Macintosh)
  mac_nodeadkeys  de: German (Macintosh, no dead keys)
  qwerty          de: German (QWERTY)
  deadtilde       de: German (dead tilde)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "ch: German"
  legacy          ch: German (Switzerland, legacy)
  de_nodeadkeys   ch: German (Switzerland, no dead keys)
  de_sundeadkeys  ch: German (Switzerland, with Sun dead keys)
  de_mac          ch: German (Switzerland, Macintosh)

Let’s say I had a desktop machine with a 104-key Swiss German keyboard. By looking through the list of keyboard models in the models section of the file /usr/share/X11/xkb/rules/xorg.lst, I think the following model best describes the keyboard:

user $ awk '/\!\ model/{flag=1;next}/\!\ layout/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep 104
  pc104           Generic 104-key PC

To inform X Windows of the keyboard’s characteristics I could, for example, enter the following command in an X Windows terminal window, which would apply for that session only:

user $ setxkbmap -model pc104 -layout ch -variant legacy

and/or I could configure X Windows permanently by creating/editing a file /etc/X11/xorg.conf.d/00-keyboard.conf containing the following:

Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbModel" "pc104"
Option "XkbLayout" "ch"
Option "XkbVariant" "legacy"
EndSection

My laptop has a UK keyboard but, depending where I am, I sometimes connect an external US, Brazilian or Spanish keyboard to it.

Left side of HP UK keyboard

Left side of HP UK keyboard

Left side of HP US keyboard

Left side of HP US keyboard

Left side of HP Brazilian keyboard

Left side of HP Brazilian keyboard

Left side of HP Iberian Spanish keyboard

Left side of HP Iberian Spanish keyboard

To be able to switch the layout to the keyboard I am currently using, the following two methods achieve the same effect in X Windows:

Current session only

user $ setxkbmap -layout gb,us,br,es -model pc105 -option grp:alt_shift_toggle

Persistent

The file /etc/X11/xorg.conf.d/00-keyboard.conf contains:

Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "gb,us,br,es"
Option "XkbModel" "pc105"
Option "XkbOptions" "grp:alt_shift_toggle"
EndSection

Either of the above methods will enable me to toggle between UK, US, Brazilian and Iberian Spanish keyboard layouts in X Windows by pressing Alt+Shft. If the laptop had, say, a Brazilian keyboard instead of a UK keyboard then I could change the order of the layouts to ‘br,gb,us,es‘ or whatever order I prefer.

In fact, even when an external keyboard is not connected to my laptop I select the layout using Alt+Shft if I want to type in English, Portuguese or Spanish. For example, to type ‘ã‘ (the letter ‘a‘ with a tilde accent) I press Alt+Shft to switch to the Brazilian Portuguese layout then press the ' (apostrophe) key followed by the A key on the laptop’s UK keyboard. Transparent key-cap stickers can be purchased for various language layouts so that users can see which keys on the keyboard correspond to keys in another layout. However I don’t bother with key-cap stickers because I can remember the layouts for the few languages I use.
 
2. Using a Modifier Key and/or a Compose Key

If you do not connect external keyboards with different layouts, or you want to be able to type letters with accents – or type different symbols – that are not on the keyboard, a Modifier Key and/or a Compose Key can be used. These are two different things. You might use a Modifier Key to add an accent to a letter, for example. If you were to configure, say, AltGr as the Modifier Key, pressing AltGr and the ` (grave accent) key simultaneously then releasing them and pressing the A key could – depending on which keyboard layout you are using – result in à (‘a‘ with the grave accent) being displayed. The ` (grave accent) key is a ‘dead key’ in this case because it is not displayed by itself when pressed in conjunction with the AltGr key; it is only displayed when the next key is pressed, i.e. à, not `a, is displayed on the screen.

You might use a Compose Key to display a symbol that is not on the keyboard. If you were to configure, say, the Pause key as the Compose Key, pressing and releasing the Pause key, then the O key and then the C key could – depending on which keyboard layout you have specified – result in the © (copyright) symbol being displayed.

Let’s say that you want a US keyboard layout with AltGr dead keys, and the Windows key as the Compose key. The setxkbmap command would be:

user $ setxkbmap -layout us -variant altgr-intl -option compose:lwin

Alternatively, the file /etc/X11/xorg.conf.d/00-keyboard.conf to make that configuration permanent would contain:

Section "InputClass"
Identifier "keyboard"
MatchIsKeyboard "yes"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
Option "XkbVariant" "altgr-intl"
Option "XkbOptions" "compose:lwin"
EndSection

However, the problem with specifying the Windows key as the Compose Key is that the Windows key is usually the key that makes a desktop environment display the applications menu, so an alternative Compose Key needs to be chosen.

You can play around with the XkbModel, XkbLayout, XkbVariant and XkbOptions options to see what works. Look in the file /usr/share/X11/xkb/rules/xorg.lst to find out what are permissible/available.

Using the example of a generic US International keyboard layout with AltGr dead keys, let’s check what options for the model, layout, variant, option and Compose Key are available:

model

user $ awk '/\!\ model/{flag=1;next}/\!\ layout/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep Generic
  pc101           Generic 101-key PC
  pc102           Generic 102-key PC
  pc104           Generic 104-key PC
  pc104alt        Generic 104-key PC with L-shaped Enter key
  pc105           Generic 105-key PC

layout

user $ awk '/\!\ layout/{flag=1;next}/\!\ variant/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "US"
  us              English (US)

variant

user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "us:"
  intl            us: English (US, intl., with dead keys)
  dvorak-intl     us: English (Dvorak, intl., with dead keys)
  altgr-intl      us: English (intl., with AltGr dead keys)
  workman-intl    us: English (Workman, intl., with dead keys)

option

user $ tac /usr/share/X11/xkb/rules/xorg.lst | awk '/\!\ option/ {exit} 1' | tac | grep ralt
  lv3:ralt_switch      Right Alt
  lv3:ralt_switch_multikey Right Alt; Shift+Right Alt as Compose
  lv3:ralt_alt         Right Alt never chooses 3rd level
  ctrl:rctrl_ralt      Right Ctrl as Right Alt
  compose:ralt         Right Alt
  lv5:ralt_switch      Right Alt chooses 5th level
  lv5:ralt_switch_lock Right Alt chooses 5th level and acts as a one-time lock if pressed with another 5th level chooser
  lv5:ralt_switch      Right Alt chooses 5th level
  lv5:ralt_switch_lock Right Alt chooses 5th level and acts as a one-time lock if pressed with another 5th level chooser
  korean:ralt_hangul   Make right Alt a Hangul key
  korean:ralt_hanja    Make right Alt a Hanja key

Compose Key

user $ grep "compose:" /usr/share/X11/xkb/rules/base.lst
  compose:ralt         Right Alt
  compose:lwin         Left Win
  compose:lwin-altgr   3rd level of Left Win
  compose:rwin         Right Win
  compose:rwin-altgr   3rd level of Right Win
  compose:menu         Menu
  compose:menu-altgr   3rd level of Menu
  compose:lctrl        Left Ctrl
  compose:lctrl-altgr  3rd level of Left Ctrl
  compose:rctrl        Right Ctrl
  compose:rctrl-altgr  3rd level of Right Ctrl
  compose:caps         Caps Lock
  compose:caps-altgr   3rd level of Caps Lock
  compose:102          The "<Less/Greater>" key
  compose:102-altgr    3rd level of "<Less/Greater>" key
  compose:paus         Pause
  compose:prsc         PrtSc
  compose:sclk         Scroll Lock

(Not all keyboard layouts have a ‘<Less/Greater>’ key, a single key with both < and > symbols on it.)

The following works for me in LXQt with a US keyboard layout:

user $ setxkbmap -layout us -variant altgr-intl -option compose:paus

With the above configuration, I press:

AltGr+a to get á
AltGr+` then a to get à
AltGr+~ then a to get ã
AltGr+e to get é
AltGr+` then e to get è
AltGr+^ then e to get ê
AltGr+~ then e to get
AltGr+o to get ó
AltGr+n to get ñ
AltGr+c to get ©
AltGr+< to get ç
AltGr+s to get ß
AltGr+? to get ¿

and so on, and I press:

Pause then o then o to get °
Pause then o then c to get ©
Pause then ~ then a to get ã
Pause then ~ then e to get
Pause then ^ then 2 to get ²
Pause then _ then 2 to get
Pause then 8 then 8 to get
Pause then E then = to get
Pause then . then . to get
Pause then then > to get
Pause then < then to get
Pause then < then 3 to get
Pause then CCCP to get

and so on. Notice that some characters are available using either method (©, ã and are three examples shown above). A full list of Compose Key characters can be found in the file /usr/share/X11/locale/<locale>/Compose in your installation. For the US layout keyboard the list is in the file /usr/share/X11/locale/en_US.UTF-8/Compose. Various lists of Compose Key sequences and the resulting symbols can also be found on the Web.

To make the configuration in the aforementioned setxkbmap command permanent I would edit the file /etc/X11/xorg.conf.d/00-keyboard.conf to contain the following:

Section "InputClass"
Identifier "keyboard"
MatchIsKeyboard "yes"
Option "XkbModel" "pc105"
Option "XkbLayout" "us"
Option "XkbVariant" "altgr-intl"
Option "XkbOptions" "compose:paus"
EndSection

Let’s say I want to be able to switch between British (gb), US (us), Brazilian (br) and Iberian Spanish (es) keyboard layouts by using Alt+Shft on my laptop with a UK keyboard. I could use the command:

user $ setxkbmap -model pc105 -layout gb,us,br,es -variant ,altgr-intl,, -option grp:alt_shift_toggle,compose:paus

The commas in the -variant option means the ‘altgr-intl‘ option applies solely to the US layout. The Compose Key option in the -option options will work for all layouts.

I could make that configuration permanent in /etc/X11/xorg.conf.d/00-keyboard.conf:

Section "InputClass"
Identifier "keyboard"
MatchIsKeyboard "yes"
Option "XkbModel" "pc105"
Option "XkbLayout" "gb,us,br,es"
Option "XkbVariant" ",altgr-intl,,"
Option "XkbOptions" "grp:alt_shift_toggle,compose:paus"
EndSection

Note that I would not be able to specify ‘altgr-intl‘ as a variant for the gb, br and es layouts I use because the variant ‘altgr-intl‘ is not available in those layouts:

user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "gb:"
  intl            gb: English (UK, intl., with dead keys)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "br:"
  nodeadkeys      br: Portuguese (Brazil, no dead keys)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "es:"
  nodeadkeys      es: Spanish (no dead keys)
  deadtilde       es: Spanish (dead tilde)
  sundeadkeys     es: Spanish (with Sun dead keys)

 
3. Virtual Terminal (TTY console) keyboard configuration

Although this post is about keyboard configuration for X Windows, I should briefly mention that configurations for X Windows do not apply to virtual terminals (TTY consoles).

If you’re using a Linux distribution running OpenRC, you specify the persistent console keymap in the file /etc/conf.d/keymaps. You can find out which console keymaps are available by examining the directories under /usr/share/keymaps/. For example, the following console keymaps are available for US keyboards in Gentoo Linux:

user $ ls /usr/share/keymaps/i386/qwerty/us*
/usr/share/keymaps/i386/qwerty/us-acentos.map.gz
/usr/share/keymaps/i386/qwerty/us.map.gz
/usr/share/keymaps/i386/qwerty/us1.map.gz

so you would be able to specify one of the following in /etc/conf.d/keymaps:

keymap="us-acentos"

keymap="us"

keymap="us1"

It is also possible to change the console keymap (non-persistent) from the command line. For example, to switch to a UK keyboard layout for a TTY console:

root # loadkeys uk

(notice it is not ‘gb‘ in the case of TTY consoles), or to switch to an Italian Apple Macintosh keyboard layout for a TTY console:

root # loadkeys mac-it

and so on.

If you’re using a Linux distribution running systemd, see my 2020 blog post ‘Reconfiguring the time zone, locales and keymaps in Sabayon Linux‘ for the commands to list and configure TTY console keymaps. The persistent TTY console keymap is specified in the file /etc/vconsole.conf, which can be edited directly and is also edited by the ‘localectl set-keymap‘ command mentioned in that post. The loadkeys command can also be used as described above to change (non-persistent) the keyboard layout for the TTY console.

Work-around in Linux to switch between single-sided and double-sided printing

I use Gentoo Linux on my laptop, and have drivers installed for quite a few printer manufacturers and models, as I work in multiple offices and they have a wide range of printers and MFPs. To date I have had no trouble printing single-sided (‘simplex’) and double-sided (‘duplex’) documents on the printers that support duplex printing. However, one of the offices I have been working in recently has a Konica Minolta bizhub C368, a floor-standing MFP, and the printer in this MFP did not enable me to switch between single-sided and double-sided printing even though Windows users in the same office could. This article explains how I managed to switch between the two printing modes.

A Linux driver for the bizhub C368 can be downloaded from the Konica Minolta Download Centre. I downloaded the tarball KMbeuUXv1_22_multi_language.tar.gz, extracted the contents to the directory ~/KMbeuUXv1_22_multi_language/ and followed the instructions in ‘BEU Linux CUPS Driver Guide.pdf‘:

user $ cd ~/KMbeuUXv1_22_multi_language
user $ su
root # ./install.pl
root # rc-service cupsd restart

I then used the CUPS Administration page in a browser window to set up the printer.

As I wanted the printer to be the default printer while I was working in that office, I edited the system-wide and user-specific lpoptions files to contain the printer name I had specified to CUPS when setting up the printer:

user $ cat ~/.cups/lpoptions
Default Konica_Minolta_bizhub_C368
root # cat /etc/cups/lpoptions
Default Konica_Minolta_bizhub_C368

I was then able to print from all the usual applications, except that the applications could only select single-sided printing, even though the printer supports double-sided printing and Windows users in the office could print double-sided. I could not find a setting for this in the CUPS Manager’s ‘Set Default Options’ page for the printer, so I edited the PPD file to change the relevant default option:

root # nano /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd

I changed the default printing option from:

*DefaultKMDuplex: 1Sided

to:

*DefaultKMDuplex: 2Sided

Then I could print double-sided pages, but selecting ‘single-sided’ in applications would still print double-sided. Now, I don’t know if there is a proper fix for this, but I could not find out how to do it. Therefore I opted for a work-around which is fine for my purposes. Here is what I did…

I created the shell script ~/Konica_Minolta_bizhub_C368.sh containing the following:

#!/bin/bash
echo
echo "Konica Minolta bizhub C368 printer"
echo
echo "Select single-sided or double-sided printing as the default"
echo
# Get the password entry over and done with now
echo "Enter your user account password."
sudo ls > /dev/null
echo
CHOICE=""
while [[ $CHOICE != "X" && $CHOICE != "x" ]]; do
    if [[ $CHOICE != "X" && $CHOICE != "x" ]]; then
        echo
        echo -n "[1]-sided, [2]-sided or e[X]it : "
        read -n1 CHOICE
        echo
    else
        break
    fi
    case $CHOICE in
        [1] ) sudo cp /home/fitzcarraldo/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.single-sided /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd
              echo "Single-sided printing has been selected"
        ;;
        [2] ) sudo cp /home/fitzcarraldo/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.double-sided /etc/cups/ppd/Konica_Minolta_bizhub_C368.ppd
              echo "Double-sided printing has been selected"
        ;;
        [Xx] ) echo; exit;;
        * ) echo; echo " Enter '1', '2' or 'X/x'"
    esac
done

I created the Desktop Configuration File ~/Desktop/Konica_Minolta_bizhub_C368.desktop containing the following:

[Desktop Entry]
Comment[en_GB]=Select single-sided or double-sided printing for Konica Minolta bizhub C368
Comment=Select single-sided or double-sided printing for Konica Minolta bizhub C368
Encoding=UTF-8
Exec=konsole -e sh /home/fitzcarraldo/Konica_Minolta_bizhub_C368.sh
GenericName[en_GB]=Select printing sides for KM bizhub C368
GenericName=Select printing sides for KM bizhub C368
Icon=/home/fitzcarraldo/Pictures/Icons/konica-minolta.png
MimeType=
Name[en_GB]=Konica_Minolta_bizhub_C368
Name=Konica_Minolta_bizhub_C368
Path=
StartupNotify=true
Terminal=true
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-DCOP-ServiceType=
X-KDE-SubstituteUID=false
X-KDE-Username=

I downloaded a Konica Minolta logo from the Web and used it for the icon for the Desktop Configuration File.

And finally I copied the PPD file to two files and edited them:

~/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.single-sided

which includes *DefaultKMDuplex: 1Sided

~/Konica_Minolta_bizhub_C368/Konica_Minolta_bizhub_C368.ppd.double-sided

which includes *DefaultKMDuplex: 2Sided

Now, if I want to switch between single-sided and double-sided printing I just double-click on the icon on my Desktop and a terminal window pops-up allowing me to select the new default:

Konica Minolta bizhub C368 printer

Select single-sided or double-sided printing as the default

Enter your user account password.
Password:

[1]-sided, [2]-sided or e[X]it :

Migrating to libglvnd in Gentoo Linux on a laptop with NVIDIA Optimus

In a 2015 post I described how I configured my Gentoo Linux installation to switch between the closed-source NVIDIA driver and the open-source Intel driver on a Clevo W230SS laptop that has NVIDIA Optimus hardware (NVIDIA GeForce GTX 860M GPU plus Intel HD 4600 IGP). I did not want to use Bumblebee, preferring to use only the NVIDIA driver or only the Intel driver, switching between them by running a Bash script then logging out of KDE Plasma and back in again. Basically, the scheme a) swapped the xorg.conf file depending on which driver I wanted to use, and b) used the eselect opengl command to select the applicable OpenGL library. The latest versions of the files in my scheme are listed below if you’re interested (I use LightDM instead of KDM these days, as KDM is no more), otherwise just skip to the section after, titled ‘Migrating to libglvnd’.

Previous scheme using eselect opengl

~/Desktop/Select_NVIDIA_GPU.desktop

[Desktop Entry]
Comment[en_GB]=Run a script to configure your installation to use the NVIDIA GeForce GTX 860M GPU when you restart X Windows
Comment=Run a script to configure your installation to use the NVIDIA GeForce GTX 860M GPU when you restart X Windows
Exec=konsole -e sh /home/fitzcarraldo/nvidia.sh
GenericName[en_GB]=Configure your installation to use the NVIDIA GeForce GTX 860M GPU
GenericName=Configure your installation to use the NVIDIA GeForce GTX 860M GPU
Icon=/home/fitzcarraldo/Pictures/Icons/nvidia_icon.png
MimeType=
Name[en_GB]=NVIDIA GPU
Name=NVIDIA GPU
Path=
StartupNotify=true
Terminal=false
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

~/nvidia.sh

#!/bin/bash
echo
echo "Your installation is currently configured to use the following graphics processor:"
echo
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "nvidia" ]; then
  echo "NVIDIA GeForce GTX 860M"
  echo
  echo "You do not need to do anything. Please close this window."
elif [ "$GPU" = "xorg-x11" ]; then
  echo "Intel HD 4600 Integrated Graphics Processor"
  echo
  echo "This script will configure your installation to use the NVIDIA GeForce GTX 860M GPU all the time."
  echo
  echo "Enter your own password."
  echo
  sudo eselect opengl set nvidia
# See separate configuration of LightDM for NVIDIA GPU and Intel HD Graphics.
  sudo cp /etc/X11/xorg.conf.nvidia /etc/X11/xorg.conf
  echo
  echo "Now you should logout to restart X Windows."
fi
echo
echo -n "Press ENTER to end: "
read ACKNOWLEDGE

/etc/X11/xorg.conf.nvidia

Section "ServerLayout"
    Identifier     "Layout0"
    Screen      1  "nvidia" 0 0
    Inactive       "intel"
EndSection

Section "Monitor"
    Identifier     "Monitor0"
    Option         "DPMS"
    Option         "DPI" "96 x 96"
EndSection

Section "Device"
    Identifier     "nvidia"
    Driver         "nvidia"
    BusID          "PCI:1:0:0"
EndSection

Section "Device"
    Identifier     "intel"
    Driver         "modesetting"
    BusID          "PCI:0:2:0"
EndSection

Section "Screen"
    Identifier     "nvidia"
    Device         "nvidia"
    Monitor        "Monitor0"
    DefaultDepth    24
    Option         "UseDisplayDevice" "none"
    SubSection     "Display"
        Depth       24
        Virtual     1920 1080
    EndSubSection
EndSection

Section "Screen"
    Identifier     "intel"
    Device         "intel"
    Monitor        "Monitor0"
EndSection

~/Desktop/Select_Intel_HD_Graphics.desktop

[Desktop Entry]
Comment[en_GB]=Run a script to configure your installation to use Intel Integrated Graphics when you restart X Windows
Comment=Run a script to configure your installation to use Intel Integrated Graphics when you restart X Windows
Exec=konsole -e sh /home/fitzcarraldo/intel.sh
GenericName[en_GB]=Configure your installation to use Intel HD Graphics
GenericName=Configure your installation to use Intel HD Graphics
Icon=/home/fitzcarraldo/Pictures/Icons/intel-hd-icon.png
MimeType=
Name[en_GB]=Intel HD Graphics
Name=Intel HD Graphics
Path=
StartupNotify=true
Terminal=false
TerminalOptions=\s--noclose
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

~/intel.sh

#!/bin/bash
echo
echo "Your installation is currently configured to use the following graphics processor:"
echo
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "xorg-x11" ]; then
  echo "Intel HD 4600 Integrated Graphics Processor"
  echo
  echo "You do not need to do anything. Please close this window."
elif [ "$GPU" = "nvidia" ]; then
  echo "NVIDIA GeForce GTX 860M"
  echo
  echo "This script will configure your installation to use the"
  echo "Intel HD 4600 Integrated Graphics Controller all the time."
  echo
  echo "Enter your own password."
  echo
  sudo eselect opengl set xorg-x11
# See separate configuration of LightDM for Intel HD Graphics and NVIDIA GPU.
  sudo cp /etc/X11/xorg.conf.intel /etc/X11/xorg.conf
  echo
  echo "Now you should logout to restart X Windows."
fi
echo
echo -n "Press ENTER to end: "
read ACKNOWLEDGE

/etc/X11/xorg.conf.intel

Section "Device" 
   Identifier  "Intel Graphics" 
   Driver      "intel" 
   Option      "AccelMethod" "sna" 
   Option      "TearFree" "true" 
EndSection

/etc/X11/xorg.conf.d/20-opengl.conf

Section "Files"
        ModulePath "/usr/lib/xorg/modules"
        ModulePath "/usr/lib64/xorg/modules"
EndSection

/etc/X11/Sessions/plasma (used by LightDM)

#!/bin/bash
#
# Make sure the following is in /etc/lightdm/lightdm.conf
# display-setup-script=/etc/X11/Sessions/plasma
#
GPU=`eselect opengl list | grep \* | awk '{ print $2 }'`
if [ "$GPU" = "nvidia" ]; then
    xrandr --setprovideroutputsource modesetting NVIDIA-0
    xrandr --auto
fi

Migrating to libglvnd

Well, the above scheme worked fine… until the recent decision by the Gentoo Linux developers to drop the app-eselect/eselect-opengl ebuild and switch the x11-base/xorg-server, media-libs/mesa and x11-drivers/nvidia-drivers to using the libglvnd library:

This package is masked and could be removed soon!
The mask comment indicates that this package is scheduled for removal from our package repository.
Please review the mask information below for more details.

Replaced by media-libs/libglvnd. Masked for removal in 30 days. Bug #728286

Affected packages	app-eselect/eselect-opengl

Author/Date		Matt Turner  (2020-08-11 00:00:00 +0000 UTC)

Without the eselect opengl command, my scripts were scuppered. So I decided to bite the bullet and switch to using libglvnd. It turned out not to be difficult, and I took the following steps to migrate:

  1. Deleted the file /etc/X11/xorg.conf
  2. Created the file /etc/X11/xorg.conf.d/01-nvidia-offload.conf containing the following:
    Section "ServerLayout"
        Identifier "layout"
        Option "AllowNVIDIAGPUScreens"
    EndSection
    
  3. Performed the usual ‘emerge -uvDN @world‘ to update and upgrade the relevant packages, which automatically unmerged app-eselect/eselect-opengl

If I had run into trouble with the installed app-eselect/eselect-opengl blocking the upgrade, I could have worked around that by doing the following:

root # emerge -C eselect-opengl
root # emerge -1v nvidia-drivers mesa xorg-server xorg-drivers

I removed all references to the libglvnd USE flag from /etc/portage/make.conf, and the only place libglvnd is declared explicitly now is in the file /etc/portage/package.use/world because I have a multilib installation:

root # grep libglvnd /etc/portage/package.*/*
/etc/portage/package.use/world:>=media-libs/libglvnd-1.3.1 abi_x86_32

The status of the applicable packages in my installation is now as follows:

root # eix -I nvidia-drivers
[I] x11-drivers/nvidia-drivers
     Available versions:  [M]340.108-r1(0/340)^mtd ~390.132-r4(0/390)^mtd 390.138-r1(0/390)^mtd 435.21-r6(0/435)^mtd 440.100-r2(0/440)^mtd 450.57-r1(0/450)^mtd {+X compat (+)driver gtk3 +kms +libglvnd multilib static-libs +tools uvm wayland ABI_MIPS="n32 n64 o32" ABI_RISCV="lp64 lp64d" ABI_S390="32 64" ABI_X86="32 64 x32" KERNEL="FreeBSD linux"}
     Installed versions:  450.57-r1(0/450)^mtd(22:04:56 14/08/20)(X driver kms libglvnd multilib tools wayland -compat -gtk3 -static-libs -uvm ABI_MIPS="-n32 -n64 -o32" ABI_RISCV="-lp64 -lp64d" ABI_S390="-32 -64" ABI_X86="32 64 -x32" KERNEL="linux -FreeBSD")
     Homepage:            https://www.nvidia.com/Download/Find.aspx
     Description:         NVIDIA Accelerated Graphics Driver

root # eix -I mesa
[I] media-libs/mesa
     Available versions:  20.0.8^t ~20.1.4^t ~20.1.5^t ~20.2.0_rc1^t ~20.2.0_rc2^t **9999*l^t {+X +classic d3d9 debug +dri3 +egl +gallium +gbm gles1 +gles2 +libglvnd +llvm lm-sensors opencl osmesa selinux test unwind vaapi valgrind vdpau vulkan vulkan-overlay wayland xa xvmc zink +zstd ABI_MIPS="n32 n64 o32" ABI_RISCV="lp64 lp64d" ABI_S390="32 64" ABI_X86="32 64 x32" KERNEL="linux" VIDEO_CARDS="freedreno i915 i965 intel iris lima nouveau panfrost r100 r200 r300 r600 radeon radeonsi v3d vc4 virgl vivante vmware"}
     Installed versions:  20.0.8^t(22:03:42 14/08/20)(X classic dri3 egl gallium gbm gles2 libglvnd llvm wayland zstd -d3d9 -debug -gles1 -lm-sensors -opencl -osmesa -selinux -test -unwind -vaapi -valgrind -vdpau -vulkan -vulkan-overlay -xa -xvmc ABI_MIPS="-n32 -n64 -o32" ABI_RISCV="-lp64 -lp64d" ABI_S390="-32 -64" ABI_X86="32 64 -x32" KERNEL="linux" VIDEO_CARDS="i965 intel -freedreno -i915 -iris -lima -nouveau -panfrost -r100 -r200 -r300 -r600 -radeon -radeonsi -vc4 -virgl -vivante -vmware")
     Homepage:            https://www.mesa3d.org/ https://mesa.freedesktop.org/
     Description:         OpenGL-like graphic library for Linux

[I] x11-apps/mesa-progs
     Available versions:  8.4.0 **9999*l {egl gles2}
     Installed versions:  8.4.0(13:53:51 02/05/19)(-egl -gles2)
     Homepage:            https://www.mesa3d.org/ https://mesa.freedesktop.org/ https://gitlab.freedesktop.org/mesa/demos
     Description:         Mesa's OpenGL utility and demo programs (glxgears and glxinfo)

Found 2 matches
root # eix -I xorg-server
[I] x11-base/xorg-server
     Available versions:  1.20.8-r1(0/1.20.8) **9999(0/9999)*l {debug dmx doc +elogind ipv6 kdrive +libglvnd libressl minimal selinux static-libs suid systemd +udev unwind wayland xcsecurity xephyr xnest xorg xvfb}
     Installed versions:  1.20.8-r1(0/1.20.8)(22:07:21 14/08/20)(elogind ipv6 libglvnd udev wayland xorg -debug -dmx -doc -kdrive -libressl -minimal -selinux -static-libs -suid -systemd -unwind -xcsecurity -xephyr -xnest -xvfb)
     Homepage:            https://www.x.org/wiki/ https://gitlab.freedesktop.org/xorg/xserver/xorg-server
     Description:         X.Org X servers

root # eix -I xorg-drivers
[I] x11-base/xorg-drivers
     Available versions:  1.20-r2 **9999*l {INPUT_DEVICES="elographics evdev joystick libinput synaptics vmmouse void wacom" VIDEO_CARDS="amdgpu ast dummy fbdev freedreno geode glint i915 i965 intel mga nouveau nv nvidia omap qxl r128 radeon radeonsi siliconmotion tegra vc4 vesa via virtualbox vmware"}
     Installed versions:  1.20-r2(22:05:41 14/08/20)(INPUT_DEVICES="evdev synaptics -elographics -joystick -libinput -vmmouse -void -wacom" VIDEO_CARDS="i965 intel nvidia -amdgpu -ast -dummy -fbdev -freedreno -geode -glint -i915 -mga -nouveau -nv -omap -qxl -r128 -radeon -radeonsi -siliconmotion -tegra -vc4 -vesa -via -virtualbox -vmware")
     Homepage:            https://wiki.gentoo.org/wiki/No_homepage
     Description:         Meta package containing deps on all xorg drivers

I can now delete the line display-setup-script=/etc/X11/Sessions/plasma in /etc/lightdm/lightdm.conf, and delete the script /etc/X11/Sessions/plasma, as the script no longer works and the xrandr commands in it are no longer necessary in any case. The files and scripts Select_NVIDIA_GPU.desktop, nvidia.sh, xorg.conf.nvidia, Select_Intel_HD_Graphics.desktop, intel.sh and xorg.conf.intel are also redundant now and can be deleted.

After rebooting, the LightDM login screen appears as usual and I can login to the Desktop Environment. I can connect an external monitor to the laptop via either VGA cable or HDMI cable and both methods work, and I can switch between the laptop monitor and the external monitor using KDE Plasma’s ‘System Settings’ > ‘Display Configuration’, so everything appears to be working correctly.

The command xrandr --listproviders (add ‘--verbose‘ to provide more information) lists both the NVIDIA and Intel video devices, so I assume everything is working correctly:

user $ xrandr --listproviders
Providers: number : 2
Provider 0: id: 0x47 cap: 0xb, Source Output, Sink Output, Sink Offload crtcs: 4 outputs: 4 associated providers: 0 name:Intel
Provider 1: id: 0x203 cap: 0x0 crtcs: 0 outputs: 0 associated providers: 0 name:NVIDIA-G0

It appears that the default is to use the Intel IGP:

user $ glxinfo | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)
user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=Intel __GLX_VENDOR_LIBRARY_NAME=mesa glxinfo  | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: Intel Open Source Technology Center
OpenGL renderer string: Mesa DRI Intel(R) HD Graphics 4600 (HSW GT2)

unless I use environment variables explicitly to specify that the NVIDIA GPU be used for a specific application:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia glxinfo  | grep -E 'OpenGL (vendor|renderer)'
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: GeForce GTX 860M/PCIe/SSE2

Performance seems reasonable:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia __GL_SYNC_TO_VBLANK=0 glxgears
27197 frames in 5.0 seconds = 5439.292 FPS
27332 frames in 5.0 seconds = 5466.274 FPS
27857 frames in 5.0 seconds = 5571.184 FPS
27553 frames in 5.0 seconds = 5510.447 FPS
27128 frames in 5.0 seconds = 5425.556 FPS
^C

To run a program such as LibreCAD using the NVIDIA GPU I can do the following:

user $ __NV_PRIME_RENDER_OFFLOAD_PROVIDER=NVIDIA-G0 __GLX_VENDOR_LIBRARY_NAME=nvidia librecad

I need to play around more to understand how to use nvidia-drivers and libglvnd with the NVIDIA Optimus hardware in this laptop, but at least I have managed to migrate from app-eselect/eselect-opengl to media-libs/libglvnd before the former is dropped from the Portage tree in the near future.

That UPS you bought for your home server may not be as useful as you think

Some years ago I decided to install a server at home for use as a NAS (network-attached storage) in my home network, and for an Internet-facing server. I live in a place where blackouts are very infrequent (perhaps a couple per year), but occasionally the mains drops out for only a second or two. I suspect these very short dropouts occur when substation switchgear operates, but have no way of being sure. Anyway, with a server running 24/7 I obviously wanted protection against any loss of the mains supply.

I ended up buying a 700VA APC Back-UPS ES-BE700G-UK, which has four mains sockets that are battery-backed and also have surge protection, plus another four mains sockets that have surge protection but are not battery-backed. Additionally, it has two RJ45 sockets to provide pass-through filtering for an Ethernet connection. It also has a USB port for connection to the server so that it can transmit unsolicited status information to the server (including requesting the server to shutdown) and can also be interrogated by the server using the apcaccess command. The APC UPS daemon works with this model of UPS, and was relatively easy to set up. APC, formerly American Power Conversion Corporation, is a subsidiary of European company Schneider Electric. My UPS was manufactured in The Philippines.

I have three devices plugged into the battery-backed sockets on the APC UPS: the server, an external 6TB USB HDD connected to the server for automated daily backups by the server, and a 5-port Ethernet switch. The battery in the UPS would provide between 15 and 20 minutes of power when the mains fails, although I have configured the UPS to trigger the server to shutdown when 30 per cent of the battery power remains, as battery life is reduced considerably if its power is allowed to drain completely. In case you’re wondering why my router is not also plugged into the UPS, due to the position of the broadband provider’s socket the router is in a different room and I have therefore had to connect it to a different UPS, an iLEPO multi-functional DC UPS (the ECO PLUS 412P, which is tiny but can keep the router powered for several hours). Obviously the router needs to be connected to a UPS, otherwise the server would not be able to send me e-mails when there is a mains power cut. Being able to receive UPS status e-mails from the server is important to me when I am away from home on work trips.

So I thought I had covered all bases, and, indeed, the UPS proved useful on several occasions. I would quite often be on a work trip and receive an e-mail from the server informing me that mains power to the UPS had been lost, then another e-mail soon after informing me that mains power to the UPS had returned. Only once did the power cut last longer than the battery capacity, and the server was shutdown automatically.

Now, the life of the 12-volt lead-acid battery in the APC UPS is supposed to last approximately three to five years. The life will depend on how many times the battery is discharged and ambient temperature.

While I was away from home on a long work trip, suddenly I could no longer connect to my server and I had not received an e-mail from the server informing me of any problem. Luckily it was near the end of my trip so I was not too inconvenienced. When I arrived home I found that the UPS was sounding an alarm and was not supplying power to the server even though there was mains supply to the UPS. It transpired that the UPS battery had suddenly died without warning and could no longer hold a charge, and this had happened while there was mains supply to the UPS, i.e. there had not been a power cut while I was away. Fortunately there was no loss of data on the server; I was able to run fsck during boot-up.

This failure was annoying on two counts. Firstly, the battery was only about thirteen months old (the manufacturing date stamped on the UPS box was only two or three months before the date I purchased the UPS). Secondly, I certainly did not expect the UPS to stop supplying power to the server while there was mains supply to the UPS. The APC white paper on UPS topologies, ‘The Different Types of UPS Systems‘, does not make this behaviour clear.

It turns out that the type of UPS topology (‘Standby’ — see the model’s Technical Specifications) in this model of UPS does not continue to provide power to connected equipment when the UPS battery either fails or is disconnected for whatever reason when there is mains power supply to the UPS. A quick search of the Web showed me that I was not alone in discovering this ‘feature’: an APC Back-UPS 350 owner posted ‘UPS Battery Backup — useless when the battery dies?‘.

From what I have read, the so-called ‘Line Interactive’ UPS topology does not suffer this shortcoming, so, the next time I have to buy a UPS for a piece of equipment that requires power 24/7, I will buy a line-interactive UPS rather than a standby UPS. But, before purchasing, I will be sure to ask the manufacturer what the precise model would do if its battery fails or is disconnected while there is mains supply to the UPS. The APC line-interactive UPSs are more expensive than the APC Back-UPS models; now I know why. It’s a pity I was not aware of the shortcoming of the Back-UPS models, as I would have spent more and bought a UPS that continues to work when the battery dies while there is mains supply. I would also hope the UPS would issue an alarm if the battery has failed or is disconnected while there is mains supply. Be sure to ask the manufacturer all these questions if you cannot tolerate a sudden loss of power to your equipment if the battery dies while there is mains supply.

Anyway, after checking that the dead battery was indeed useless I replaced it with a new Yuasa battery that has lasted nearly three years now. I will be replacing it shortly as a precaution, even though it has not had to be used much at all since I installed it. I have not replaced the APC Back-UPS model but I will be replacing the battery at least every three years just to be cautious, and of course taking the old batteries to my local waste disposal centre to be recycled properly. By the way, it is possible to purchase a 12-volt battery manufactured by one of the reputable battery manufacturers such as Yuasa with the same specification as the APC battery, for a significantly lower price than APC charges for replacement batteries (which I suspect are badged by APC in any case).