From f35e0b9382c6df1f98a4c3ba34b10a8077432e56 Mon Sep 17 00:00:00 2001
From: Tanguy Pruvot <tpruvot@users.noreply.github.com>
Date: Thu, 5 Aug 2021 06:47:31 +0200
Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=B8=20Prevent=20M42=20unintended=20pin?=
 =?UTF-8?q?=20change=20to=20output=20(#22493)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Marlin/src/gcode/control/M42.cpp | 36 ++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp
index 6ef8455e0b5..908260ed25d 100644
--- a/Marlin/src/gcode/control/M42.cpp
+++ b/Marlin/src/gcode/control/M42.cpp
@@ -31,6 +31,13 @@
   #include "../../module/temperature.h"
 #endif
 
+#ifdef MAPLE_STM32F1
+  // these are enums on the F1...
+  #define INPUT_PULLDOWN INPUT_PULLDOWN
+  #define INPUT_ANALOG INPUT_ANALOG
+  #define OUTPUT_OPEN_DRAIN OUTPUT_OPEN_DRAIN
+#endif
+
 void protected_pin_err() {
   SERIAL_ERROR_MSG(STR_ERR_PROTECTED_PIN);
 }
@@ -55,13 +62,20 @@ void GcodeSuite::M42() {
 
   if (!parser.boolval('I') && pin_is_protected(pin)) return protected_pin_err();
 
+  bool avoidWrite = false;
   if (parser.seenval('M')) {
     switch (parser.value_byte()) {
-      case 0: pinMode(pin, INPUT); break;
+      case 0: pinMode(pin, INPUT); avoidWrite = true; break;
       case 1: pinMode(pin, OUTPUT); break;
-      case 2: pinMode(pin, INPUT_PULLUP); break;
+      case 2: pinMode(pin, INPUT_PULLUP); avoidWrite = true; break;
       #ifdef INPUT_PULLDOWN
-        case 3: pinMode(pin, INPUT_PULLDOWN); break;
+        case 3: pinMode(pin, INPUT_PULLDOWN); avoidWrite = true; break;
+      #endif
+      #ifdef INPUT_ANALOG
+        case 4: pinMode(pin, INPUT_ANALOG); avoidWrite = true; break;
+      #endif
+      #ifdef OUTPUT_OPEN_DRAIN
+        case 5: pinMode(pin, OUTPUT_OPEN_DRAIN); break;
       #endif
       default: SERIAL_ECHOLNPGM("Invalid Pin Mode"); return;
     }
@@ -99,8 +113,22 @@ void GcodeSuite::M42() {
     }
   #endif
 
-  pinMode(pin, OUTPUT);
+  if (avoidWrite) {
+    SERIAL_ECHOLNPGM("?Cannot write to INPUT");
+    return;
+  }
+
+  // An OUTPUT_OPEN_DRAIN should not be changed to normal OUTPUT (STM32)
+  // Use M42 Px M1/5 S0/1 to set the output type and then set value
+  #ifndef OUTPUT_OPEN_DRAIN
+    pinMode(pin, OUTPUT);
+  #endif
   extDigitalWrite(pin, pin_status);
+
+  #ifdef ARDUINO_ARCH_STM32
+    // A simple I/O will be set to 0 by analogWrite()
+    if (pin_status <= 1) return;
+  #endif
   analogWrite(pin, pin_status);
 }