Stopping my laptop spontaneously resuming immediately after Suspend to RAM

If I selected ‘Suspend to RAM’ via the Desktop Environment in the Gentoo Linux installation on my Clevo W230SS laptop, the laptop did suspend but then immediately resumed automatically. The same thing happened if I suspended the laptop using either of the following commands from the command line:

root # pm-suspend

user $ qdbus org.kde.Solid.PowerManagement /org/freedesktop/PowerManagement Suspend

This behaviour was annoying, as it meant I had to shut down the laptop completely when I was not at my desk for a long time, rather than just being able to suspend the laptop.

Problem 1: USB devices

I usually have several USB devices connected to my laptop when I am at home or in the office, and I began to suspect that these USB connections were somehow causing Linux to resume as soon as it had suspended. Searching the Web turned up a Q&A page that seemed to confirm my suspicion: Why does my laptop resume immediately after suspend? I installed the utility acpitool mentioned on that Web page and used it with the ‘-w‘ option to check which wakeup-capable USB devices were currently enabled in my installation:

root # acpitool -w
   Device       S-state   Status   Sysfs node
  ---------------------------------------
  1. RP01         S4    *disabled  pci:0000:00:1c.0
  2. PXSX         S4    *disabled
  3. RP02         S4    *disabled
  4. PXSX         S4    *disabled
  5. RP03         S4    *disabled  pci:0000:00:1c.2
  6. PXSX         S4    *disabled  pci:0000:03:00.0
  7. RP04         S4    *disabled  pci:0000:00:1c.3
  8. PXSX         S4    *disabled  pci:0000:04:00.0
  9.            *disabled  platform:rtsx_pci_sdmmc.0
  10.           *disabled  platform:rtsx_pci_ms.0
  11. RLAN        S4    *disabled
  12. RP05        S4    *disabled
  13. PXSX        S4    *disabled
  14. RP06        S4    *disabled
  15. PXSX        S4    *disabled
  16. RP07        S4    *disabled
  17. PXSX        S4    *disabled
  18. RP08        S4    *disabled
  19. PXSX        S4    *disabled
  20. GLAN        S4    *disabled
  21. EHC1        S3    *enabled   pci:0000:00:1d.0
  22. EHC2        S3    *enabled   pci:0000:00:1a.0
  23. XHC         S3    *disabled  pci:0000:00:14.0
  24. HDEF        S4    *disabled  pci:0000:00:1b.0
  25. PEG0        S4    *disabled  pci:0000:00:01.0
  26. PEGP        S4    *disabled  pci:0000:01:00.0
  27. PEGA        S4    *disabled
  28. PWRB        S3    *enabled   platform:PNP0C0C:0
^C
root #

(I had to use Ctrl-C to get back to the command prompt.)

I then used the command ‘acpitool -W <device number>‘ on each of the three enabled devices (21, 22 and 28 above) in order to find out which of them needed to be disabled in order for my laptop to remain suspended when I suspended it. I found that I only needed to disable devices EHC1 (pci:0000:00:1d.0) and EHC2 (pci:0000:00:1a.0) to be able to suspend the laptop successfully:

root # acpitool -W 21 | grep 21
  Changed status for wakeup device #21 (EHC1)
  21. EHC1        S3    *disabled  pci:0000:00:1d.0
^C
root # acpitool -W 22 | grep 22
  Changed status for wakeup device #22 (EHC2)
  22. EHC2        S3    *disabled  pci:0000:00:1a.0
^C
root # pm-suspend

In this laptop these two devices are two internal USB root hubs:

user $ lsusb -t
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/8p, 480M
        |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 480M
            |__ Port 3: Dev 5, If 0, Class=Mass Storage, Driver=usb-storage, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/2p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M
        |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
            |__ Port 1: Dev 6, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
            |__ Port 4: Dev 7, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
            |__ Port 4: Dev 7, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M
        |__ Port 3: Dev 4, If 0, Class=Wireless, Driver=btusb, 12M
        |__ Port 3: Dev 4, If 1, Class=Wireless, Driver=btusb, 12M
        |__ Port 4: Dev 5, If 0, Class=Video, Driver=uvcvideo, 480M
        |__ Port 4: Dev 5, If 1, Class=Video, Driver=uvcvideo, 480M

The next challenge was to find out how to disable and re-enable the two devices automatically when I suspend and resume the installation. Further searching of the Web turned up another Q&A page which pointed me in the right direction: How to run a script when suspending/resuming? – Sony VAIO Ubuntu 12.04. It turns out that you need to put a script of the following form in the directory /etc/pm/sleep.d/:

#!/bin/bash

case "$1" in
    suspend)
        # executed on suspend
        ;;
    resume) 
        # executed on resume
        ;;
    *)
        ;;
esac

If you want the script to run when hibernating and thawing, the tests would be for ‘hibernate‘ and ‘thaw‘ instead of ‘suspend‘ and ‘resume‘.

The thread [SOLVED] Computer immediately resumes after suspend in the KDE Forums almost gave me the solution I needed. I created a file /etc/pm/sleep.d/01-toggle-usb-hubs containing the following:

#!/bin/sh
#
username=fitzcarraldo
userhome=/home/$username
export XAUTHORITY="$userhome/.Xauthority"
export DISPLAY=":0"
#
case "${1}" in
    suspend|hibernate)
        # Unbind ehci-pci for the device 0000:00:1a.0
        echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci-pci/unbind
        # Unbind ehci-pci for the device 0000:00:1d.0
        echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/unbind
    ;;
    resume|thaw)
        # Bind ehci-pci for the device 0000:00:1a.0
        echo -n "0000:00:1a.0" | tee /sys/bus/pci/drivers/ehci-pci/bind
        # Bind ehci-pci for the device 0000:00:1d.0
        echo -n "0000:00:1d.0" | tee /sys/bus/pci/drivers/ehci-pci/bind
    ;;
    *)
        exit $NA
    ;;
esac

I obtained the device details from the output of the ‘acpitools -w‘ command listed earlier and by looking in the directory /sys/bus/pci/drivers/ehci-pci:

root # ls /sys/bus/pci/drivers/ehci-pci
0000:00:1a.0  0000:00:1d.0  bind  new_id  remove_id  uevent  unbind

Notice that the script tests for either ‘suspend‘ or ‘hibernate‘ to disable the two devices, and tests for either ‘resume‘ or ‘thaw‘ to enable the two devices.

I made the script executable:

root # chmod +x /etc/pm/sleep.d/01-toggle-usb-hubs


Problem 2: Blank X Windows display due to NVIDIA closed-source driver bug

However, a problem remained: My laptop has an NVIDIA GPU and, when resuming from suspension, the X Windows display (Virtual Terminal 7) was a blank blank screen with only the mouse pointer visible. Now, I also experience this effect if I switch from Virtual Terminal 7 to e.g. Virtual terminal 1 (Ctrl-Alt-F1) and then switch back to Virtual Terminal 7 (Ctrl-Alt-F7). Apparently this is due to a bug in the closed-source NVIDIA driver (I am currently using Gentoo package x11-drivers/nvidia-drivers-358.16-r1). However, if I first disable compositing before switching to another virtual terminal, the X Windows display on Virtual Terminal 7 is still visible when I switch back to Virtual Terminal 7. So I thought I would try disabling compositing before suspending to RAM, and created a script /etc/pm/sleep.d/02-toggle-compositing containing the following:

#!/bin/sh
#
username=fitzcarraldo
userhome=/home/$username
export XAUTHORITY="$userhome/.Xauthority"
export DISPLAY=":0"
#
case "$1" in
    suspend|hibernate)
        su $username -c "qdbus org.kde.kwin /KWin toggleCompositing" &
    ;;
    resume|thaw)
        su $username -c "qdbus org.kde.kwin /KWin toggleCompositing" &
    ;;
    *)
        exit $NA
    ;;
esac

As I have KDE 4 on this laptop, I made the script use the command ‘qdbus org.kde.kwin /KWin toggleCompositing‘ to disable/enable compositing, so replace that command with the appropriate command if you are not using KDE.

I made the script executable:

root # chmod +x /etc/pm/sleep.d/02-toggle-compositing

Now both the scripts in the directory /etc/pm/sleep.d/ run when I suspend or resume the laptop, and everything works as expected. Mission accomplished! :-)

SDDM keyboard layout

I am using Plasma 5 in Gentoo Linux ~amd64 with OpenRC on my Compal NBLB2 laptop. The Display Manager I am using is SDDM, and the log-in screen was using the US keyboard layout, the only keyboard layout available in the log-in screen’s keyboard menu. Searching the Web told me that SDDM uses the keyboard layout specified in the file /etc/X11/xorg.conf.d/00-keyboard.conf. The trouble is, it doesn’t (at least not in my case). The file already existed in my installation, and its contents are listed below:

Section "InputClass"
    Identifier "keyboard"
    MatchIsKeyboard "yes"
    Option "XkbLayout" "gb,us,br,es"
    Option "XkbVariant" ""
    Option "XkbOptions" "grp:alt_shift_toggle"
EndSection

The X.Org keyboard layouts specified in the file are available once I have logged in to the Plasma 5 Desktop, but none of the four keyboards (gb, us, br and es) were displayed by SDDM in its log-in screen menu. Eventually I discovered it is possible to specify the keyboard layouts in the file /usr/share/sddm/scripts/Xsetup which, by default, contains only the following:

