Password via G-code and MarlinUI (#18399)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
This commit is contained in:
		| @@ -1642,6 +1642,37 @@ | ||||
|  */ | ||||
| //#define PRINTCOUNTER | ||||
|  | ||||
| /** | ||||
|  * Password | ||||
|  * | ||||
|  * Set a numerical password for the printer which can be requested: | ||||
|  * | ||||
|  *  - When the printer boots up | ||||
|  *  - Upon opening the 'Print from Media' Menu | ||||
|  *  - When SD printing is completed or aborted | ||||
|  * | ||||
|  * The following G-codes can be used: | ||||
|  * | ||||
|  *  M510 - Lock Printer. Blocks all commands except M511. | ||||
|  *  M511 - Unlock Printer. | ||||
|  *  M512 - Set, Change and Remove Password. | ||||
|  * | ||||
|  * If you forget the password and get locked out you'll need to re-flash | ||||
|  * the firmware with the feature disabled, reset EEPROM, and (optionally) | ||||
|  * re-flash the firmware again with this feature enabled. | ||||
|  */ | ||||
| //#define PASSWORD_FEATURE | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #define PASSWORD_LENGTH 4                 // (#) Number of digits (1-9). 3 or 4 is recommended | ||||
|   #define PASSWORD_ON_STARTUP | ||||
|   #define PASSWORD_UNLOCK_GCODE             // Unlock with the M511 P<password> command. Disable to prevent brute-force attack. | ||||
|   #define PASSWORD_CHANGE_GCODE             // Change the password with M512 P<old> N<new>. | ||||
|   //#define PASSWORD_ON_SD_PRINT_MENU       // This does not prevent gcodes from running | ||||
|   //#define PASSWORD_AFTER_SD_PRINT_END | ||||
|   //#define PASSWORD_AFTER_SD_PRINT_ABORT | ||||
|   //#include "Configuration_Secure.h"       // External file with PASSWORD_DEFAULT_VALUE | ||||
| #endif | ||||
|  | ||||
| //============================================================================= | ||||
| //============================= LCD and SD support ============================ | ||||
| //============================================================================= | ||||
|   | ||||
| @@ -213,6 +213,10 @@ | ||||
|   #include "libs/L64XX/L64XX_Marlin.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #include "feature/password/password.h" | ||||
| #endif | ||||
|  | ||||
| PGMSTR(NUL_STR, ""); | ||||
| PGMSTR(M112_KILL_STR, "M112 Shutdown"); | ||||
| PGMSTR(G28_STR, "G28"); | ||||
| @@ -452,11 +456,15 @@ void startOrResumeJob() { | ||||
|     #ifdef EVENT_GCODE_SD_STOP | ||||
|       queue.inject_P(PSTR(EVENT_GCODE_SD_STOP)); | ||||
|     #endif | ||||
|  | ||||
|     TERN_(PASSWORD_AFTER_SD_PRINT_ABORT, password.lock_machine()); | ||||
|   } | ||||
|  | ||||
|   inline void finishSDPrinting() { | ||||
|     if (queue.enqueue_one_P(PSTR("M1001"))) | ||||
|     if (queue.enqueue_one_P(PSTR("M1001"))) { | ||||
|       marlin_state = MF_RUNNING; | ||||
|       TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| #endif // SDSUPPORT | ||||
| @@ -1205,6 +1213,10 @@ void setup() { | ||||
|     SETUP_RUN(tft_lvgl_init()); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(PASSWORD_ON_STARTUP) | ||||
|     SETUP_RUN(password.lock_machine());      // Will not proceed until correct password provided | ||||
|   #endif | ||||
|  | ||||
|   marlin_state = MF_RUNNING; | ||||
|  | ||||
|   SETUP_LOG("setup() completed."); | ||||
|   | ||||
| @@ -266,6 +266,13 @@ | ||||
| #define STR_DEBUG_COMMUNICATION             "COMMUNICATION" | ||||
| #define STR_DEBUG_LEVELING                  "LEVELING" | ||||
|  | ||||
| #define STR_PRINTER_LOCKED                  "Printer locked! (Unlock with M511 or LCD)" | ||||
| #define STR_WRONG_PASSWORD                  "Incorrect Password" | ||||
| #define STR_PASSWORD_TOO_LONG               "Password too long" | ||||
| #define STR_PASSWORD_REMOVED                "Password removed" | ||||
| #define STR_REMINDER_SAVE_SETTINGS          "Remember to save!" | ||||
| #define STR_PASSWORD_SET                    "Password is " | ||||
|  | ||||
| // LCD Menu Messages | ||||
|  | ||||
| #define LANGUAGE_DATA_INCL_(M) STRINGIFY_(fontdata/langdata_##M.h) | ||||
|   | ||||
| @@ -342,15 +342,22 @@ | ||||
| #endif | ||||
|  | ||||
| // Macros for adding | ||||
| #define INC_0 1 | ||||
| #define INC_1 2 | ||||
| #define INC_2 3 | ||||
| #define INC_3 4 | ||||
| #define INC_4 5 | ||||
| #define INC_5 6 | ||||
| #define INC_6 7 | ||||
| #define INC_7 8 | ||||
| #define INC_8 9 | ||||
| #define INC_0   1 | ||||
| #define INC_1   2 | ||||
| #define INC_2   3 | ||||
| #define INC_3   4 | ||||
| #define INC_4   5 | ||||
| #define INC_5   6 | ||||
| #define INC_6   7 | ||||
| #define INC_7   8 | ||||
| #define INC_8   9 | ||||
| #define INC_9  10 | ||||
| #define INC_10 11 | ||||
| #define INC_11 12 | ||||
| #define INC_12 13 | ||||
| #define INC_13 14 | ||||
| #define INC_14 15 | ||||
| #define INC_15 16 | ||||
| #define INCREMENT_(n) INC_##n | ||||
| #define INCREMENT(n) INCREMENT_(n) | ||||
|  | ||||
| @@ -367,16 +374,22 @@ | ||||
| #define ADD10(N) ADD5(ADD5(N)) | ||||
|  | ||||
| // Macros for subtracting | ||||
| #define DEC_0 0 | ||||
| #define DEC_1 0 | ||||
| #define DEC_2 1 | ||||
| #define DEC_3 2 | ||||
| #define DEC_4 3 | ||||
| #define DEC_5 4 | ||||
| #define DEC_6 5 | ||||
| #define DEC_7 6 | ||||
| #define DEC_8 7 | ||||
| #define DEC_9 8 | ||||
| #define DEC_0   0 | ||||
| #define DEC_1   0 | ||||
| #define DEC_2   1 | ||||
| #define DEC_3   2 | ||||
| #define DEC_4   3 | ||||
| #define DEC_5   4 | ||||
| #define DEC_6   5 | ||||
| #define DEC_7   6 | ||||
| #define DEC_8   7 | ||||
| #define DEC_9   8 | ||||
| #define DEC_10  9 | ||||
| #define DEC_11 10 | ||||
| #define DEC_12 11 | ||||
| #define DEC_13 12 | ||||
| #define DEC_14 13 | ||||
| #define DEC_15 14 | ||||
| #define DECREMENT_(n) DEC_##n | ||||
| #define DECREMENT(n) DECREMENT_(n) | ||||
|  | ||||
|   | ||||
							
								
								
									
										58
									
								
								Marlin/src/feature/password/password.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								Marlin/src/feature/password/password.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|  | ||||
| #include "password.h" | ||||
| #include "../../gcode/gcode.h" | ||||
| #include "../../core/serial.h" | ||||
|  | ||||
| Password password; | ||||
|  | ||||
| // public: | ||||
| bool     Password::is_set, Password::is_locked; | ||||
| uint32_t Password::value, Password::value_entry; | ||||
|  | ||||
| // | ||||
| // Authenticate user with password. | ||||
| // Called from Setup, after SD Prinitng Stops/Aborts, and M510 | ||||
| // | ||||
| void Password::lock_machine() { | ||||
|   is_locked = true; | ||||
|   TERN_(HAS_LCD_MENU, authenticate_user(ui.status_screen, screen_password_entry)); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Authentication check | ||||
| // | ||||
| void Password::authentication_check() { | ||||
|   if (value_entry == value) | ||||
|     is_locked = false; | ||||
|   else | ||||
|     SERIAL_ECHOLNPGM(STR_WRONG_PASSWORD); | ||||
|  | ||||
|   TERN_(HAS_LCD_MENU, authentication_done()); | ||||
| } | ||||
|  | ||||
| #endif // PASSWORD_FEATURE | ||||
							
								
								
									
										57
									
								
								Marlin/src/feature/password/password.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								Marlin/src/feature/password/password.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../../lcd/ultralcd.h" | ||||
|  | ||||
| class Password { | ||||
| public: | ||||
|   static bool is_set, is_locked; | ||||
|   static uint32_t value, value_entry; | ||||
|  | ||||
|   Password() { is_locked = false; } | ||||
|  | ||||
|   static void lock_machine(); | ||||
|  | ||||
|   #if HAS_LCD_MENU | ||||
|     static void access_menu_password(); | ||||
|     static void authentication_check(); | ||||
|     static void authentication_done(); | ||||
|     static void media_gatekeeper(); | ||||
|  | ||||
|     private: | ||||
|     static void authenticate_user(const screenFunc_t, const screenFunc_t); | ||||
|     static void menu_password(); | ||||
|     static void menu_password_entry(); | ||||
|     static void screen_password_entry(); | ||||
|     static void screen_set_password(); | ||||
|     static void start_over(); | ||||
|  | ||||
|     static void digit_entered(); | ||||
|     static void set_password_done(); | ||||
|     static void menu_password_report(); | ||||
|  | ||||
|     static void remove_password(); | ||||
|   #endif | ||||
| }; | ||||
|  | ||||
| extern Password password; | ||||
							
								
								
									
										83
									
								
								Marlin/src/gcode/feature/password/M510-M512.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								Marlin/src/gcode/feature/password/M510-M512.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "../../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|  | ||||
| #include "../../../feature/password/password.h" | ||||
| #include "../../../core/serial.h" | ||||
| #include "../../gcode.h" | ||||
|  | ||||
| // | ||||
| // M510: Lock Printer | ||||
| // | ||||
| void GcodeSuite::M510() { | ||||
|   password.lock_machine(); | ||||
| } | ||||
|  | ||||
| // | ||||
| // M511: Unlock Printer | ||||
| // | ||||
| #if ENABLED(PASSWORD_UNLOCK_GCODE) | ||||
|  | ||||
|   void GcodeSuite::M511() { | ||||
|     if (password.is_locked) { | ||||
|       password.value_entry = parser.ulongval('P'); | ||||
|       password.authentication_check(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| #endif // PASSWORD_UNLOCK_GCODE | ||||
|  | ||||
| // | ||||
| // M512: Set/Change/Remove Password | ||||
| // | ||||
| #if ENABLED(PASSWORD_CHANGE_GCODE) | ||||
|  | ||||
|   void GcodeSuite::M512() { | ||||
|     if (password.is_set && parser.ulongval('P') != password.value) { | ||||
|       SERIAL_ECHOLNPGM(STR_WRONG_PASSWORD); | ||||
|       return; | ||||
|      } | ||||
|  | ||||
|     if (parser.seenval('N')) { | ||||
|       password.value_entry = parser.ulongval('N'); | ||||
|  | ||||
|       if (password.value_entry < CAT(1e, PASSWORD_LENGTH)) { | ||||
|         password.is_set = true; | ||||
|         password.value = password.value_entry; | ||||
|         SERIAL_ECHOLNPAIR(STR_PASSWORD_SET, password.value); // TODO: Update password.string | ||||
|       } | ||||
|       else | ||||
|         SERIAL_ECHOLNPGM(STR_PASSWORD_TOO_LONG); | ||||
|     } | ||||
|     else { | ||||
|       password.is_set = false; | ||||
|       SERIAL_ECHOLNPGM(STR_PASSWORD_REMOVED); | ||||
|     } | ||||
|     SERIAL_ECHOLNPGM(STR_REMINDER_SAVE_SETTINGS); | ||||
|   } | ||||
|  | ||||
| #endif // PASSWORD_CHANGE_GCODE | ||||
|  | ||||
| #endif // PASSWORD_FEATURE | ||||
| @@ -57,6 +57,10 @@ GcodeSuite gcode; | ||||
|   #include "../feature/spindle_laser.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #include "../feature/password/password.h" | ||||
| #endif | ||||
|  | ||||
| #include "../MarlinCore.h" // for idle() | ||||
|  | ||||
| // Inactivity shutdown | ||||
| @@ -241,6 +245,17 @@ void GcodeSuite::dwell(millis_t time) { | ||||
| void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|   KEEPALIVE_STATE(IN_HANDLER); | ||||
|  | ||||
|  /** | ||||
|   * Block all Gcodes except M511 Unlock Printer, if printer is locked | ||||
|   * Will still block Gcodes if M511 is disabled, in which case the printer should be unlocked via LCD Menu | ||||
|   */ | ||||
|   #if ENABLED(PASSWORD_FEATURE) | ||||
|     if (password.is_locked && !(parser.command_letter == 'M' && parser.codenum == 511)) { | ||||
|       SERIAL_ECHO_MSG(STR_PRINTER_LOCKED); | ||||
|       return; | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   // Handle a known G, M, or T | ||||
|   switch (parser.command_letter) { | ||||
|     case 'G': switch (parser.codenum) { | ||||
| @@ -736,6 +751,16 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { | ||||
|         case 504: M504(); break;                                  // M504: Validate EEPROM contents | ||||
|       #endif | ||||
|  | ||||
|       #if ENABLED(PASSWORD_FEATURE) | ||||
|         case 510: M510(); break;                                  // M510: Lock Printer | ||||
|         #if ENABLED(PASSWORD_UNLOCK_GCODE) | ||||
|           case 511: M511(); break;                                // M511: Unlock Printer | ||||
|         #endif | ||||
|         #if ENABLED(PASSWORD_CHANGE_GCODE) | ||||
|           case 512: M512(); break; | ||||
|         #endif                                                    // M512: Set/Change/Remove Password | ||||
|       #endif | ||||
|  | ||||
|       #if ENABLED(SDSUPPORT) | ||||
|         case 524: M524(); break;                                  // M524: Abort the current SD print job | ||||
|       #endif | ||||
|   | ||||
| @@ -225,6 +225,9 @@ | ||||
|  * M502 - Revert to the default "factory settings". ** Does not write them to EEPROM! ** | ||||
|  * M503 - Print the current settings (in memory): "M503 S<verbose>". S0 specifies compact output. | ||||
|  * M504 - Validate EEPROM contents. (Requires EEPROM_SETTINGS) | ||||
|  * M510 - Lock Printer | ||||
|  * M511 - Unlock Printer | ||||
|  * M512 - Set/Change/Remove Password | ||||
|  * M524 - Abort the current SD print job started with M24. (Requires SDSUPPORT) | ||||
|  * M540 - Enable/disable SD card abort on endstop hit: "M540 S<state>". (Requires SD_ABORT_ON_ENDSTOP_HIT) | ||||
|  * M569 - Enable stealthChop on an axis. (Requires at least one _DRIVER_TYPE to be TMC2130/2160/2208/2209/5130/5160) | ||||
| @@ -760,6 +763,16 @@ private: | ||||
|   #endif | ||||
|   TERN_(EEPROM_SETTINGS, static void M504()); | ||||
|  | ||||
|   #if ENABLED(PASSWORD_FEATURE) | ||||
|     static void M510(); | ||||
|     #if ENABLED(PASSWORD_UNLOCK_GCODE) | ||||
|       static void M511(); | ||||
|     #endif | ||||
|     #if ENABLED(PASSWORD_CHANGE_GCODE) | ||||
|       static void M512(); | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   TERN_(SDSUPPORT, static void M524()); | ||||
|  | ||||
|   TERN_(SD_ABORT_ON_ENDSTOP_HIT, static void M540()); | ||||
|   | ||||
| @@ -3083,5 +3083,16 @@ static_assert(   _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2) | ||||
|   #error "ESP3D_WIFISUPPORT or WIFISUPPORT requires an ESP32 controller." | ||||
| #endif | ||||
|  | ||||
| /** | ||||
|  * Sanity Check for Password Feature | ||||
|  */ | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #if NONE(HAS_LCD_MENU, PASSWORD_UNLOCK_GCODE, PASSWORD_CHANGE_GCODE) | ||||
|     #error "Without PASSWORD_UNLOCK_GCODE, PASSWORD_CHANGE_GCODE, or a supported LCD there's no way to unlock the printer or set a password." | ||||
|   #elif DISABLED(EEPROM_SETTINGS) | ||||
|     #warning "PASSWORD_FEATURE settings will be lost on power-off without EEPROM_SETTINGS." | ||||
|   #endif | ||||
| #endif | ||||
|  | ||||
| // Misc. Cleanup | ||||
| #undef _TEST_PWM | ||||
|   | ||||
| @@ -588,6 +588,17 @@ namespace Language_en { | ||||
|   PROGMEM Language_Str MSG_BAD_PAGE                        = _UxGT("Bad page index"); | ||||
|   PROGMEM Language_Str MSG_BAD_PAGE_SPEED                  = _UxGT("Bad page speed"); | ||||
|  | ||||
|   PROGMEM Language_Str MSG_EDIT_PASSWORD                   = _UxGT("Edit Password"); | ||||
|   PROGMEM Language_Str MSG_LOGIN_REQUIRED                  = _UxGT("Login Required"); | ||||
|   PROGMEM Language_Str MSG_PASSWORD_SETTINGS               = _UxGT("Password Settings"); | ||||
|   PROGMEM Language_Str MSG_ENTER_DIGIT                     = _UxGT("Enter Digit"); | ||||
|   PROGMEM Language_Str MSG_CHANGE_PASSWORD                 = _UxGT("Set/Edit Password"); | ||||
|   PROGMEM Language_Str MSG_REMOVE_PASSWORD                 = _UxGT("Remove Password"); | ||||
|   PROGMEM Language_Str MSG_PASSWORD_SET                    = _UxGT("Password is "); | ||||
|   PROGMEM Language_Str MSG_START_OVER                      = _UxGT("Start Over"); | ||||
|   PROGMEM Language_Str MSG_REMINDER_SAVE_SETTINGS          = _UxGT("Remember to Save!"); | ||||
|   PROGMEM Language_Str MSG_PASSWORD_REMOVED                = _UxGT("Password Removed"); | ||||
|  | ||||
|   // | ||||
|   // Filament Change screens show up to 3 lines on a 4-line display | ||||
|   //                        ...or up to 2 lines on a 3-line display | ||||
|   | ||||
| @@ -51,6 +51,10 @@ | ||||
|   #include "../../module/settings.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #include "../../feature/password/password.h" | ||||
| #endif | ||||
|  | ||||
| void menu_tmc(); | ||||
| void menu_backlash(); | ||||
|  | ||||
| @@ -603,6 +607,10 @@ void menu_advanced_settings() { | ||||
|     }); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(PASSWORD_FEATURE) | ||||
|     SUBMENU(MSG_PASSWORD_SETTINGS, password.access_menu_password); | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS) | ||||
|     CONFIRM_ITEM(MSG_INIT_EEPROM, | ||||
|       MSG_BUTTON_INIT, MSG_BUTTON_CANCEL, | ||||
|   | ||||
| @@ -50,6 +50,10 @@ | ||||
|   #include "../../lcd/menu/menu_mmu2.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #include "../../feature/password/password.h" | ||||
| #endif | ||||
|  | ||||
| void menu_tune(); | ||||
| void menu_cancelobject(); | ||||
| void menu_motion(); | ||||
| @@ -133,7 +137,7 @@ void menu_main() { | ||||
|  | ||||
|       if (card_detected) { | ||||
|         if (!card_open) { | ||||
|           SUBMENU(MSG_MEDIA_MENU, menu_media); | ||||
|           SUBMENU(MSG_MEDIA_MENU, TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_media)); | ||||
|           MENU_ITEM(gcode, | ||||
|             #if PIN_EXISTS(SD_DETECT) | ||||
|               MSG_CHANGE_MEDIA, M21_STR | ||||
| @@ -240,7 +244,7 @@ void menu_main() { | ||||
|               MSG_RELEASE_MEDIA, PSTR("M22") | ||||
|             #endif | ||||
|           ); | ||||
|           SUBMENU(MSG_MEDIA_MENU, menu_media); | ||||
|           SUBMENU(MSG_MEDIA_MENU, TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_media)); | ||||
|         } | ||||
|       } | ||||
|       else { | ||||
|   | ||||
							
								
								
									
										184
									
								
								Marlin/src/lcd/menu/menu_password.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								Marlin/src/lcd/menu/menu_password.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| /** | ||||
|  * Marlin 3D Printer Firmware | ||||
|  * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] | ||||
|  * | ||||
|  * Based on Sprinter and grbl. | ||||
|  * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| // | ||||
| // Advanced Settings Menus | ||||
| // | ||||
|  | ||||
| #include "../../inc/MarlinConfigPre.h" | ||||
|  | ||||
| #if BOTH(HAS_LCD_MENU, PASSWORD_FEATURE) | ||||
|  | ||||
| #include "../../feature/password/password.h" | ||||
|  | ||||
| #include "menu.h" | ||||
| #include "menu_addon.h" | ||||
|  | ||||
| void menu_advanced_settings(); | ||||
|  | ||||
| screenFunc_t success_screen, fail_screen; | ||||
| bool authenticating; // = false | ||||
| char string[(PASSWORD_LENGTH) + 1]; | ||||
| static uint8_t digit_no; | ||||
|  | ||||
| // | ||||
| // Screen for both editing and setting the password | ||||
| // | ||||
| void Password::menu_password_entry() { | ||||
|   START_MENU(); | ||||
|  | ||||
|   // "Login" or "New Code" | ||||
|   STATIC_ITEM_P(authenticating ? GET_TEXT(MSG_LOGIN_REQUIRED) : GET_TEXT(MSG_EDIT_PASSWORD), SS_CENTER|SS_INVERT); | ||||
|  | ||||
|   STATIC_ITEM_P(PSTR(""), SS_CENTER|SS_INVERT, string); | ||||
|  | ||||
|   // Make the digit edit item look like a sub-menu | ||||
|   PGM_P const label = GET_TEXT(MSG_ENTER_DIGIT); | ||||
|   EDIT_ITEM_P(uint8, label, &editable.uint8, 0, 9, digit_entered); | ||||
|   MENU_ITEM_ADDON_START(utf8_strlen_P(label) + 1); | ||||
|     lcd_put_wchar(' '); | ||||
|     lcd_put_wchar('1' + digit_no); | ||||
|     SETCURSOR_X(LCD_WIDTH - 1); | ||||
|     lcd_put_wchar('>'); | ||||
|   MENU_ITEM_ADDON_END(); | ||||
|  | ||||
|   ACTION_ITEM(MSG_START_OVER, start_over); | ||||
|  | ||||
|   if (!authenticating) BACK_ITEM(MSG_BUTTON_CANCEL); | ||||
|  | ||||
|   END_MENU(); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Authentication check | ||||
| // | ||||
| void Password::authentication_done() { | ||||
|   ui.goto_screen(is_locked ? fail_screen : success_screen); | ||||
|   ui.completion_feedback(!is_locked); | ||||
| } | ||||
|  | ||||
| // A single digit was completed | ||||
| void Password::digit_entered() { | ||||
|   uint32_t multiplier = CAT(1e, PASSWORD_LENGTH); // 1e5 = 100000 | ||||
|   LOOP_LE_N(i, digit_no) multiplier /= 10; | ||||
|   value_entry += editable.uint8 * multiplier; | ||||
|   string[digit_no++] = '0' + editable.uint8; | ||||
|  | ||||
|   // Exit edit screen menu and go to another screen | ||||
|   ui.goto_previous_screen(); | ||||
|   ui.use_click(); | ||||
|   ui.goto_screen(menu_password_entry); | ||||
|  | ||||
|   // After password has been keyed in | ||||
|   if (digit_no == PASSWORD_LENGTH) { | ||||
|     if (authenticating) | ||||
|       authentication_check(); | ||||
|     else | ||||
|       set_password_done(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // | ||||
| // Set/Change Password | ||||
| // | ||||
| void Password::screen_password_entry() { | ||||
|   value_entry = 0; | ||||
|   digit_no = 0; | ||||
|   editable.uint8 = 0; | ||||
|   memset(string, '-', PASSWORD_LENGTH); | ||||
|   string[PASSWORD_LENGTH] = '\0'; | ||||
|   menu_password_entry(); | ||||
| } | ||||
|  | ||||
| void Password::screen_set_password() { | ||||
|   authenticating = false; | ||||
|   screen_password_entry(); | ||||
| } | ||||
|  | ||||
| void Password::authenticate_user(const screenFunc_t in_succ_scr, const screenFunc_t in_fail_scr) { | ||||
|   success_screen = in_succ_scr; | ||||
|   fail_screen = in_fail_scr; | ||||
|   if (is_set) { | ||||
|     authenticating = true; | ||||
|     ui.goto_screen(screen_password_entry); | ||||
|     ui.defer_status_screen(); | ||||
|     ui.update(); | ||||
|   } | ||||
|   else { | ||||
|     ui.goto_screen(in_succ_scr); | ||||
|     is_locked = false; | ||||
|   } | ||||
| } | ||||
|  | ||||
| void Password::access_menu_password() { | ||||
|   authenticate_user(menu_password, menu_advanced_settings); | ||||
| } | ||||
|  | ||||
| #if ENABLED(PASSWORD_ON_SD_PRINT_MENU) | ||||
|   void Password::media_gatekeeper() { | ||||
|     authenticate_user(menu_media, menu_main); | ||||
|   } | ||||
| #endif | ||||
|  | ||||
| void Password::start_over() { | ||||
|   ui.goto_previous_screen(); // Goto previous screen, if any | ||||
|   ui.goto_screen(screen_password_entry); | ||||
| } | ||||
|  | ||||
| void Password::menu_password_report() { | ||||
|   START_SCREEN(); | ||||
|   BACK_ITEM(MSG_PASSWORD_SETTINGS); | ||||
|   STATIC_ITEM(MSG_PASSWORD_SET, SS_LEFT, string); | ||||
|   STATIC_ITEM(MSG_REMINDER_SAVE_SETTINGS, SS_LEFT); | ||||
|   END_SCREEN(); | ||||
| } | ||||
|  | ||||
| void Password::set_password_done() { | ||||
|   is_set = true; | ||||
|   value = value_entry; | ||||
|   ui.completion_feedback(true); | ||||
|   ui.goto_screen(menu_password_report); | ||||
| } | ||||
|  | ||||
| void Password::remove_password() { | ||||
|   is_set = false; | ||||
|   string[0] = '0'; | ||||
|   string[1] = '\0'; | ||||
|   ui.completion_feedback(true); | ||||
|   ui.goto_screen(menu_password_report); | ||||
| } | ||||
|  | ||||
| // | ||||
| // Password Menu | ||||
| // | ||||
| void Password::menu_password() { | ||||
|   START_MENU(); | ||||
|   BACK_ITEM(MSG_ADVANCED_SETTINGS); | ||||
|   SUBMENU(MSG_CHANGE_PASSWORD, screen_set_password); | ||||
|   ACTION_ITEM(MSG_REMOVE_PASSWORD, []{ ui.save_previous_screen(); remove_password(); } ); | ||||
|   #if ENABLED(EEPROM_SETTINGS) | ||||
|     ACTION_ITEM(MSG_STORE_EEPROM, ui.store_settings); | ||||
|   #endif | ||||
|   END_MENU(); | ||||
| } | ||||
|  | ||||
| #endif // HAS_LCD_MENU && PASSWORD_FEATURE | ||||
| @@ -140,6 +140,10 @@ | ||||
|   #define HAS_CASE_LIGHT_BRIGHTNESS 1 | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(PASSWORD_FEATURE) | ||||
|   #include "../feature/password/password.h" | ||||
| #endif | ||||
|  | ||||
| #if ENABLED(TOUCH_SCREEN_CALIBRATION) | ||||
|   #include "../lcd/tft/touch.h" | ||||
| #endif | ||||
| @@ -152,7 +156,7 @@ typedef struct {  int16_t X, Y, Z, X2, Y2, Z2, Z3, Z4; | ||||
| typedef struct {     bool X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7; } tmc_stealth_enabled_t; | ||||
|  | ||||
| // Limit an index to an array size | ||||
| #define ALIM(I,ARR) _MIN(I, signed(COUNT(ARR) - 1)) | ||||
| #define ALIM(I,ARR) _MIN(I, (signed)COUNT(ARR) - 1) | ||||
|  | ||||
| // Defaults for reset / fill in on load | ||||
| static const uint32_t   _DMA[] PROGMEM = DEFAULT_MAX_ACCELERATION; | ||||
| @@ -407,6 +411,14 @@ typedef struct SettingsDataStruct { | ||||
|     uint8_t caselight_brightness;                        // M355 P | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
|   // PASSWORD_FEATURE | ||||
|   // | ||||
|   #if ENABLED(PASSWORD_FEATURE) | ||||
|     bool password_is_set; | ||||
|     uint32_t password_value; | ||||
|   #endif | ||||
|  | ||||
|   // | ||||
|   // TOUCH_SCREEN_CALIBRATION | ||||
|   // | ||||
| @@ -1345,6 +1357,14 @@ void MarlinSettings::postprocess() { | ||||
|       EEPROM_WRITE(caselight.brightness); | ||||
|     #endif | ||||
|  | ||||
|     // | ||||
|     // Password feature | ||||
|     // | ||||
|     #if ENABLED(PASSWORD_FEATURE) | ||||
|       EEPROM_WRITE(password.is_set); | ||||
|       EEPROM_WRITE(password.value); | ||||
|     #endif | ||||
|  | ||||
|     // | ||||
|     // TOUCH_SCREEN_CALIBRATION | ||||
|     // | ||||
| @@ -2185,6 +2205,15 @@ void MarlinSettings::postprocess() { | ||||
|         EEPROM_READ(caselight.brightness); | ||||
|       #endif | ||||
|  | ||||
|       // | ||||
|       // Password feature | ||||
|       // | ||||
|       #if ENABLED(PASSWORD_FEATURE) | ||||
|         _FIELD_TEST(password_is_set); | ||||
|         EEPROM_READ(password.is_set); | ||||
|         EEPROM_READ(password.value); | ||||
|       #endif | ||||
|  | ||||
|       // | ||||
|       // TOUCH_SCREEN_CALIBRATION | ||||
|       // | ||||
| @@ -2665,7 +2694,7 @@ void MarlinSettings::reset() { | ||||
|       #define PID_DEFAULT(N,E) DEFAULT_##N | ||||
|     #endif | ||||
|     HOTEND_LOOP() { | ||||
|       PID_PARAM(Kp, e) = float(PID_DEFAULT(Kp, ALIM(e, defKp))); | ||||
|       PID_PARAM(Kp, e) =      float(PID_DEFAULT(Kp, ALIM(e, defKp))); | ||||
|       PID_PARAM(Ki, e) = scalePID_i(PID_DEFAULT(Ki, ALIM(e, defKi))); | ||||
|       PID_PARAM(Kd, e) = scalePID_d(PID_DEFAULT(Kd, ALIM(e, defKd))); | ||||
|       TERN_(PID_EXTRUSION_SCALING, PID_PARAM(Kc, e) = float(PID_DEFAULT(Kc, ALIM(e, defKc)))); | ||||
| @@ -2783,6 +2812,15 @@ void MarlinSettings::reset() { | ||||
|     } | ||||
|   #endif | ||||
|  | ||||
|   #if ENABLED(PASSWORD_FEATURE) | ||||
|     #ifdef PASSWORD_DEFAULT_VALUE | ||||
|       password.is_set = true; | ||||
|       password.value = PASSWORD_DEFAULT_VALUE; | ||||
|     #else | ||||
|       password.is_set = false; | ||||
|     #endif | ||||
|   #endif | ||||
|  | ||||
|   postprocess(); | ||||
|  | ||||
|   DEBUG_ECHO_START(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user