(ノートPCで)「べつにサスペンドできなくてもいいや」みたいなことを 書いたばかりだが、翻ってできちゃってわーいな話。
NetBSDユーザとしては、できないのがずっと当たり前だったので、 サスペンドとか別になくてもいいじゃんと思い続けること20年余。 ちょうど、Type-Cが長いこと使えなくても、MicroSDみたいな外部補助記憶が 使えなくても別になんとも思ってこなかったiPhoneユーザに近いか。
サスペンドできた。
sysctl -w hw.acpi.sleep.state=3
でよい。
「ThinkPadならできるよ」 と書いてあったので念の為試したらx280ではできちゃった。ポイントがいくつか。
外付けのUSBデバイスとかあるとカーネルにサスペンドを拒否される。 これは分かるのだが、RAIDframeも該当した。 NetBSDではzpoolデバイスに RAIDframe を指定して使っているので、今回も /dev/raid28d で zpoolを作って使っていたが、サスペンドできない!
NetBSDのZFSだとデバイス名がずれたときに自動認識してくれないので 少し不安だが、デバイス接続順を変えて試したところ zpool import -f プール名 と明示的に指定するとインポートできるようなのでRAIDframe経由せずに 再構築した。
manやWeb情報をみると /etc/apm のしたにスクリプトを作るといいよってのが まだ残っていて騙されてしまったが、もうapmdないものね。powerdですよ。
/etc/powerd/scripts/ を見ると、スクリプトが置いてあるので調整。
後者について、えっと、「スリープボタンてどこよ?」
ThinkPad X280のキーボードには刻印ないっす。探したら、 「ThinkPadをキーボードでスリープ状態にする」がみつかり、 [Fn]+[4$] で行けるとわかった。そこで sleep_button スクリプトを修正。
--- sleep_button.orig 2017-07-13 22:51:15.000000000 +0900
+++ sleep_button 2024-08-27 12:46:37.806733805 +0900
@@ -11,7 +11,24 @@
case "${2}" in
pressed)
if /sbin/sysctl -q hw.acpi.sleep.state; then
+ ncons=`wsconscfg -g`
+ wsconscfg -s 1
+ sleep 1
/sbin/sysctl -w hw.acpi.sleep.state=3
+ ###################
+ if=iwm0
+ PATH=/usr/local/bin/DT:$PATH
+ #ifconfig $if down up
+ #/etc/rc.d/wpa_supplicant restart
+ ### echo "$@" > /tmp/args.powerd
+ repeat=10
+ while [ $((--repeat)) -gt 0 ]; do
+ sleep 2
+ ifconfig $if | grep -q 'status: active' && break
+ done
+ wsconscfg -s $ncons
+ svc -t /service/*vpn*
+ ###################
elif /sbin/sysctl -q machdep.xen.suspend; then
/sbin/sysctl -w machdep.xen.suspend=1
else
もともとある hw.acpi.sleep.state=3 の前後に、 仮想コンソールの切り替えと復帰とWi-Fiが戻ったらVPNもつなぎ直すのを入れた。
これでばっちり。
おまけ。
OpenBSDではバッテリ情報を sysctl 変数から取る必要があったので いちいち面倒でこんな表示が出るスクリプトを作って使っていた。
battery
AC Offline: Battery remaining 66.0%
Discharging at 7.89(31.61/47.77) - 4h00m to go
NetBSDだと envstat(8) で情報が出るが、逆に情報量多すぎて見づらいし、 残り時間を知りたい。てことで、OpenBSDで使っていたbatteryスクリプトを NetBSDにも対応。コチラどうぞ。
#!/bin/sh
case `uname` in
OpenBSD)
getval() {
case $1 in
lastfull) fld=acpibat0.watthour0 ;;
remain) fld=acpibat0.watthour3 ;;
rate) fld=acpibat0.power0 ;;
power) fld=acpiac0.indicator0 ;;
esac
sysctl -n hw.sensors.$fld | cut -d' ' -f1
}
;;
NetBSD)
curstat=`envstat`
getval() {
case $1 in
lastfull) echo "$curstat"|awk '/last full cap:/{print $4}' ;;
remain) echo "$curstat"|awk '/charge:/{print $2}' ;;
rate) echo "$curstat"|awk '/rate:.*[0-9]/{print $3}' ;;
power) echo "$curstat"|awk '/connected:/{print $2}' ;;
esac
}
;;
esac
for v in remain lastfull rate power; do
eval $v=`getval $v`
done
# echo $remain $lastfull $rate $power
percent=`echo "100*$remain/$lastfull"|bc -l|cut -d. -f1`
case $rate in
0.0*|"") rate=0 ;;
esac
case $power in
Off|FALSE)
printf "AC Offline: Battery remaining %5.1f%%\n" $percent
if [ x"$rate" = x"0" ]; then
echo Unknown lifetime
else
life=`echo "$remain/$rate"|bc -l`
hour=${life%.*} dmin=${life#*.}
min=`echo "0.$dmin * 60" | bc -l | cut -d. -f1`
printf "Discharging at %.2f(%.2f/%.2f) - ${hour:-0}h%02dm to go\n" $rate $remain $lastfull $min
fi
;;
On|TRUE)
printf "AC ONline: Battery remaining %5.1f%%\n" $percent
if [ x"$rate" = x"0" ]; then
echo "Last full capacity: ${lastfull}Wh"
else
tf=`echo "$lastfull - $remain"|bc -l`
tofull=`echo "$tf/$rate"|bc -l`
hour=${tofull%.*} dmin=${tofull#*.}
min=`echo "0.$dmin * 60" | bc -l | cut -d. -f1`
printf "Rate $rate to $tf ($remain/$lastfull) - "
printf "${hour:-0}h%02dm to full\n" $min
fi
;;
esac
# hw.sensors.acpibat0.volt0=11.40 VDC (voltage)
# hw.sensors.acpibat0.volt1=11.75 VDC (current voltage)
# hw.sensors.acpibat0.power0=6.59 W (rate)
# hw.sensors.acpibat0.watthour0=46.74 Wh (last full capacity)
# hw.sensors.acpibat0.watthour1=2.34 Wh (warning capacity)
# hw.sensors.acpibat0.watthour2=0.20 Wh (low capacity)
# hw.sensors.acpibat0.watthour3=30.78 Wh (remaining capacity), OK
# hw.sensors.acpibat0.watthour4=48.10 Wh (design capacity)
# hw.sensors.acpibat0.raw0=1 (battery discharging), OK
# hw.sensors.acpibat0.raw1=24 (discharge cycles)
電源をつないだときの表示はこんな感じ。
battery
AC ONline: Battery remaining 63.0%
Rate 40.926 to 17.220 (30.550/47.770) - 0h25m to full