#!/bin/sh
# Xsetup - run as root before the login dialog appears

I edited the file to contain the list of keyboards I wanted SDDM to allow me to choose from on the log-in screen:

#!/bin/sh
# Xsetup - run as root before the login dialog appears
setxkbmap gb,us,br,es

Now the SDDM log-in screen displays the national flags of those four keyboard languages in its keyboard menu, and I can select which keyboard layout to use for typing my password to log in to the Plasma 5 Desktop.

NetworkManager: Failed to activate – The name org.freedesktop.NetworkManager was not provided by any .service files

Because I need to connect quickly and easily to numerous wired and wireless networks (DHCP or static IP addressing), I use NetworkManager in my Gentoo Linux amd64 installation running OpenRC and KDE 4. My Clevo W230SS laptop has an Intel Dual Band Wireless-AC 7260 Plus Bluetooth adapter card, and my installation uses the iwlwifi module:

# lspci -knn | grep Net -A2
03:00.0 Network controller [0280]: Intel Corporation Wireless 7260 [8086:08b1] (rev bb)
        Subsystem: Intel Corporation Dual Band Wireless-AC 7260 [8086:4070]
        Kernel driver in use: iwlwifi
# lsmod | grep iwl
iwlmvm                143919  0
iwlwifi                75747  1 iwlmvm

As I am using NetworkManager instead of netifrc, in accordance with the instructions in the Gentoo Wiki article on NetworkManager I do not have any net.* services enabled (not even net.lo):

# rc-update show -v
       NetworkManager |      default                 
                acpid |                              
            alsasound |                              
         avahi-daemon |                              
       avahi-dnsconfd |                              
               binfmt | boot                         
            bluetooth |      default                 
             bootmisc | boot                         
         busybox-ntpd |                              
     busybox-watchdog |                              
                clamd |                              
          consolefont |                              
           consolekit |      default                 
               cronie |      default                 
         cups-browsed |      default                 
                cupsd |      default                 
                 dbus |      default                 
                devfs |                       sysinit
               dhcpcd |                              
                dhcpd |                              
             dhcrelay |                              
            dhcrelay6 |                              
                dmesg |                       sysinit
              dropbox |                              
           fancontrol |                              
                 fsck | boot                         
                 fuse |                              
           git-daemon |                              
                  gpm |                              
              hddtemp |                              
             hostname | boot                         
              hwclock | boot                         
            ip6tables |                              
             iptables |                              
              keymaps | boot                         
            killprocs |              shutdown        
    kmod-static-nodes |                       sysinit
           lm_sensors |                              
                local |      default                 
           localmount | boot                         
             loopback | boot                         
      mit-krb5kadmind |                              
          mit-krb5kdc |                              
       mit-krb5kpropd |                              
              modules | boot                         
             mount-ro |              shutdown        
                 mtab | boot                         
                mysql |                              
                  nas |                              
         net.enp4s0f1 |                              
               net.lo |                              
             netmount |      default                 
           ntp-client |                              
                 ntpd |                              
           nullmailer |                              
              numlock |                              
  nvidia-persistenced |                              
           nvidia-smi |                              
              osclock |                              
              pciparm |                              
               procfs | boot                         
              pwcheck |                              
            pydoc-2.7 |                              
            pydoc-3.4 |                              
               rfcomm |                              
                 root | boot                         
               rsyncd |                              
            s6-svscan |                              
                samba |      default                 
                saned |                              
            saslauthd |                              
            savecache |              shutdown        
                 sntp |                              
                 sshd |      default                 
             svnserve |                              
                 swap | boot                         
            swapfiles | boot                         
              swclock |                              
               sysctl | boot                         
                sysfs |                       sysinit
            syslog-ng |      default                 
        teamviewerd10 |                              
         termencoding | boot                         
             timidity |                              
         tmpfiles.dev |                       sysinit
       tmpfiles.setup | boot                         
               twistd |                              
                 udev |                       sysinit
                  ufw | boot                         
              urandom | boot                         
       wpa_supplicant |                              
                  xdm |      default                 
            xdm-setup |

I have left the netmount service enabled in case I want to use network-attached file shares at home or in one of the various office locations where I work.

Networking works fine on my laptop with the many wired and wireless networks I have used except for one particular public wireless network (it is in an airport, has multiple Access Points, and its Access Points only support 802.11a/b/g, which may or may not be relevant) for which the following message would usually appear in a pop-up window when I tried to connect to the network from the KDE network management GUI after start-up:

Failed to activate
The name org.freedesktop.NetworkManager was not provided by any .service files

Error message displayed by KDE when trying to connect to one specific network

Error message displayed by KDE when trying to connect to one specific network


This occurred with both networkmanager-1.0.2-r1 and networkmanager-1.0.6, the two Stable Branch releases of NetworkManager currently available in Gentoo Linux.

The wireless network is not the only network at that particular location, and the ‘Failed to activate’ message occurred whichever network (wireless or wired) I tried to access at that location. When this problem occurred, it transpired that the NetworkManager service was not running (it had crashed):

