"shutdown now" doesn't shut down the machine anymore

Here’s another patch for the keyboard firmware (independent of the one above, i.e. you can apply it on the stock keyboard firmware on its own).

This one watches F1 and F12, and if you press both for 10 seconds, it forces the computer off and will keep the OLED display off until both keys are released.

This is meant to work with my little shutdown systemd service and foam pad doohickey: the script shuts down the OS cleanly, then the kernel fails to turn off the power currently, as per above, but it’s okay because the keyboard does it itself eventually.

10 seconds is plently long enough for the OS to unmount stuff cleanly and halt.

It is primarily a workaround for the shutdown issue above. But it’s not that stupid actually: even if the kernel did power off the machine properly, in case it goes haywire for any reason, this patch turns the keyboard into a sort of “safety last resort shutoff” that works regardless of whether the system behaves properly.

Meaning you can slam the lid closed, stuff the computer in your laptop bag and be certain it won’t cook itself in the bag and empty its batteries no matter what.

Here’s the patch:

diff --git a/reform2-keyboard4-fw/src/main.c b/reform2-keyboard4-fw/src/main.c
index b640168..f8392f7 100644
--- a/reform2-keyboard4-fw/src/main.c
+++ b/reform2-keyboard4-fw/src/main.c
@@ -606,6 +606,9 @@ int active_menu_mode = 0;
 uint8_t last_menu_key = 0;
 uint32_t circle_long_press_start_ms = 0;
 
+uint32_t scuttle_countdown_start_ms = 0;
+uint32_t computer_scuttled = false;
+
 uint8_t* active_matrix = matrix;
 bool hyper_key = 0; // Am I holding HYPER?
 bool circle_key = 0; // Am I holding CIRCLE?
@@ -648,7 +651,9 @@ int is_repeatable(uint8_t keycode, int menu_repeat_count) {
 int process_keyboard(uint8_t* resulting_scancodes) {
   // how many keys are pressed this round
   uint8_t total_pressed = 0;
+  uint8_t total_scuttle_key_pressed = 0;
   uint8_t used_key_codes = 0;
+  uint32_t now_ms = board_millis();
 
   menu_repeat_count++;
   if (menu_repeat_count > MENU_REPEAT_RATE) menu_repeat_count = 0;
@@ -723,13 +728,17 @@ int process_keyboard(uint8_t* resulting_scancodes) {
       if (debounced_pressed) {
         total_pressed++;
 
+        // Track how many scuttle keys (F1 and F12) are pressed simultaneously
+        if (keycode == KEY_F1 || keycode == KEY_F12) {
+          total_scuttle_key_pressed++;
+        }
+
         // circle? open OLED menu
         if (keycode == KEY_CIRCLE) {
           if (!last_menu_key) {
             if (!active_menu_mode) {
               enter_menu_mode();
             }
-            uint32_t now_ms = board_millis();
             if (!now_ms) now_ms++;
 
             if (!circle_long_press_start_ms) {
@@ -789,14 +798,41 @@ int process_keyboard(uint8_t* resulting_scancodes) {
     }
   }
 
+  // Has the computer been scuttled yet?
+  if (computer_scuttled) {
+
+    // If all the scuttle keys are released, reset the scuttled flag
+    if (total_scuttle_key_pressed == 0) {
+      computer_scuttled = false;
+    }
+
+ // The computer hasn't been scuttled yet
+ } else {
+
+    // If all the scuttle keys haven't been depressed,reset the scuttle timer
+    if(total_scuttle_key_pressed < 2) {
+      scuttle_countdown_start_ms = now_ms;
+
+    // ...otherwise count down to scuttle the computer
+    } else {
+
+      // Press the scuttle keys (F1 and F12) for 10 seconds to turn the computer off
+      if ((now_ms > scuttle_countdown_start_ms && now_ms -  scuttle_countdown_start_ms > 10000) || (now_ms < scuttle_countdown_start_ms && 0xffffffff - scuttle_countdown_start_ms + now_ms + 1 > 10000)) {
+        execute_menu_function(KEY_0);
+        execute_menu_function(KEY_ESC);
+        exit_menu_mode();
+        computer_scuttled = true;
+      }
+    }
+  }
+
   // if no more keys are held down, allow a new menu command
   if (total_pressed<1) last_menu_key = 0;
 
-  // if device is off and user is pressing random keys,
-  // show a hint for turning on the device
+  // if device is off and user is pressing random keys, and the computer hasn't been scutled by the scuttle keys, show a hint for turning on the device
 #if KBD_MODE == KBD_MODE_LAPTOP
   if (!remote_get_power_state()) {
-    if (total_pressed>0 && !active_menu_mode && !circle_key && !last_menu_key) {
+    if (total_pressed>0 && !computer_scuttled && !active_menu_mode && !circle_key && !last_menu_key) {
       execute_menu_function(KEY_H);
     }
   }

So, my problem is solved in a roundabout kind of way :slight_smile:

1 Like