Skip to content

Commit

Permalink
fixes to sample code, addition of advanced code
Browse files Browse the repository at this point in the history
Fixed the sample code so it will hit enter after voting, and switched the twitch and discord buttons to match the stickers.

Added advanced code.  TBD if we want to use it on shipping firmware.  Updated readme to reference it.
  • Loading branch information
Dan committed Apr 11, 2021
1 parent 2fb3c04 commit 8f3eadb
Show file tree
Hide file tree
Showing 6 changed files with 962 additions and 8 deletions.
184 changes: 184 additions & 0 deletions README-adv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Hacker HotKey Advanced Firmware
```
/**********************************************************
* _______ _______ _______ _______ _______ _______ *
* | +---+ | +---+ | +---+ | +---+ | +---+ | +---+ | *
* | | H | | | A | | | C | | | K | | | E | | | R | | *
* | +---+ | +---+ | +---+ | +---+ | +---+ | +---+ | *
* |/_____\|/_____\|/_____\|/_____\|/_____\|/_____\| *
* _______ _______ _______ _______ _______ _______ *
* | +---+ | +---+ | +---+ | +---+ | +---+ | +---+ | *
* | | H | | | O | | | T | | | K | | | E | | | Y | | *
* | +---+ | +---+ | +---+ | +---+ | +---+ | +---+ | *
* |/_____\|/_____\|/_____\|/_____\|/_____\|/_____\| *
* *
**********************************************************/
```
This guide is intended to help you set up hotkeys using the Hacker Hotkey Advanced Firmware
Details are also included in the hackerhotkey-adv.ino file
You will need to download all three files (hackerhotkey-adv.ino, FingerprintUSBHost.h, and FingerprintUSBHost.cpp) and include them in a hackerhotkey-adv folder to successfully compile. Alternatively the FingerprintUSBHost Library can be downloaded and installed as a library from https://github.com/keyboardio/FingerprintUSBHost

## Host OS Detection

Hacker Hotkey attempts to determine the Host OS by using the FingerPrintUSBHost Library.
If you want to force Hacker Hotkey to act as if it's connected to a specific OS, set it in this ection
Valid options are "Windows", "MacOS", "Linux", "Other".
```c
Example: String OS = "Linux";
```
Otherwise, for auto-detection leave it blank.

You can also dynamically set the HostOS at boot time by holding down one of the top 4 keys when the device powers on.
[1] = Windows, [2] = MacOS, [3] = Linux, [4] = Other

## Hotkey Setup
Use this section to define your hotkeys. You will want to remove the existing hotkeys that are in the code and replace them with your own.
Use the Hotkey Formatting Guide below as a refernece

# Hotkey Formatting Guide
Each Hotkey is defined as a String Array. There are a few primary parts of this array:
```c
String key1[] = {"[mods go between brackets]text comes after","additional actions come next"};
^ Key Num ^ Modifier Keys ^ Hotkey Text ^ up to 9 actions can be performed
```
## Simple Examples
```c
String key1[] = {"You pressed the first top row key!"}; //types the line of text shown
String key2[] = {"You pressed the second top row key!"};
String key3[] = {"You pressed the third top row key!\xB0"}; //types the line of text shown and then Enter
String key4[] = {"You pressed the fourth top key!\xB0"};
String key5[] = {"[^]z"}; // This presses Control-z (undo on windows)
String key6[] = {"[^]c"}; // This presses Control-c (copy on windows)
String key7[] = {"[^+]v"}; // This presses Control-Shift-v (paste without formatting in some apps)
String key8[] = {"[^]c","[1000]","[^]v"}; // This copies, waits for one second, and then pastes.
```
## Modifier Keys
Modifier keys will remain pressed until all other keys are pressed and released.
You enable them by placing them within square brackets at the beginning of your string
Modifier Keys are not required, if left off your text will be written normally.
Spaces are allowed between Modifier Keys for clarity.

```c
Example: "[^!]HACK" would type [Control Key]+[Alt Key]+HACK - release
```

Shortcuts have been made for these Modifier Keys to make writing hotkeys simpler:

```
# = LEFT_GUI = Left Windows Key / GUI Key (Linux) / Option Key (Mac)
^ = LEFT_CTRL = Left Control Key
! = LEFT_ALT = Left Alt Key / Command Key (Mac)
+ = LEFT_SHIFT = Left Shift Key
```

Please note: If you use uppercase letters/symbols the hotkey will push shift also, so
[^]c and [^]C act differently. The first acts as Control+c and the second acts as Control+Shift+c