$ nmcli d
Error: NetworkManager is not running.
$ rc-status
Runlevel: default
 dbus                   [  started  ]
 NetworkManager         [  crashed  ]
 netmount               [  started  ]
 syslog-ng              [  started  ]
 cupsd                  [  started  ]
 samba                  [  crashed  ]
 consolekit             [  started  ]
 cronie                 [  started  ]
 bluetooth              [  started  ]
 xdm                    [  started  ]
 cups-browsed           [  started  ]
 sshd                   [  started  ]
 local                  [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed
 xdm-setup              [  started  ]
 avahi-daemon           [  started  ]
Dynamic Runlevel: manual

(I am not bothered that Samba crashes in that particular location. It crashes even if a connection is established, because the public wireless network does not provide network file systems. Samba works fine when I connect the laptop to an office network or to my home network.)

Even if the ‘Failed to activate’ message occurred, sometimes (but not always) the laptop could still connect to networks after I restarted the NetworkManager service (albeit sometimes it was necessary to restart it more than once):

# /etc/init.d/NetworkManager restart

When it is possible to connect to networks, the NetworkManager service is of course running:

$ nmcli d
DEVICE    TYPE      STATE        CONNECTION           
sit0      sit       connected    sit0                 
wlp3s0    wifi      connected    Free_Airport_Internet
enp4s0f1  ethernet  unavailable  --                   
lo        loopback  unmanaged    --        
$ rc-status
Runlevel: default
 dbus                   [  started  ]
 NetworkManager         [  started  ]
 netmount               [  started  ]
 syslog-ng              [  started  ]
 cupsd                  [  started  ]
 samba                  [  crashed  ]
 consolekit             [  started  ]
 cronie                 [  started  ]
 bluetooth              [  started  ]
 xdm                    [  started  ]
 cups-browsed           [  started  ]
 sshd                   [  started  ]
 local                  [  started  ]
Dynamic Runlevel: hotplugged
Dynamic Runlevel: needed
 xdm-setup              [  started  ]
 avahi-daemon           [  started  ]
Dynamic Runlevel: manual

I searched the Web for the error message and, based on a recommendation on the Web page ‘nm-applet gives errors‘ claiming the problem is due to the iwlwifi driver when used with an Intel 7260 controller, I created a file /etc/modprobe.d/iwlwifi.conf containing the following line, and rebooted:

options iwlwifi power_save=0

However, the error message still occurred. So I changed the iwlwifi module options line to the following, as also recommended on that page, and rebooted:

options iwlwifi 11n_disable=1 power_save=0

However, the error message still occurred.

The default value for OpenRC’s rc_depend_strict variable is YES if rc_depend_strict is not declared in the file /etc/rc.conf, but I do not think that is the cause of the problem:

# Do we allow any started service in the runlevel to satisfy the dependency
# or do we want all of them regardless of state? For example, if net.eth0
# and net.eth1 are in the default runlevel then with rc_depend_strict="NO"
# both will be started, but services that depend on 'net' will work if either
# one comes up. With rc_depend_strict="YES" we would require them both to
# come up.
#rc_depend_strict="YES"

As already mentioned, sometimes just restarting the NetworkManager service once or more did enable the laptop to connect to the network. This made me wonder whether the problem had something to do either with the timing of the launch of the NetworkManager service or with the timing of the service establishing a connection. As netmount is the only other network-related service enabled at start-up, I checked the netmount service’s configuration file /etc/conf.d/netmount to see what it contained (it’s the same in both the latest stable openrc-0.17 and the latest testing openrc-0.18.2):

# You will need to set the dependencies in the netmount script to match
# the network configuration tools you are using. This should be done in
# this file by following the examples below, and not by changing the
# service script itself.
#
# Each of these examples is meant to be used separately. So, for
# example, do not set rc_need to something like "net.eth0 dhcpcd".
#
# If you are using newnet and configuring your interfaces with static
# addresses with the network script, you  should use this setting.
#
#rc_need="network"
#
# If you are using oldnet, you must list the specific net.* services you
# need.
#
# This example assumes all of your netmounts can be reached on
# eth0.
#
#rc_need="net.eth0"
#
# This example assumes some of your netmounts are on eth1 and some
# are on eth2.
#
#rc_need="net.eth1 net.eth2"
#
# If you are using a dynamic network management tool like
# networkmanager, dhcpcd in standalone mode, wicd, badvpn-ncd, etc, to
# manage the network interfaces with the routes to your netmounts, you
# should list that tool.
#
#rc_need="networkmanager"
#rc_need="dhcpcd"
#rc_need="wicd"
#
# The default setting is designed to be backward compatible with our
# current setup, but you are highly discouraged from using this. In
# other words, please change it to be more suited to your system.
#
rc_need="net"

As I am using NetworkManager rather than netifrc, I followed the instructions in the file’s comments and changed the file’s contents from:

rc_need="net"

to:

rc_need="networkmanager"

After making the above change, the console messages at boot-up included a new message:

* ERROR: netmount needs service(s) networkmanager

That message made sense: rc_need had been set to "networkmanager" and, obviously, netmount can only do its job if NetworkManager is running (AND a network connection has been established). However, notice that the name of the NetworkManager service initscript is /etc/init.d/NetworkManager, not /etc/init.d/networkmanager. In other words, the instructions in /etc/conf.d/netmount are wrong: the name of the service is actually ‘NetworkManager‘, not ‘networkmanager‘. So I changed /etc/conf.d/netmount to contain rc_need="NetworkManager" instead of rc_need="networkmanager" and, unsurprisingly, the above-mentioned error message no longer occurs. I have filed Gentoo Bugzilla Bug Report No. 564846 requesting that the comment in the configuration file be changed.

Nevertheless, the ‘Failed to activate’ message still occurred when I tried to connect to any network at that location by using the DE’s network management GUI, and therefore I still needed to restart the NetworkManager service manually in order to be able to connect to any network there. Although I am not yet sure of the root cause and solution, I have found a work-around which avoids me having to manually restart the NetworkManager service, as explained below.

Although OpenRC correctly launches the NetworkManager service, that service remains inactive until it actually establishes a network connection. This is not a bug, it is the way OpenRC and NetworkManager work (see the explanation in the Gentoo Forums thread NetworkManager has started, but is inactive). This is why the following console message appears during boot-up:

* WARNING: NetworkManager has already started, but is inactive

If you did not configure NetworkManager to connect automatically to a network, after logging-in to the DE you will need to use the DE’s network management GUI (plasma-nm in the case if KDE, nm-applet in the case of e.g. Xfce) to tell NetworkManager to connect to the desired network. However, I found that waiting that long before trying to connect is too late to avoid the ‘Failed to activate’ problem, i.e. NetworkManager crashes after a while. I do not know why this happens, but it usually happens only when I am at the location covered by one specific wireless network (which is why I wonder if the problem is a result of that network only supporting 802.11a/b/g). By configuring NetworkManager to connect automatically to the wireless network which seemed to trigger the problem, the NetworkManager service tries to connect earlier. It is possible to configure NetworkManager to do this either by using the DE network GUI and ticking ‘Automatically connect to this network when it is available’ for the relevant network connection, or by directly editing the relevant connection’s file in the directory /etc/NetworkManager/system-connections/.

Of the various wired and wireless connections I had configured on the laptop, I had named the problematic wireless network’s connection ‘Free_Airport_Internet’. So I edited the file /etc/NetworkManager/system-connections/Free_Airport_Internet and deleted the line ‘autoconnect=false‘ in the [connections] section of the file (the default value of the autoconnect variable is TRUE – see man nm-settings). I could instead have done this by using the DE’s network manager GUI and ticking ‘Automatically connect to this network when it is available’ for that network connection. Now, when the laptop boots, NetworkManager tries to connect to that network and the ‘Failed to activate’ problem is avoided. This works with or without the iwlwifi driver options I mentioned above, so, despite the claim on the Web page I referenced above, the root cause of the problem does not appear to be the iwlwifi driver. What I don’t understand is why the problem only seems to occur with one particular network (a public wireless network which happens to only support 802.11a/b/g), i.e. even if none of the NetworkManager connection files in my installation have been configured to try to establish a connection automatically, with all the other wireless networks I have used in other locations (I believe those all support at least 802.11a/b/g/n) I have been able to establish a connection manually by using the DE’s network management GUI.

The bottom line

If your installation uses NetworkManager and you experience the ‘Failed to activate’ message when trying to connect to networks from the DE’s network management GUI, check if the NetworkManager service is running. You can check by using the command ‘nmcli d‘ in a console. If it is not running, try to restart the NetworkManager service from the command line. If the connection is not already configured to start automatically, configure it to start automatically in order to try to make NetworkManager become active at an early stage.

POSTSCRIPT (November 6, 2015)

The two links below are to old bug reports regarding earlier versions of NetworkManager having trouble using wireless networks with multiple Access Points. I wonder if the problem I saw with NetworkManager crashing when not configured to connect automatically to the specific network I mentioned above is somehow related to those problems:

background scanning causes drivers to disassociate – WiFi roaming causes NetworkManager to lose routing

network-manager roams to (none) ((none)) – background scanning

Roaming to BSSID “(none)” certainly happens with this particular network too, as shown by the messages in the laptop’s system log from yesterday when I was using the laptop with that network (the laptop was stationary the whole time):

# cat /var/log/messages | grep "Nov  5 11" | grep NetworkManager | grep \(none\)
Nov  5 11:01:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 04:C5:A4:C3:F9:EE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:01:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:13:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:13:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to 04:C5:A4:C3:F9:EE (Free_Airport_Internet)
Nov  5 11:15:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 04:C5:A4:C3:F9:EE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:15:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:19:22 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:19:23 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)
Nov  5 11:49:50 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID B8:BE:BF:69:89:6E (Free_Airport_Internet) to (none) ((none))
Nov  5 11:49:50 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to 68:BC:0C:A1:3C:DE (Free_Airport_Internet)
Nov  5 11:51:51 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID 68:BC:0C:A1:3C:DE (Free_Airport_Internet) to (none) ((none))
Nov  5 11:51:51 clevow230ss NetworkManager[2459]:   (wlp3s0): roamed from BSSID (none) ((none)) to B8:BE:BF:69:89:6E (Free_Airport_Internet)

Today I’m using a hotel network in my hotel room, and that does not roam to BSSID “(none)”, but I don’t know if my room is within range of more than one Access Point:

# cat /var/log/messages | grep "Nov  6" | grep NetworkManager | grep \(none\)
#

Anyway, with the work-around described in this post I have not had any further trouble accessing the particular network, but it would be interesting to know the root cause.

Using a keyboard shortcut in Linux to add an e-mail signature giving current location and local time

In my previous post I showed how to find the current time at any town or city Worldwide from the command line in Gentoo Linux. My interest in a command to do this is not to use it on the command line per se, but to use the command in a keyboard shortcut to insert a signature at the end of my e-mails.

I have to travel internationally frequently because of my work, but I leave my laptop’s hardware clock set to UTC and the system clock set to the local time of my home town. This means that, irrespective of where I am in the World, the e-mail client (Thunderbird, in my case) uses the local time of my home town in e-mail headers and calenders. It is not practical to reconfigure Linux for each timezone I happen to be in (see my post Configuring the Linux clock), and, in any case, I want the file system’s timestamps to use one timezone only and all the timestamps in my e-mails and the e-mail client’s calender to use one timezone only, so there is less chance of me getting confused. I could have configured the installation to use UTC for the system clock, but I prefer the system clock to use the timezone of my home town. Of course, even though the system clock is always set to the timezone of my home town, on the Panel clock I select the timezone of the location where I happen to be, so that the Panel clock displays the local time in that timezone.

I wanted to be able to insert a signature at the end of each e-mail, stating my current location and the current time at that location, so that the person receiving the e-mail could tell from where in the World I sent the e-mail and the local time it was sent, as that local time could differ from the time shown in the e-mail header. For example, let us assume that Jane, who lives in the UK and whose system clock is configured for the timezone Europe/London, is making a brief visit to Perth, Australia and sends an e-mail to Dave in the UK at 06:36 on 11 October (Perth time). The e-mail below illustrates the type of signature I wanted to achieve.

Subject: Site visit
From: Jane <jane@acompany.com>
To: Dave <dave@acompany.com>
Date: Sat Oct 10 2015 23:36:40 GMT+0100 (BST)

Hello Dave,

This is to let you know that I have just arrived in Perth and will be
visiting site at 09:00 local time to speak to the client. Tomorrow p.m.
I have a meeting scheduled with our local project manager, so I would
appreciate it if you would e-mail the latest documentation to me. I will
not have spare time until I’m in my room at the hotel tonight but will
read the documents tomorrow a.m. in readiness for the meeting with
the local project manager. Thanks in advance.

Regards,
Jane
Current location: Perth (Australia)
Local time now: Sat Oct 11 06:36:31 2015 AWST

As you can see above, because the OS on Jane’s and Dave’s laptops is configured for the timezone Europe/London, the e-mail header shows the current time in the UK when the e-mail was sent, which was October 10, 23:36 British Summer Time (22:36 UTC), and the signature shows the corresponding local time in Perth, Australia, which was October 11, 06:36 Australian Western Standard Time. It becomes even more confusing if the computer of the person receiving the e-mail is configured for a third timezone. For example, let’s say Dave is based in Seattle, USA rather than the UK. His e-mail client would then display the time in that timezone when the e-mail was sent. This is usually my case, i.e. my Linux installation is configured for Timezone1 but I happen to be in Timezone2 when I send an e-mail to someone who is based in Timezone3 and whose OS is configured for that timezone.

