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 run my own fork of DWM that I am in the process of porting to Zig. It has a few patches in it that add XFT support and a system tray. They’re from DWM’s patch selection.
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.
There is also a patch to the HID multitouch driver that ignores events at the very right edge of the display because after some time of use, the multitouch controller for the display seems to generate a lot of spurious click events there. I don’t know if this is an issue with my particular touch screen though.
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