Additionally, all modifier keys supported by Arduino can be used when added as such:

```sh
LEFT_CTRL BACKSPACE F1_ <-- note the underscore
LEFT_SHIFT TAB F2
LEFT_ALT RETURN F3
LEFT_GUI ESC F4
RIGHT_CTRL INSERT F5
RIGHT_SHIFT DELETE F6
RIGHT_ALT PAGE_UP F7
RIGHT_GUI PAGE_DOWN F8
UP_ARROW HOME F9
DOWN_ARROW END F10
LEFT_ARROW CAPS_LOCK F11
RIGHT_ARROW F12

Example: "[RIGHT_SHIFT F12]" would press Shift+F12 and no additional text.
```

## Delay

You can enter a delay in the Modifier Keys brackets in order to delay prior to typing text.
The delay may be combined with Modifier Keys, but will be executed after any modifier keys are pressed.
```c
Example: "[300]THE PLANET" would delay for 300ms and then type "THE PLANET".
```


## Hotkey Text

Hotkey Text is any text added after the Modifier Keys brackets. This text is typed as written, with the
exception of the Special Hotkey Text section below.

## Special Hotkey Text (escape codes)

These keys work outside of the modifier field. Below is a chart with hex escape sequences
for inserting them into your hotkey. Other characters may work also but are untested.
See: https://en.m.wikipedia.org/wiki/Escape_sequences_in_C
```c
Example "hi\xB3mom" would type "hi[tab]mom" or, "\xC2" would press the F1 button.
```

```
Key Escape value Key Escape value
------------------------- -------------------------
LEFT_CTRL \x80 PAGE_UP \xD3
LEFT_SHIFT \x81 PAGE_DOWN \xD6
LEFT_ALT \x82 HOME \xD2
LEFT_GUI \x83 END \xD5
RIGHT_CTRL \x84 CAPS_LOCK \xC1
RIGHT_SHIFT \x85 F1 \xC2
RIGHT_ALT \x86 F2 \xC3
RIGHT_GUI \x87 F3 \xC4
UP_ARROW \xDA F4 \xC5
DOWN_ARROW \xD9 F5 \xC6
LEFT_ARROW \xD8 F6 \xC7
RIGHT_ARROW \xD7 F7 \xC8
BACKSPACE \xB2 \b F8 \xC9
TAB \xB3 \t F9 \xCA
RETURN \xB0 \n F10 \xCB
ESC \xB1 F11 \xCC
INSERT \xD1 F12 \xCD
DELETE \xD4
```

## Functions
Functions may be used within your hotkeys, and this can provide additonal capabilities. Currently functions are
called when the hotkey is defined, not at each button press. A function must return a String value that can be
inserted into the hotkey. The string may contain Modifier Keys and Hotkey Text.

One function is provided in this code: osCondition()

The Hacker Hotkey attempts to identify the host OS it is connected to when plugged in. osCondition alows you to
return different text based on which OS it is connected to. This is not foolproof, the code might mis-identify
your OS, so use with caution. The Hack Hotkey also will most likely not be able to identify a host within a VM.
The code also does not properly identify mobile OS', and may identify them as Mac, Linux or unsure.
```c
Usage: osCondition("Windows Value","MacOS Value","Linux Value","Unsure");
```
Always include each argument even if it is a blank string ("");

## Additional Actions
You may have noticed that some of the default hotkeys are very long, that's because each hotkey supports
up to nine actions per key. Each of these actions support all the modifiers, hotkey text and functions
outlined above. You simply add them to the array when defining it. This allows you to add delays
between actions, differnet modifier keys for different actions, and so on.
```c
Example: {"action one","action two","[+]action three with a modifier"}
```
## Memory Considerations
The ATMega32u4 has 32KB of program memory, and 2560B of SRAM. This makes the Hacker Hotkey ideal
for a number of small hotkey actions, but it can be a challege when attemping to create hotkeys
that has a large number of actions, or use long strings of text.
One way to combat this is to keep long strings of text out of SRAM until absolutely needed. When
defining your hotkeys, you can wrap the string in the F() macro. This stores your string in
program memory until needed.
```c
Example: String key1[] = {F("This string is stored in the 2560B of SRAM")}; //not wrapped with F()
vs. String key1[] = {F("This saves some SRAM in favor of Program Memory")}; //wrapped with F()
```
What this will not allow is using extremely large strings of text, such as the first page of the
Digital Millenium Copyright Act in a macro. It will still overwhelm the SRAM when processed and
your hotkey will fail quietly, or do weird and funky stuff.