I wanted to use a keyboard shortcut to add a signature to the end of my e-mails, as shown above. I therefore created the Bash script listed below, which I named timezone_signature_GeoNames.sh:

#!/bin/bash

location=$(kdialog --title "Current Location" --inputbox "Enter your location:")

localtime=$(perl /home/fitzcarraldo/now1.pl $location)
place=`echo $localtime | cut -d'|' -f1`
place=$place" "`echo $localtime | cut -d'|' -f2`
timezone=`echo $localtime | cut -d'|' -f4`

if [ $location != "" ]; then
  echo -n "Current location: "
  echo $place
  echo -n "Local time now:"
  /usr/sbin/zdump ${timezone} | cut -d' ' -f2-
fi
echo

Notice that the Bash script uses the GUI dialogues utility kdialog to display a pop-up window prompting me to enter the name of a town/city. As I am using KDE I opted to use a dialogues utility developed for use in KDE, but I could have used Zenity instead.

The Perl script now1.pl is a variant of the Perl script now.pl described in my previous post, modified very slightly in order to facilitate formatting of the output by the Bash script, and is listed below.

#!perl

use strict;
use warnings;

use DateTime;
use Geo::GeoNames;
use URI::Escape;
use Encode;

binmode STDOUT, ':encoding(UTF-8)';

my $city = decode("UTF-8", @ARGV ? shift : 'London');
# N.B. Replace London with your home town/city.

my $geo = Geo::GeoNames->new( username => '************' );
# N.B. Replace the asterisks with your GeoNames user name.

my $result = $geo->search(
q       => uri_escape_utf8($city),
maxRows => 1,
style   => 'FULL'
);

defined $result->[0] or die "Unrecognized city '$city'\n";

my $city_name    = $result->[0]->{name};
my $country_name = $result->[0]->{countryName};
my $time_zone    = $result->[0]->{timezone}{content};
my $time_now     = DateTime->now( time_zone => $time_zone );

#print "$city_name ($country_name) $time_now ($time_zone)\n";

print "$city_name|($country_name)|$time_now|$time_zone\n";

exit 0;

The only thing remaining was to configure a keyboard shortcut to launch the Bash script. I opted to use the key combination Ctrl-Alt-z for the shortcut. As I am using KDE I could have used KDE’s ‘System Settings’ > ‘Shortcuts and Gestures’> ‘Custom Shortcuts’ to specify the shortcut and the name of the script it launches. However, as I also use AutoKey for various shortcuts, I opted to use that instead, so I used the AutoKey GUI to create a shortcut named ‘Insert Current Time’ to use the following command:

output = system.exec_command("/home/fitzcarraldo/timezone_signature_GeoNames.sh")
keyboard.send_keys(output)

Use

I compose my e-mails as usual, and, after entering my name at the end of the e-mail, I press Ctrl-Alt-z. A window then pops up prompting me to enter my current location, which I do and then click on ‘OK’. The location and current time at that location are then added to the end of the e-mail, and it just remains for me to click on the ‘Send’ button in the e-mail client’s window. As the Perl script now1.pl uses the Internet to access the GeoNames database, my laptop must be connected to the Internet when I use the shortcut.

KDialog window that pops up when I use the keyboard shortcut

KDialog window that pops up when I use the keyboard shortcut

If the town/city name consists of more than one word (Rio de Janeiro, for example) then replace spaces with hyphens when you enter the location name in the pop-up window (Rio-de-Janeiro, for example) and then the keyboard shortcut will return the correct location and local time:

Current location: Rio de Janeiro (Brazil)
Local time now: Fri Oct 16 09:28:19 2015 BRT

Find the time now at any town or city Worldwide from the command line in Gentoo Linux

In my hunt for a command to return the current time at any town or city in the World, I recently found a Perl script now.pl posted in 2012 by Jim Monty on grokbase. The script uses a Perl module to access the database of the GeoNames Web site. To use the module you need to have a user account at the GeoNames Web site and be connected to the Internet. The script also uses the modules URI::Escape and DateTime.

In the case of Gentoo Linux, ebuilds for some of the Perl modules used by now.pl are not available in the main Portage tree, so I installed them from a Portage local overlay, as explained below.

First I created in my local overlay an ebuild for the Perl module Geo::GeoNames and then merged it:

# mkdir -p /usr/local/portage/dev-perl/Geo-GeoNames
# cd /usr/local/portage/dev-perl/Geo-GeoNames
# nano -w Geo-GeoNames-1.01.ebuild
# ebuild Geo-GeoNames-1.01.ebuild manifest
# emerge --ask Geo-GeoNames

The ebuild Geo-GeoNames-1.01.ebuild I created is listed below:

EAPI=5

MODULE_AUTHOR=BDFOY
inherit perl-module

DESCRIPTION="Provides a perl interface to the webservices found at http://api.geonames.org"

SLOT="0"
KEYWORDS="alpha amd64 ~arm hppa ia64 ~mips ppc ppc64 ~s390 ~sh sparc x86 ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris"
IUSE=""

RDEPEND="
        dev-perl/Module-Build
        "
DEPEND="${RDEPEND}"

SRC_TEST=do

I’m not sure if I declared the correct dependencies in DEPEND and RDEPEND, but the Geo::GeoNames module is merged in my installation and functions correctly.

The Perl script also uses the Perl module URI::Escape, which I found out is part of the package dev-perl/URI in the Portage main tree and was already installed, so I did not need to do anything further as far as that was concerned.

Next I needed to install the Perl module Date::Time. Fortunately there is an ebuild for dev-perl/DateTime in the main Portage tree, so I merged that package directly:

# emerge --ask DateTime

Then I surfed to the GeoNames Web site and registered for a user account. My thanks go to the people who provide and maintain the site and database.

I then created a file /home/fitzcarraldo/now.pl containing the Perl script listed in Jim Monty’s post of Aug 19, 2012 on the Web page: [DateTime] Is there timezone data for any Indian cities such as Mumbai, Dehli, &c.?. My thanks also go to Jim Monty for posting his script.

My initial attempts at running now.pl resulted in an error message warning about a missing Mojo::UserAgent Perl module. I therefore needed to install the package Mojolicious but, unfortunately, the main Portage tree does not have an ebuild for it. I could have either added a third-party overlay (e.g. srcshelton) which contains a Mojolicious ebuild or downloaded the ebuild and put it in my local overlay. I opted for the latter, and merged it:

# mkdir -p /usr/local/portage/dev-perl/Mojolicious
# cd /usr/local/portage/dev-perl/Mojolicious
# cp /home/fitzcarraldo/Downloads/Mojolicious-5.30.ebuild .
# ebuild Mojolicious-5.30.ebuild manifest
# emerge --ask Mojolicious

Despite the examples given in Jim Monty’s post using now.pl with place names containing diacritics, in my case the script could not handle them, so I made a couple of small modifications, and the script I’m using is show below:

#!perl
use strict;
use warnings;

use DateTime;
use Geo::GeoNames;
use URI::Escape;
use Encode;

binmode STDOUT, ':encoding(UTF-8)';

my $city = decode("UTF-8", @ARGV ? shift : 'London');

my $geo = Geo::GeoNames->new( username => '***********' );
# N.B. Replace the asterisks with your GeoNames user name.

my $result = $geo->search(
q       => uri_escape_utf8($city),
maxRows => 1,
style   => 'FULL'
);

defined $result->[0] or die "Unrecognized city '$city'\n";

my $city_name    = $result->[0]->{name};
my $country_name = $result->[0]->{countryName};
my $time_zone    = $result->[0]->{timezone}{content};
my $time_now     = DateTime->now( time_zone => $time_zone );

print "$city_name ($country_name) $time_now ($time_zone)\n";

exit 0;

I made the script executable and ensured my user account could use it:

# chmod +x /home/fitzcarraldo/now.pl
# chown fitzcarraldo:fitzcarraldo /home/fitzcarraldo/now.pl

Now if I enter the name of a town or city anywhere in the World while my laptop is connected to the Internet, the script prints the town/city name, country, local time and the time zone’s name as given in the zoneinfo database (a.k.a. ‘Olsen database’, ‘tz database‘ and ‘IANA time zone database’):

$ cd
$ perl now.pl
London (United Kingdom) 2015-09-25T23:10:16 (Europe/London)
$ perl now.pl "London Canada"
London (Canada) 2015-09-25T18:10:22 (America/Toronto)
$ perl now.pl Paris
Paris (France) 2015-09-26T00:10:29 (Europe/Paris)
$ perl now.pl "New York"
New York (United States) 2015-09-25T18:10:41 (America/New_York)
$ perl now.pl Tokyo
Tokyo (Japan) 2015-09-26T07:10:50 (Asia/Tokyo)
$ perl now.pl "Mexico City"
Mexico City (Mexico) 2015-09-25T17:10:59 (America/Mexico_City)
$ perl now.pl "Kuala Lumpur"
Kuala Lumpur (Malaysia) 2015-09-26T06:11:09 (Asia/Kuala_Lumpur)
$ perl now.pl "São Paulo"
São Paulo (Brazil) 2015-09-25T19:11:29 (America/Sao_Paulo)
$ perl now.pl Maceio
Maceió (Brazil) 2015-09-25T19:11:39 (America/Maceio)
$ perl now.pl Maceió
Maceió (Brazil) 2015-09-25T19:11:48 (America/Maceio)
$ perl now.pl "Várzea Grande"
Várzea Grande (Brazil) 2015-09-25T18:12:04 (America/Cuiaba)
$ perl now.pl "Mos Eisley"
Unrecognized city 'Mos Eisley'

