I have a Panasonic Toughbook CF-33 as my backup/outdoor/camping laptop. It’s a rugged laptop with a 2K display and a detachable keyboard/touchpad base. It has a multitouch screen and pen input as well.
These are my notes for running Linux on it because I sometimes forget parts of the setup that are annoying to re-research if I need them again.
I want to run Linux on this thing with the following requirements:
The laptop should be usable completely without the keyboard/touchpad base. There are a few distinct phases of usage that each need to be configured.
The CF-33 can be configured to provide an on-screen keyboard in EFI. This is enough to operate GRUB and the EFI shell.
initrd
I use full disk encryption so I need an on-screen keyboard in the initrd
environment.
I use unl0kr
for that, and an entry in /etc/crypttab
to make it part of the initial ramdisk:
1$ doas apt install unl0kr
The entry in /etc/crypttab
looks like this.
It needs to be adjusted to match the device UUID and name, but the Debian setup process already configures that.
This is mostly about the keyscript
part:
sda3_crypt UUID=bc262d7a-3762-4b42-8641-b148bd944111 none luks,discard,x-initrd.attach,keyscript=/usr/share/initramfs-tools/scripts/unl0kr-keyscript
Configure unl0kr
in /etc/unl0kr.conf
.
The defaults are usually OK though.
After configuring it, update the initrd:
1$ doas update-initramfs -u
To get an on-screen keyboard on the frame buffer, I use buffyboard which I have installed to /usr/local/bin
.
This is the wrapper I use to start it:
1#!/bin/bash
2
3set -xu
4
5active=$(fgconsole)
6
7if [[ "$active" == "7" ]]; then
8 # Turn it off always if we're in X.
9 # TODO: Start onboard if necessary.
10 doas systemctl stop buffyboard.service
11else
12 isActive=$(systemctl is-active buffyboard.service)
13 if [[ "$isActive" == "active" ]]; then
14 doas systemctl stop buffyboard.service
15 else
16 doas systemctl start buffyboard.service
17 fi
18fi
The script stops buffyboard if it detects TTY 7 as the active TTY so that it doesn’t conflict with onboard
for my X11 setup.
The systemd service is buffyboard.service
from buffyboard’s repository.
To start buffyboard, I use triggerhappy with the following configuration in /etc/triggerhappy/triggers.d/keyboard.conf
:
KEY_PROG3 1 /usr/local/bin/osk.sh
My /etc/doas.conf
allows the user nobody
(which triggerhappy runs as) to start/stop the buffyboard systemd service like this:
1permit keepenv nopass nobody cmd systemctl args stop buffyboard.service
2permit keepenv nopass nobody cmd systemctl args start buffyboard.service
My X on-screen keyboard of choice is onboard
:
1$ doas apt install onboard
My /etc/lightdm/lightdm-gtk-greeter.conf
looks like this:
[greeter]
keyboard=onboard
I use xbindkeys
to always have working keyboard bindings, no matter which window manager is running.
My .xbindkeysrc
looks like this:
"lxterm"
mod4 + space
"pkill onboard; onboard"
XF86Launch3
"/bin/bash -c /home/gbe/bin/r.sh"
mod4 + XF86Eject
"polybar-msg action pulseaudio toggle"
XF86AudioMute
"polybar-msg action pulseaudio dec"
XF86AudioLowerVolume
"polybar-msg action pulseaudio inc"
XF86AudioRaiseVolume
"xscreensaver-command -lock"
mod4 + ctrl + q
I have patched the panasonic-laptop
kernel driver to map the keys labelled “A1” and “A2” on the tablet bezel to the key symbols LAUNCH3
and LAUNCH4
.
These are LAUNCHx
keys instead of MACROxy
because X11 apparently doesn’t register those macro keys.
I don’t know precisely where I have that information from (probably one of the evdev
headers), but it matches my observations.
I use QGIS as my GNSS client, and connect it to gpsd
with its “GPS” toolbar. Works quite nicely.
My polybar setup (~/.config/polybar/config.ini
) looks like this:
[colors]
background = #cccccc
foreground = #111111
primary = #4a799c
disabled = #707880
[bar/main]
height = 24pt
dpi = 144
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 3pt
border-size = 0pt
padding-left = 0
padding-right = 1
module-margin = 1
separator = |
separator-foreground = ${colors.disabled}
font-0 = Ubuntu
font-1 = Noto Color Emoji:scale=7
font-2 = Font Awesome 6 Free Solid
font-3 = Weather Icons:style=Regular
font-4 = DejaVu Sans
modules-right = backlight project pulseaudio battery1 battery2 date
cursor-click = pointer
cursor-scroll = ns-resize
enable-ipc = true
override-redirect = false
wm-restack = i3
[module/pulseaudio]
type = internal/pulseaudio
format-volume = <ramp-volume> <label-volume>
ramp-volume-0 =
ramp-volume-0-foreground = ${colors.primary}
ramp-volume-1 =
ramp-volume-1-foreground = ${colors.primary}
ramp-volume-2 =
ramp-volume-2-foreground = ${colors.primary}
label-volume = %percentage%%
label-muted = M
label-muted-foreground = ${colors.disabled}
click-right = pavucontrol
[module/backlight]
type = internal/backlight
ramp-4 = 🌕
ramp-3 = 🌔
ramp-2 = 🌓
ramp-1 = 🌒
ramp-0 = 🌑
format = <ramp>
[module/battery1]
type = internal/battery
battery = BAT1
label-charging = %percentage%%
label-discharging = %percentage%%
label-low = %percentage%%
format-charging = <animation-charging> <label-charging>
format-discharging = <ramp-capacity> <label-discharging>
format-low = <animation-low> <label-low>
ramp-capacity-0 =
ramp-capacity-0-foreground = ${colors.primary}
ramp-capacity-1 =
ramp-capacity-1-foreground = ${colors.primary}
ramp-capacity-2 =
ramp-capacity-2-foreground = ${colors.primary}
ramp-capacity-3 =
ramp-capacity-3-foreground = ${colors.primary}
ramp-capacity-4 =
ramp-capacity-4-foreground = ${colors.primary}
animation-charging-0 =
animation-charging-0-foreground = ${colors.primary}
animation-charging-1 =
animation-charging-1-foreground = ${colors.primary}
animation-charging-2 =
animation-charging-2-foreground = ${colors.primary}
animation-charging-3 =
animation-charging-3-foreground = ${colors.primary}
animation-charging-4 =
animation-charging-4-foreground = ${colors.primary}
animation-charging-framerate = 750
animation-low-0 = "|"
animation-low-0-foreground = ${colors.primary}
animation-low-1 = !
animation-low-1-foreground = ${colors.primary}
animation-low-framerate = 500
[module/battery2]
inherit = module/battery1
battery = BAT2
[module/project]
type = custom/script
exec = /home/gbe/bin/newproject.sh
click-left = /home/gbe/bin/newproject.sh clicked
[module/ddate]
type = custom/script
interval = 600
exec = ddate +"%{%A, %e %B%} %Y%N (%H)"
[module/date]
type = internal/date
interval = 1
date = %m-%d %H:%M
date-alt = %d%H%M%Z %b%y
label = %date%
label-foreground = ${colors.primary}
[settings]
screenchange-reload = true
pseudo-transparency = true