If you can rewrite this mess to be more efficient, please submit a pull request.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,16 @@ This repos contains example software for the [Kernelcon](https://kernelcon.org/)
PID: 0x8036
SN: Upload any sketch to obtain it
```
5. upload code
6. choose your code
* [hacker hotkey sample](hackerHotKey/hackerHotKey.ino)
* A simple firmware example that is a good starting point for developing your own code
* [hacker hotkey advanced](hackerhotkey-adv/hackerhotkey-adv.ino)
* More advanced firmware if you just want to create powerful hotkeys without coding
* Refer to the [Hacker Hotkey Advanced guide](README-adv.md) for configuring hotkeys
7. upload code
* sketch -> upload
* Arduino IDE will compile and upload firmware to the Hacker Hotkey, which you can use immediately after upload (no unplugging, reseting, etc required)




14 changes: 7 additions & 7 deletions hackerHotKey/hackerHotKey.ino
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,31 @@ void loop() {
delay(200);
}
else if (digitalRead(BTN2) == LOW) {
Keyboard.println("https://discord.kernelcon.org");
Keyboard.println("https://twitch.kernelcon.org");
delay(200);
}
else if (digitalRead(BTN3) == LOW) {
Keyboard.println("https://twitch.kernelcon.org");
Keyboard.println("https://discord.kernelcon.org");
delay(200);
}
else if (digitalRead(BTN4) == LOW) {
Keyboard.println("https://github.com/kernelcon");
Keyboard.println("https://github.com/kernelcon/hacker-hotkey");
delay(200);
}
else if (digitalRead(BTN5) == LOW) {
Keyboard.println("!vote 4");
Keyboard.println("!vote 4\n");
delay(200);
}
else if (digitalRead(BTN6) == LOW) {
Keyboard.println("!vote 3");
Keyboard.println("!vote 3\n");
delay(200);
}
else if (digitalRead(BTN7) == LOW) {
Keyboard.println("!vote 2");
Keyboard.println("!vote 2\n");
delay(200);
}
else if (digitalRead(BTN8) == LOW) {
Keyboard.println("!vote 1");
Keyboard.println("!vote 1\n");
delay(200);
}
}
102 changes: 102 additions & 0 deletions hackerhotkey-adv/FingerprintUSBHost.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* FingerprintUSBHost - USB Host Fingerprinter library
* Copyright (c) 2016 Jesse Vincent
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "FingerprintUSBHost.h"

#if defined(USBCON)

FingerprintUSBHost_ FingerprintUSBHost;

int FingerprintUSBHost_::getInterface(uint8_t* interfaceCount) {
return 0;
}

int FingerprintUSBHost_::getDescriptor(USBSetup& setup) {
#ifdef DEBUG
usbSetups[usbSetupCount++] = setup;
#endif

if (setup.bmRequestType != REQUEST_DEVICETOHOST || setup.bRequest != GET_DESCRIPTOR || setup.wValueH != USB_STRING_DESCRIPTOR_TYPE) {

return 0;
}


if (setup.wLength == 0xff) {
guess.maybe_linux = 1;
guess.maybe_win = 1;
guess.not_mac = 1; // In testing, MacOS NEVER sets a descript request lenght of 255
} else {
guess.not_linux = 1; // In testing, Linux ALWAYS sets a descriptor request length of 255;
}

return 0;
}

GuessedHost::OSVariant FingerprintUSBHost_::guessHostOS(void) {

if (guess.not_mac && guess.not_linux && guess.maybe_win) {
return GuessedHost::WINDOWS;
} else if (guess.maybe_linux && !guess.not_linux) {
return GuessedHost::LINUX;
} else if (! guess.not_mac) {
return GuessedHost::MACOS;

} else {
return GuessedHost::UNSURE;
}
}

void FingerprintUSBHost_::guessHostOS(String &os) {
switch (guessHostOS()) {
case GuessedHost::WINDOWS:
os="Windows";
break;
case GuessedHost::LINUX:
os="Linux";
break;
case GuessedHost::MACOS:
os="MacOS";
break;
default:
os="unsure";
break;
}
}


bool FingerprintUSBHost_::setup(USBSetup& setup) {
return false;
}

FingerprintUSBHost_::FingerprintUSBHost_(void) : PluggableUSBModule(0, 0, epType) {
memset(&guess, 0, sizeof(guess));
PluggableUSB().plug(this);
}

int FingerprintUSBHost_::begin(void) {
return 0;
}



#endif /* if defined(USBCON) */
Loading

0 comments on commit 8f3eadb

Please sign in to comment.