now.pl works by first using the Geo::GeoNames module to look up in the GeoNames database via the Internet the time zone for the town/city you have specified, then using the Date::Time module to look up the time in that time zone from the zoneinfo data in your installation, based on the time now in your installation’s system clock. In other words, if your system clock is, for example, 3 minutes ahead of actual time then the time returned by now.pl for the relevant time zone would also be 3 minutes fast. But if your system clock is correct, the script would return an accurate time for the requested town/city.

My interest in finding a command that returns the current time at any town or city around the Globe was because I wanted to create a keyboard shortcut to insert a signature in my e-mails, displaying my current location and the local time wherever I happened to be (I have to travel internationally frequently because of my work). In my next post I will explain how I created such an e-mail signature.

Gentoo Linux: Run a script at shutdown, but not when rebooting

In Gentoo Linux it is straightforward to run scripts automatically when the OS starts (boots) and stops (either shutting down or rebooting). You simply need to place an executable script file in the directory /etc/local.d/ with the suffix ‘.start‘ or ‘.stop‘, depending on whether you want the script to run at the beginning or end of your Linux session. The file /etc/local.d/README (complete with ‘sequentially’ misspelt) explains it better:

This directory should contain programs or scripts which are to be run
when the local service is started or stopped.

If a file in this directory is executable and it has a .start extension,
it will be run when the local service is started. If a file is
executable and it has a .stop extension, it will be run when the local
service is stopped.

All files are processed in lexical order.

Keep in mind that files in this directory are processed sequencially,
and the local service is not considered started or stopped until
everything is processed, so if you have a process which takes a long
time to run, it can delay your boot or shutdown processing.

Scripts with a ‘.stop‘ suffix are launched both when you shutdown your Linux installation and when you reboot it. However, sometimes you may not want to run a script when you reboot your installation. A typical example would be a script to backup your hard drive; you would probably only want it to run when you have finished for the day and you are shutting down and powering off your machine. So, how do you achieve that? I initially thought I would be able to use the ‘runlevel‘ command or the RUNLEVEL environment variable in a script (see man runlevel regarding both). But I could not get my script /etc/local.d/10-run_on_shutdown.stop to work using either. However, the command ‘who -r‘ (‘who --runlevel‘) does work for me in Gentoo Linux with OpenRC:

$ cat /etc/local.d/10-run_on_shutdown.stop
#!/bin/bash
if [ `who -r | awk '{print $2}'` = "0" ]; then
  echo "shutting down" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
elif [ `who -r | awk '{print $2}'` = "6" ]; then
  echo "rebooting" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
else
  echo "neither rebooting nor shutting down" >> /home/fitzcarraldo/test.txt
  date >> /home/fitzcarraldo/test.txt
fi
$

After rebooting, then shutting down and booting, then rebooting again, the contents of the file test.txt show that the above-mentioned simple script works as intended:

$ cat test.txt
rebooting
Sun  6 Sep 12:42:11 BST 2015
shutting down
Sun  6 Sep 12:46:04 BST 2015
rebooting
Sun  6 Sep 12:49:31 BST 2015
$

So the following script /etc/local.d/10-run_on_shutdown.stop will do the desired job:

$ cat /etc/local.d/10-run_on_shutdown.stop
#!/bin/bash
if [ `who -r | awk '{print $2}'` = "0" ]; then
  ######################################################################
  # Put Bash commands here to be executed on shutdown but not on reboot.
  ######################################################################
fi
$

Don’t forget to make the script executable:

# chmod +x /etc/local.d/10-run_on_shutdown.stop

Gentoo Linux installations without initramfs: Updating Intel CPU microcode

This post explains how I configured the Gentoo Linux (amd64) installation on my Clevo W230SS laptop to make it update the Intel CPU microcode using the kernel Microcode Early Update driver.

Back in April I installed Gentoo Linux Stable and built the kernel using the default manual configuration steps given in the Gentoo Handbook, and my installation therefore did not use an initramfs. The contents of the /boot directory were as listed below:

# ls -1 /boot
System.map-3.18.11-gentoo
config-3.18.11-gentoo
grub
lost+found
vmlinuz-3.18.11-gentoo

Contrast the above with the boot directory of the Gentoo Linux Testing (~amd64) installation on my Compal NBLB2 laptop, which does use an initramfs because I built the kernel using the optional genkernel utility:

# ls -1 /boot
System.map-genkernel-x86_64-3.18.11-gentoo
boot
grub
initramfs-genkernel-x86_64-3.18.11-gentoo
kernel-genkernel-x86_64-3.18.11-gentoo
lost+found

Since I wrote my earlier post on updating CPU microcode, the use of a kernel module and initscript to update CPU microcode has been dropped (in Gentoo Linux, at least). This is because updating CPU microcode relatively late in the boot process may cause problems if some processes have started before the update has taken place. The only safe way to update CPU microcode is to use the kernel’s built-in Microcode Early Update driver (METHOD 2 in my earlier post).

Now, new versions of the relevant Gentoo Linux ebuilds (microcode-ctl-1.28-r1, microcode-data-20150121-r1 and iucode_tool-1.3) have recently been released (see Gentoo Bug Report No. 528712). If a Gentoo Linux installation does not use an initramfs, the microcode-data ebuild now includes an ‘initramfs‘ USE flag which you can set in order to create a minimal initramfs to load the CPU microcode at boot. Below I explain in detail how I configured my installation to update the CPU microcode early during boot.

Before doing anything at all, I checked the microcode version for my CPU (Intel Core i7-4810MQ @ 2.80GHz):

# grep microcode /proc/cpuinfo
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
microcode   : 0x12
# dmesg | grep microcode
[    0.262544] microcode: CPU0 sig=0x306c3, pf=0x10, revision=0x12
[    0.262641] microcode: CPU1 sig=0x306c3, pf=0x10, revision=0x12
[    0.262740] microcode: CPU2 sig=0x306c3, pf=0x10, revision=0x12
[    0.262841] microcode: CPU3 sig=0x306c3, pf=0x10, revision=0x12
[    0.262939] microcode: CPU4 sig=0x306c3, pf=0x10, revision=0x12
[    0.263038] microcode: CPU5 sig=0x306c3, pf=0x10, revision=0x12
[    0.263138] microcode: CPU6 sig=0x306c3, pf=0x10, revision=0x12
[    0.263236] microcode: CPU7 sig=0x306c3, pf=0x10, revision=0x12
[    0.263367] microcode: Microcode Update Driver: v2.00 , Peter Oruba

Fortunately I did not need to rebuild the kernel as I had already configured it back in April when I installed Gentoo, with a view to implementing early microcode updating at some point:

# grep CONFIG_BLK_DEV_INITRD /usr/src/linux/.config
CONFIG_BLK_DEV_INITRD=y
# grep CONFIG_MICROCODE /usr/src/linux/.config
CONFIG_MICROCODE=y
CONFIG_MICROCODE_INTEL=y
# CONFIG_MICROCODE_AMD is not set
CONFIG_MICROCODE_OLD_INTERFACE=y
CONFIG_MICROCODE_INTEL_EARLY=y
# CONFIG_MICROCODE_AMD_EARLY is not set
CONFIG_MICROCODE_EARLY=y
# grep CONFIG_INITRAMFS_SOURCE /usr/src/linux/.config
CONFIG_INITRAMFS_SOURCE=""

Then I set the initramfs USE flag and unmasked the ~amd64 ebuilds created by Gentoo developer SpanKY (microcode-ctl-1.28-r1.ebuild, microcode-data-20150121-r1.ebuild and iucode_tool-1.3.ebuild) as discussed in the above-mentioned Gentoo bug report:

# cat /etc/portage/package.use/microcode-data
sys-apps/microcode-data initramfs
# cat /etc/portage/package.accept_keywords/microcode-data
sys-apps/microcode-data ~amd64
sys-apps/iucode_tool ~amd64
# cat /etc/portage/package.accept_keywords/microcode-ctl
sys-apps/microcode-ctl ~amd64

Then I merged the packages:

# emerge --ask microcode-ctl microcode-data

This resulted in the following files:

