1+ // --------------------------------------------//
2+ // HID-Button-Micro V1.0 //
3+ // (c) Alexander Feuster 2024 //
4+ // http://www.github.com/feuster/HID-Button //
5+ // //
6+ // powered by coffee //
7+ // //
8+ // ( ( //
9+ // ) ) //
10+ // .______. //
11+ // | | //
12+ // | | //
13+ // |______| //
14+ // \______/ //
15+ // //
16+ // --------------------------------------------//
17+
18+ // defines
19+ #define enable_reboot // enabled reboot on maximum duration button press else credential pair 3 is typed
20+ #define enable_german_layout // define german keyboard layout, if disabled US keyboard layout will be used
21+
22+ // includes
23+ #include " Credentials.h" // header file with stored USER|PASSWORD credentials
24+ #include < Keyboard.h> // library for emulating a HID keyboard
25+ #include " Bounce2.h" // library for handling the button hardware bouncing
26+
27+ // / -----------------------------------------------------------------------------------------------------------------------
28+ // / do not change code behind this line if not needed !!!
29+ // / -----------------------------------------------------------------------------------------------------------------------
30+
31+ // / -----------------------------------------------------------------------------------------------------------------------
32+ // / hardware & software definitions
33+ // / -----------------------------------------------------------------------------------------------------------------------
34+ // input pin for pushbutton (other pin with according wiring change)
35+ const int buttonPin = A0;
36+
37+ // reset pin for hardware reset trigger (other pin with according wiring change)
38+ #ifdef enable_reboot
39+ const int resetPin = A1;
40+ #endif
41+
42+ // first run
43+ bool firstRun = true ;
44+
45+ // state of the builtin LED for blinking
46+ int previousLedState = HIGH;
47+
48+ // time to define a long button press in ms
49+ int longPressTimeSpan = 1000 ;
50+
51+ // time to define a maximum duration button press in ms (must be longer than longPressTimeSpan)
52+ #ifdef enable_reboot
53+ int maxPressTimeSpan = 5000 ; // used longer timespan for the reboot to prevent unwanted trigger
54+ #else
55+ int maxPressTimeSpan = 3000 ; // use shorter timespan for typing the credential pair 2
56+ #endif
57+
58+ // create a Bounce2::Button object
59+ Bounce2::Button button = Bounce2::Button();
60+
61+ // / -----------------------------------------------------------------------------------------------------------------------
62+ // / start the hardware initialization
63+ // / -----------------------------------------------------------------------------------------------------------------------
64+ void setup () {
65+ #ifdef enable_reboot
66+ // configure the reset pin as output with default HIGH
67+ digitalWrite (resetPin, HIGH);
68+ pinMode (resetPin, OUTPUT);
69+ #endif
70+
71+ // configure the pushbutton pin as input with internal pullup resistor
72+ pinMode (buttonPin, INPUT_PULLUP);
73+
74+ // configure the builtin LED pin as output since the Micro does not blink without
75+ digitalWrite (LED_BUILTIN, LOW);
76+ pinMode (LED_BUILTIN, OUTPUT);
77+
78+ // Bounce2::Button configuration
79+ button.attach (buttonPin, INPUT_PULLUP);
80+ button.interval (5 );
81+ button.setPressedState (LOW);
82+
83+ // initialize control over the keyboard:
84+ Keyboard.begin ();
85+ }
86+
87+ // / -----------------------------------------------------------------------------------------------------------------------
88+ // / program loop
89+ // / -----------------------------------------------------------------------------------------------------------------------
90+ void loop () {
91+ // wait some time on first run, to give hardware time to initialize and blink the builtin LED as start confirmation
92+ if (firstRun)
93+ {
94+ firstRun = false ;
95+ for (int i = 0 ; i < 20 ; i++)
96+ {
97+ blink (100 );
98+ }
99+ }
100+
101+ // read the pushbutton state once per loop
102+ button.update ();
103+
104+ // validate if button was pressed short
105+ if (button.released () && button.previousDuration () < longPressTimeSpan)
106+ {
107+ // type login credentials pair 1
108+ Type (USER1, PASSWORD1);
109+ }
110+ // validate if button was pressed long
111+ else if (button.released () && button.previousDuration () > longPressTimeSpan && button.previousDuration () < maxPressTimeSpan)
112+ {
113+ // type login credentials pair 2
114+ Type (USER2, PASSWORD2);
115+ }
116+ // validate if button was pressed over the maximal time within a small timespan window to prevent unwanted repeats
117+ else if (button.isPressed () && button.currentDuration () > maxPressTimeSpan && button.currentDuration () < maxPressTimeSpan + 25 )
118+ {
119+ #ifdef enable_reboot
120+ // blink as signalization for reboot
121+ for (int i = 0 ; i < 10 ; i++)
122+ {
123+ blink (100 );
124+ }
125+ digitalWrite (LED_BUILTIN, previousLedState);
126+
127+ // execute reboot
128+ reboot ();
129+ #else
130+ // type login credentials pair 3
131+ Type (USER3, PASSWORD3);
132+ #endif
133+ }
134+
135+ // keep alive
136+ delay (25 );
137+
138+ // /program loop ends here and will repeat now in a new cycle
139+ }
140+
141+ // / -----------------------------------------------------------------------------------------------------------------------
142+ // / set the keyboard layout
143+ // / -----------------------------------------------------------------------------------------------------------------------
144+ void KeyBoardBegin ()
145+ {
146+ #ifdef enable_german_layout
147+ Keyboard.begin (KeyboardLayout_de_DE);
148+ #else
149+ Keyboard.begin (KeyboardLayout_en_US);
150+ #endif
151+ }
152+
153+ // / -----------------------------------------------------------------------------------------------------------------------
154+ // / type the desired user credentials as USB HID keyboard
155+ // / -----------------------------------------------------------------------------------------------------------------------
156+ void Type (char User[], char Password[])
157+ {
158+ // turn the builtin LED on while login is typed
159+ digitalWrite (LED_BUILTIN, HIGH);
160+
161+ // type login credentials pair or only the password if user is left empty in the credentials
162+ if (User[0 ] != 0 )
163+ {
164+ TypeInSingleChars (User);
165+ sendKeyStroke (KEY_TAB); // switches from the user input field to the password input field (should work for 99% of login masks)
166+ }
167+ TypeInSingleChars (Password);
168+ sendKeyStroke (KEY_RETURN); // confirms login input
169+
170+ // clear potential write error
171+ if (Keyboard.getWriteError () != 0 )
172+ Keyboard.clearWriteError ();
173+
174+ // turn the builtin LED off after login has been typed
175+ digitalWrite (LED_BUILTIN, LOW);
176+ }
177+
178+ // / -----------------------------------------------------------------------------------------------------------------------
179+ // / print a longer text as single chars
180+ // / remark: this should prevent freezing when typing longer texts
181+ // / -----------------------------------------------------------------------------------------------------------------------
182+ void TypeInSingleChars (char Text[])
183+ {
184+ // split text array in single chars and type char
185+ KeyBoardBegin ();
186+ for (byte i = 0 ; Text[i] != 0 ; i++)
187+ {
188+ Keyboard.print (Text[i]);
189+ // delay should prevent freezing when typing longer texts
190+ delay (10 );
191+ }
192+ Keyboard.end ();
193+ }
194+
195+ // / -----------------------------------------------------------------------------------------------------------------------
196+ // / sendKeyStroke is used as wrapper to add a keep alive delay
197+ // / -----------------------------------------------------------------------------------------------------------------------
198+ void sendKeyStroke (uint8_t key)
199+ {
200+ // press single key and release
201+ KeyBoardBegin ();
202+ Keyboard.press (key);
203+ Keyboard.releaseAll ();
204+ delay (50 );
205+ Keyboard.end ();
206+ }
207+
208+ // / -----------------------------------------------------------------------------------------------------------------------
209+ // / blink builtin LED
210+ // / -----------------------------------------------------------------------------------------------------------------------
211+ void blink (long milli)
212+ {
213+ digitalWrite (LED_BUILTIN, previousLedState);
214+ previousLedState = !previousLedState;
215+ delay (milli);
216+ }
217+
218+ #ifdef enable_reboot
219+ // / -----------------------------------------------------------------------------------------------------------------------
220+ // / reboot via RESET pin low (needs wiring Arduino RESET pin to IO pin which is used as trigger)
221+ // / -----------------------------------------------------------------------------------------------------------------------
222+ void reboot ()
223+ {
224+ digitalWrite (resetPin, LOW);
225+ }
226+ #endif
0 commit comments