# ls -la /lib/firmware/microcode.cpio
-rw-r--r-- 1 root root 663552 Aug 26 15:06 /lib/firmware/microcode.cpio
# ls -la /lib/firmware/intel-ucode
total 768
drwxr-xr-x  2 root root  4096 Aug 26 15:06 .
drwxr-xr-x 62 root root 16384 Aug 26 15:06 ..
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-03-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-05-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-05-01
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-05-02
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-05-03
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-06-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-06-05
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-06-0a
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-06-0d
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-01
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-02
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-07-03
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-08-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-08-03
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-08-06
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-08-0a
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-09-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0a-00
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0a-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0b-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0b-04
-rw-r--r--  1 root root  2048 Aug 26 15:06 06-0d-06
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0e-08
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0e-0c
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0f-02
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-0f-06
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-0f-07
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-0f-0a
-rw-r--r--  1 root root 28672 Aug 26 15:06 06-0f-0b
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-0f-0d
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-16-01
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-17-06
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-17-07
-rw-r--r--  1 root root 24576 Aug 26 15:06 06-17-0a
-rw-r--r--  1 root root 14336 Aug 26 15:06 06-1a-04
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-1a-05
-rw-r--r--  1 root root 15360 Aug 26 15:06 06-1c-02
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-1c-0a
-rw-r--r--  1 root root  4096 Aug 26 15:06 06-1d-01
-rw-r--r--  1 root root  6144 Aug 26 15:06 06-1e-04
-rw-r--r--  1 root root  7168 Aug 26 15:06 06-1e-05
-rw-r--r--  1 root root  8192 Aug 26 15:06 06-25-02
-rw-r--r--  1 root root  3072 Aug 26 15:06 06-25-05
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-26-01
-rw-r--r--  1 root root 10240 Aug 26 15:06 06-2a-07
-rw-r--r--  1 root root 16384 Aug 26 15:06 06-2d-06
-rw-r--r--  1 root root 17408 Aug 26 15:06 06-2d-07
-rw-r--r--  1 root root 13312 Aug 26 15:06 06-2f-02
-rw-r--r--  1 root root 12288 Aug 26 15:06 06-3a-09
-rw-r--r--  1 root root 21504 Aug 26 15:06 06-3c-03
-rw-r--r--  1 root root 14336 Aug 26 15:06 06-3d-04
-rw-r--r--  1 root root 13312 Aug 26 15:06 06-3e-04
-rw-r--r--  1 root root 11264 Aug 26 15:06 06-3e-06
-rw-r--r--  1 root root 15360 Aug 26 15:06 06-3e-07
-rw-r--r--  1 root root 28672 Aug 26 15:06 06-3f-02
-rw-r--r--  1 root root 20480 Aug 26 15:06 06-45-01
-rw-r--r--  1 root root 23552 Aug 26 15:06 06-46-01
-rw-r--r--  1 root root  4096 Aug 26 15:06 0f-00-07
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-00-0a
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-01-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-04
-rw-r--r--  1 root root  8192 Aug 26 15:06 0f-02-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-02-06
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-07
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-02-09
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-03-02
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-03-03
-rw-r--r--  1 root root  7168 Aug 26 15:06 0f-03-04
-rw-r--r--  1 root root 10240 Aug 26 15:06 0f-04-01
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-04-03
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-04-04
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-04-07
-rw-r--r--  1 root root  9216 Aug 26 15:06 0f-04-08
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-04-09
-rw-r--r--  1 root root  4096 Aug 26 15:06 0f-04-0a
-rw-r--r--  1 root root  3072 Aug 26 15:06 0f-06-02
-rw-r--r--  1 root root  6144 Aug 26 15:06 0f-06-04
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-06-05
-rw-r--r--  1 root root  2048 Aug 26 15:06 0f-06-08

(By the way, the file 06-3c-03 is the microcode file for my particular CPU: Family 06h, Model 03Ch, Stepping 03h, as determined from the CPU World Web site.)

Then I copied to the boot directory the cpio file created when I merged the packages:

# cp /lib/firmware/microcode.cpio /boot/

Then I added an initrd line to /boot/grub/grub.cfg as shown below:

# grep -B 15 -A 1 initrd /boot/grub/grub.cfg

### BEGIN /etc/grub.d/10_linux ###
menuentry 'Gentoo GNU/Linux' --class gentoo --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-525a90f1-8ad2-44a3-ade3-20f18a0a9595' {
        load_video
        insmod gzio
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1  f6ffc085-66fe-4bbe-b080-cec355749f85
        else
          search --no-floppy --fs-uuid --set=root f6ffc085-66fe-4bbe-b080-cec355749f85
        fi
        echo    'Loading Linux 3.18.11-gentoo ...'
        linux   /vmlinuz-3.18.11-gentoo root=/dev/sda5 ro  drm_kms_helper.edid_firmware=edid/1920x1080_Clevo_W230SS.bin i915.modeset=1 rcutree.rcu_idle_gp_delay=1
        initrd /microcode.cpio
}

After rebooting:

# grep microcode /proc/cpuinfo
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
microcode       : 0x1c
# dmesg | grep microcode
[    0.000000] CPU0 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.049968] CPU1 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.065070] CPU2 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.080101] CPU3 microcode updated early to revision 0x1c, date = 2014-07-03
[    0.268736] microcode: CPU0 sig=0x306c3, pf=0x10, revision=0x1c
[    0.268838] microcode: CPU1 sig=0x306c3, pf=0x10, revision=0x1c
[    0.268935] microcode: CPU2 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269034] microcode: CPU3 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269131] microcode: CPU4 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269230] microcode: CPU5 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269329] microcode: CPU6 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269448] microcode: CPU7 sig=0x306c3, pf=0x10, revision=0x1c
[    0.269570] microcode: Microcode Update Driver: v2.00 , Peter Oruba

As you can see above, the microcode early update kernel driver updates the microcode version to 0x1c at boot (cf. 0x12 originally). If you have a different model of CPU to mine, of course the version in your case could be different.

Note that the line ‘initrd /lib/firmware/microcode.cpio‘ in the file grub.cfg does not work for me. It has to be ‘initrd /microcode.cpio‘ and the file microcode.cpio has to be in the /boot directory:

# ls /boot
System.map-3.18.11-gentoo  config-3.18.11-gentoo  grub  lost+found  microcode.cpio  vmlinuz-3.18.11-gentoo

Note also that the precise steps specified in Comment #41 of Gentoo Bug Report No. 528712 do not work for me and others (see Gentoo Forums thread microcode-data-20150121-r1 with USE=initramfs: kernel panic). If I build the kernel with CONFIG_INITRAMFS_SOURCE="/lib/firmware/microcode.cpio", delete the line ‘initrd /microcode‘ from grub.cfg, delete the file /boot/microcode.cpio and reboot, the kernel panics and the last two console lines are as follows:

[    3.142079] drm_kms_helper: panic occurred, switching back to text console
[    3.142879] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,5)

Unless Gentoo developer SpanKY explains how he managed to get the procedure he gave in Comment #41 of Gentoo Bug Report No. 528712 to work, it seems the normal behaviour when applying the steps he gave would be for the kernel to panic. Even Gentoo developer Daniel Pielmeier experienced a kernel panic when he applied SpanKY‘s steps (Comment #54 of Gentoo Bug Report No. 528712).

As the procedure I gave above works fine, I therefore reverted to using CONFIG_INITRAMFS_SOURCE="", copying /lib/firmware/microcode.cpio to /boot/microcode.cpio again and re-adding the line ‘initrd /microcode.cpio‘ in the file grub.cfg. However, if you did not have an initramfs and were able to get the precise procedure given in Comment #41 of Gentoo Bug Report #528712 to work, please post a comment here.

Installing the DraftSight Free 2D CAD application in Gentoo Linux

I occasionally have to view AutoCAD files and had been using a 2009 version of VariCAD Viewer for Linux, installed from an RPM package using the rpm command in Gentoo Linux. It was the only version that I could get to work correctly in Gentoo Linux. Versions from more recent years would either not install at all or would install but not run correctly. And the 2009 version of VariCAD Viewer could not open more-recent AutoCAD files. So I had been looking for an alternative for quite a while.

Recently I found out about DraftSight, which is produced by Dassault Systèmes SolidWorks Corp. and is available for Windows, Mac OS and Linux. Apart from the commercial versions DraftSight Professional and DraftSight Enterprise, there is also a free version, DraftSight Free, which is billed as ‘straightforward 2D CAD software for students, hobbyists and other individuals’. I thought this would suit my purposes, as it can read and write DWG and DXF files (see the features page on the DraftSight Web site).

The Gentoo Linux betagarden overlay has ebuilds for releases of DraftSight Free. The package is a proprietary binary package, the Gentoo ebuild is named media-gfx/draftsight-bin and the current version in the betagarden overlay is 1.6.1_beta.

So I added the betagarden overlay using Layman, downloaded the file draftSight.deb (DraftSight 2015 beta) from the DraftSight Web site and copied it to /usr/portage/distfiles/draftsight-1.6.1_beta.deb as specified in the ebuild, and issued the usual emerge command to merge the package. However the ebuild would not install the package whatever I tried: Portage gave an error message that the .deb file could not be downloaded (despite it already being in the distfiles directory). In the end I copied the ebuild and its files sub-directory to /usr/local/portage/media-gfx/draftsight-bin/ in my local overlay, disconnected from the network and merged the package:

# layman -a betagarden
# rm /usr/portage/distfiles/draftsight*
# cp /home/fitzcarraldo/Downloads/draftSight.deb /usr/portage/distfiles/draftsight-1.6.1_beta.deb
# mkdir -p /usr/local/portage/media-gfx/draftsight-bin/files
# cp /var/lib/layman/betagarden/media-gfx/draftsight-bin/draftsight-bin-1.6.1_beta.ebuild /usr/local/portage/media-gfx/draftsight-bin/
# cp /var/lib/layman/betagarden/media-gfx/draftsight-bin/files/* /usr/local/portage/media-gfx/draftsight-bin/files/
# layman -d betagarden
# cd /usr/local/portage/media-gfx/draftsight-bin/
# ebuild draftsight-bin-1.6.1_beta.ebuild manifest
# emerge --ask draftsight-bin

This worked, and I can now launch DraftSight from the KDE launcher’s menu (the only additional thing I did was to specify an icon myself using the KDE Menu Editor, as the DraftSight entry in the KDE launcher menu was icon-less) or by issuing the command ‘draftsight‘ from the command line.

DraftSight is a big advance on using an old version of VariCAD Viewer, and I have finally found a decent 2D CAD application to use in Linux.

The problem of scanning using USB multi-function printers in Linux (success at last)

After my investigations described in a couple of earlier posts ([1], [2]), I finally got Gentoo Linux to scan reliably via the USB connection to my Canon MP560 MFP (multi-function peripheral), a single USB device with three interfaces: scanner (Interface 0); printer (Interface 1); mass storage (Interface 2). Well, ninety-nine per cent reliably, if that isn’t a contradiction in terms. The formula for success? I had to do all the following:

  1. Stop the kernel from binding the usb-storage driver to the device.

  2. Create a UDEV rule to modify the ACL (access control list) of the device to give both the ‘lp‘ and ‘scanner‘ groups Read-Write access to the device.

  3. Create a UDEV rule to: a) change the owner of the device from ‘root‘ to my user account (fitzcarraldo); b) change the device’s group to ‘scanner‘ instead of ‘lp‘; c) give all users Read-Write access to the device (see my note about this at the end of this post).

  4. Disable the SANE backend from accessing the MP560 via the network.

Let’s look in more detail at each of these …

Stop the kernel from binding the usb-storage driver to the device

Originally I had built the usb-storage driver into the kernel (CONFIG_USB_STORAGE=y). During the course of my investigations into this problem I rebuilt the kernel with CONFIG_USB_STORAGE=m, i.e. I rebuilt the driver as an external module, although it should not matter either way.

The vendor ID (04a9) and product ID (173e) of the MP560 can be found using the lsusb command:

# lsusb | grep -i canon
Bus 001 Device 007: ID 04a9:173e Canon, Inc. MP560

If the usb-storage driver is built as an external module, the kernel configuration file will include the following:

# grep CONFIG_USB_STORAGE= /usr/src/linux/.config
CONFIG_USB_STORAGE=m

In this case, it is possible to stop the driver binding to the USB storage interface in the MP560 by creating a ‘quirk’ in the file /etc/modprobe.d/usb-storage.conf as shown below:

# cat /etc/modprobe.d/usb-storage.conf
options usb-storage quirks=04a9:173e:i

If the usb-storage driver is built into the kernel, the kernel configuration file will include the following:

# grep CONFIG_USB_STORAGE= /usr/src/linux/.config
CONFIG_USB_STORAGE=y

In this case, it is possible to stop the driver binding to the USB storage interface in the MP560 by adding a ‘quirk’ (usb-storage.quirks=<idVendor>:<idProduct>:i) to the kernel boot line as shown below (ignore the rest of the parameters shown below, as yours are likely to be different):

# grep usb-storage /boot/grub/grub.cfg
linux /vmlinuz-3.18.11-gentoo root=/dev/sda5 ro drm_kms_helper.edid_firmware=edid/1920x1080_Clevo_W230SS.bin i915.modeset=1 rcutree.rcu_idle_gp_delay=1 usb-storage.quirks=04a9:173e:i

If you edit the file /boot/grub/grub.cfg directly, the change will be lost if you rebuild or upgrade in future. The ‘proper’ way to add the quirk would be to add it to the list of kernel boot parameters in GRUB_CMDLINE_LINUX_DEFAULT in the file /etc/default/grub and regenerate grub.cfg using the command ‘grub2-mkconfig -o /boot/grub/grub.cfg‘.

Create a UDEV rules file to modify the device’s ACL

I created a UDEV rules file /etc/udev/rules.d/99-canon-mp560.rules containing the following:

# ACL settings for Canon PIXMA MP560 printer MFP
ATTR{idVendor}=="04a9", ATTR{idProduct}=="173e", GOTO="canon"
GOTO="canon_end"
 
LABEL="canon"
RUN+="/bin/setfacl -m g:scanner:rw -m g:lp:rw $env{DEVNAME}"
TEST=="/var/run/ConsoleKit/database", \
        RUN+="udev-acl --action=$env{ACTION} --device=$env{DEVNAME}"
 
LABEL="canon_end"

Create a UDEV rules file to change the owner, group and permissions of the device

The file 41-libsane.rules in my installation is the only UDEV rules file in the directory /lib/udev/rules.d/ that explicitly mentions the MP560:

# grep 173e /lib/udev/rules.d/*
/lib/udev/rules.d/41-libsane.rules:ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173e", MODE="0664", GROUP="scanner", ENV{libsane_matched}="yes"

As the USB device was always in the ‘lp‘ group (see the output of the ‘ls -la‘ command [1]), the above UDEV rule was clearly being overridden by another rule, but which one in the long list of rules files created automatically when I installed the OS and various packages (see below)?

# ls -F1 /lib/udev/rules.d/
10-ft-rockey.rules
10-virtualbox.rules
40-gentoo.rules
40-usb-media-players.rules
41-libsane.rules
42-usb-hid-pm.rules
50-udev-default.rules
56-hpmud.rules
60-block.rules
60-cdrom_id.rules
60-drm.rules
60-evdev.rules
60-persistent-alsa.rules
60-persistent-input.rules
60-persistent-storage-tape.rules
60-persistent-storage.rules
60-persistent-v4l.rules
60-serial.rules
61-accelerometer.rules
64-btrfs.rules
69-cd-sensors.rules
70-libgphoto2.rules
70-mouse.rules
70-printers.rules
70-touchpad.rules
70-udev-acl.rules
75-net-description.rules
75-probe_mtd.rules
77-mm-cinterion-port-types.rules
77-mm-ericsson-mbm.rules
77-mm-huawei-net-port-types.rules
77-mm-longcheer-port-types.rules
77-mm-mtk-port-types.rules
77-mm-nokia-port-types.rules
77-mm-pcmcia-device-blacklist.rules
77-mm-platform-serial-whitelist.rules
77-mm-simtech-port-types.rules
77-mm-telit-port-types.rules
77-mm-usb-device-blacklist.rules
77-mm-usb-serial-adapters-greylist.rules
77-mm-x22x-port-types.rules
77-mm-zte-port-types.rules
77-nm-olpc-mesh.rules
78-sound-card.rules
80-drivers.rules
80-mm-candidate.rules
80-net-name-slot.rules
80-udisks2.rules
85-regulatory.rules
90-alsa-restore.rules
90-libgpod.rules
90-network.rules
90-pulseaudio.rules
95-cd-devices.rules
95-upower-battery-recall-dell.rules
95-upower-battery-recall-fujitsu.rules
95-upower-battery-recall-gateway.rules
95-upower-battery-recall-ibm.rules
95-upower-battery-recall-lenovo.rules
95-upower-battery-recall-toshiba.rules
95-upower-csr.rules
95-upower-hid.rules
95-upower-wup.rules
97-hid2hci.rules
99-fuse.rules
99-ntfs3g.rules
99-nvidia.rules

Anyway, I created a UDEV rules file /etc/udev/rules.d/95-libsane.rules to change the owner of the MP560 USB device from ‘root‘ to me (i.e. user name ‘fitzcarraldo‘), to put the device in the ‘scanner‘ group instead of the ‘lp‘ group, and to give all users Read-Write permission for the device:

ATTRS{idVendor}=="04a9", ATTRS{idProduct}=="173e", MODE="0666", OWNER="fitzcarraldo", GROUP="scanner", ENV{libsane_matched}="yes"

So I now have two user-created UDEV rules files:

# ls /etc/udev/rules.d/
95-libsane.rules 99-canon-mp560.rules

Note that user-created UDEV rules files should be put in the directory /etc/udev/rules.d/, not the directory /lib/udev/rules.d/ which is reserved for UDEV rules installed when you install the OS and by packages you install later. Unfortunately, there is no consistency in UDEV rules file names and their contents between Linux distributions, which makes debugging UDEV rules even more difficult. Higher numbered rules files override lower-numbered rules files.

I then switched off the MP560 and switched it on again. The two UDEV rules files I created had worked as intended. The ownership and group of the device had changed, and so had the permissions and ACL:

# ls -la /dev/bus/usb/001
total 0
drwxr-xr-x  2 root         root       200 Jul 29 10:10 .
drwxr-xr-x  4 root         root        80 Jul 29 09:56 ..
crw-rw-r--  1 root         usb     189, 0 Jul 29 11:25 001
crw-rw-r--  1 root         usb     189, 1 Jul 29 09:56 002
crw-rw-r--  1 root         usb     189, 2 Jul 29 11:25 003
crw-rw-r--  1 root         usb     189, 3 Jul 29 09:56 004
crw-rw-r--  1 root         usb     189, 4 Jul 29 11:25 005
crw-rw-r--  1 root         usb     189, 5 Jul 29 11:25 006
crw-rw-r--  1 root         usb     189, 7 Jul 29 11:25 008
crw-rw-rw-+ 1 fitzcarraldo scanner 189, 8 Jul 29 11:27 009

# getfacl /dev/bus/usb/001/009
getfacl: Removing leading '/' from absolute path names
# file: dev/bus/usb/001/009
# owner: fitzcarraldo
# group: scanner
user::rw-
user:fitzcarraldo:rw-
group::rw-
group:lp:rw-
group:scanner:rw-
mask::rw-
other::rw-

Disable the SANE backend from accessing the MP560 via the network

Although scanning via the USB connection sometimes still works if I have also specified a network connection in the file /etc/sane.d/pixma.conf, apparently the two interfaces should not normally be enabled simultaneously. See the post [sane-devel] Pixma 530 series – tested and not working by SANE developer Rolf Bensch:

Please disconnect the scanner from network and try again. The backend
has problems if both network and USB are connected at once.

Therefore, to try using SANE to access the MP560 via USB, I disabled network access to the MP560 by commenting out the URI in the relevant SANE backend configuration file, which in the case of the MP560 is the file /etc/sane.d/pixma.conf. I commented out the line ‘bjnp://192.168.1.78‘ which I had previously inserted to enable me to scan via my home network because the USB connection was unreliable.

Trying to scan

I then checked if the USB-connected scanner is detected by SANE when running as root user and when running under my user account:

# scanimage -L
device `pixma:04A9173E_1653C4' is a CANON Canon PIXMA MP560 multi-function peripheral
# sane-find-scanner -q
found USB scanner (vendor=0x04a9 [Canon], product=0x173e [MP560 series]) at libusb:001:010
# exit
exit
$ scanimage -L
device `pixma:04A9173E_1653C4' is a CANON Canon PIXMA MP560 multi-function peripheral
$ sane-find-scanner -q
found USB scanner (vendor=0x04a9 [Canon], product=0x173e [MP560 series]) at libusb:001:010

The test using the scanimage command worked:

$ scanimage -d pixma:04A9173E_1653C4 -T
scanimage: scanning image of size 638x877 pixels at 24 bits/pixel
scanimage: acquiring RGB frame, 8 bits/sample
scanimage: reading one scanline, 1914 bytes...  PASS
scanimage: reading one byte...          PASS
scanimage: stepped read, 2 bytes...     PASS
scanimage: stepped read, 4 bytes...     PASS
scanimage: stepped read, 8 bytes...     PASS
scanimage: stepped read, 16 bytes...    PASS
scanimage: stepped read, 32 bytes...    PASS
scanimage: stepped read, 64 bytes...    PASS
scanimage: stepped read, 128 bytes...   PASS
scanimage: stepped read, 256 bytes...   PASS
scanimage: stepped read, 512 bytes...   PASS
scanimage: stepped read, 1024 bytes...  PASS
scanimage: stepped read, 2048 bytes...  PASS
scanimage: stepped read, 2047 bytes...  PASS
scanimage: stepped read, 1023 bytes...  PASS
scanimage: stepped read, 511 bytes...   PASS
scanimage: stepped read, 255 bytes...   PASS
scanimage: stepped read, 127 bytes...   PASS
scanimage: stepped read, 63 bytes...    PASS
scanimage: stepped read, 31 bytes...    PASS
scanimage: stepped read, 15 bytes...    PASS
scanimage: stepped read, 7 bytes...     PASS
scanimage: stepped read, 3 bytes...     PASS

So I tried to scan an A4 page from the command line:

$ scanimage -d pixma:04A9173E_1653C4 -l 0 -t 0 -x 215 -y 297 --resolution 150 --mode Color | convert - scanned-page.png

That worked, so I launched XSane, one of the GUI scanner applications:

$ xsane

That also worked.

Sometimes either scanimage or a GUI scanner application (XSane, gscan2pdf, Simple Scan or whatever) hangs, but, more often than not, scanning now works via the USB connection. However, if either scanimage or a GUI scanner application hangs, I kill them, run them again and then they usually work.

Importantly, printing still works, even though I have changed the USB device group from ‘lp‘ to ‘scanner‘.

So I have satisfied my curiosity and managed to get the MP560 to scan when connected to my laptop via USB, even though it already worked fine when using a network connection instead.

A note on the version of SANE

For information, I currently have Version 1.0.25_pre20150725 (daily snapshot from 25 July 2015) of the package sane-backends installed:

$ eix -I sane-backends
[I] media-gfx/sane-backends
     Available versions:  1.0.24-r5 (~)1.0.25_pre20150628 (~)1.0.25_pre20150725[1] {avahi doc gphoto2 ipv6 snmp systemd threads usb v4l xinetd ABI_MIPS="n32 n64 o32" ABI_PPC="32 64" ABI_S390="32 64" ABI_X86="32 64 x32" SANE_BACKENDS="+abaton +agfafocus +apple +artec +artec_eplus48u +as6e +avision +bh +canon +canon630u +canon_dr -canon_pp +cardscan +coolscan +coolscan2 +coolscan3 +dc210 +dc240 +dc25 +dell1600n_net +dmc +epjitsu +epson +epson2 +fujitsu +genesys +gt68xx +hp +hp3500 +hp3900 +hp4200 +hp5400 +hp5590 +hpljm1005 -hpsj5s +hs2p +ibm +kodak +kodakaio +kvs1025 +kvs20xx kvs40xx +leo +lexmark +ma1509 +magicolor +matsushita +microtek +microtek2 +mustek -mustek_pp +mustek_usb mustek_usb2 +nec +net +niash +p5 +pie +pixma +plustek +plustek_pp -pnm +qcam +ricoh +rts8891 +s9036 +sceptre +sharp +sm3600 +sm3840 +snapscan +sp15c +st400 +stv680 +tamarack +teco1 +teco2 +teco3 +test +u12 +umax +umax1220u +umax_pp +xerox_mfp"}
     Installed versions:  1.0.25_pre20150725[1](01:39:24 25/07/15)(avahi gphoto2 ipv6 usb v4l -doc -snmp -systemd -threads -xinetd ABI_MIPS="-n32 -n64 -o32" ABI_PPC="-32 -64" ABI_S390="-32 -64" ABI_X86="32 64 -x32" SANE_BACKENDS="abaton agfafocus apple artec artec_eplus48u as6e avision bh canon canon630u canon_dr cardscan coolscan coolscan2 coolscan3 dc210 dc240 dc25 dell1600n_net dmc epjitsu epson epson2 fujitsu genesys gt68xx hp hp3500 hp3900 hp4200 hp5400 hp5590 hpljm1005 hs2p ibm kodak kodakaio kvs1025 kvs20xx leo lexmark ma1509 magicolor matsushita microtek microtek2 mustek mustek_usb nec net niash p5 pie pixma plustek plustek_pp qcam ricoh rts8891 s9036 sceptre sharp sm3600 sm3840 snapscan sp15c st400 stv680 tamarack teco1 teco2 teco3 test u12 umax umax1220u umax_pp xerox_mfp -canon_pp -hpsj5s -kvs40xx -mustek_pp -mustek_usb2 -pnm")
     Homepage:            http://www.sane-project.org/
     Description:         Scanner Access Now Easy - Backends

[1] "local_overlay" /usr/local/portage

However, the same symptoms occurred with versions 1.0.24-r5, 1.0.25_pre20150628 and 1.0.25_pre20150725 of the sane-backends package, so I believe the problem was not version-specific.

A note about scanning in Linux
An early developer’s Web site for the SANE pixma backend has the following warning:

If you grant a group a full permission to access the scanner (by using udev, hotplug, resmgr etc.), every members in the group will have full access rights not only for the scanner part but also for the other parts of the device i.e. printer, memory-card reader and fax. These users can bypass your system’s security policy and do everything with the device intentionally and unintentionally.

It is all very well to say that, but it is the only way I could get the backend to work reliably (almost). And, judging by the number of people who posted on the Web that they had to do the same with other Linux distributions, other manufacturers and models of MFPs, this is a common requirement in order to get Linux to work with MFP scanners. It’s not impressive when people have to resort to this to get something to work.

Note that the success of the approach described in this post is dependent on the contents and order of all the UDEV rules files. Just because the rules files I have posted above work in my case does not guarantee they will work in your case too. It depends what rules files your installation already has, what are their precise contents and in what order they are. In my opinion this is not a good concept.

I stand by my comments in the Conclusion of my first post regarding this problem. To have to jump through so many hoops to be able to scan using Linux on a computer connected to a MFP via USB is ridiculous in my opinion. The fact that it works reliably via a network connection does not alter that. I have been ‘scratching an itch’ as I enjoy tinkering, but I feel sorry for users who just need something that works without having to mess around for hours or days.

Background

  1. The problem of scanning using USB multi-function printers in Linux
  2. The problem of scanning using USB multi-function printers in Linux (continued)

How to group the entries in the right-click menu of a KDE file manager

This is easier to explain by giving an example. I will use PeaZip as my example, but the principle applies whatever the menu entries.

Immediately after installing PeaZip Portable on my main laptop running Gentoo Linux by using the steps in one of my earlier posts, the resulting right-click menu in KDE Dolphin looks like the screenshot below. Notice that the PeaZip entries in the Actions sub-menu are not listed contiguously.

Actions sub-menu of right-click menu in KDE

But in KDE it is relatively easy to group menu entries tidily in a sub-menu, as shown in the screenshot below.

Sub-menu of Actions sub-menu for right-click menu in KDE

The peazip*.desktop files for the five PeaZip actions shown in the above screenshots are located in the directory ~/.kde4/share/kde4/services/ServiceMenus/ and each file includes the line ‘X-KDE-Submenu='.

All I had to do was edit each of the five peazip*.desktop files and change that line in each file to ‘X-KDE-Submenu=PeaZip‘.

That’s it!

Follow

Get every new post delivered to your Inbox.

Join 66 other followers