From 0159cc1ceeba25a78a4cc43b9bbe207e79433030 Mon Sep 17 00:00:00 2001 From: Justin Lin <61717681+justinlin099@users.noreply.github.com> Date: Sat, 10 Aug 2024 16:36:13 +0800 Subject: [PATCH 01/11] Update BadgeCommander --- sw/BadgeCommander/.test.swp | Bin 0 -> 12288 bytes sw/BadgeCommander/BadUSBTranslation.py | 635 +++++++++++++++++++++++++ sw/BadgeCommander/BadgeCommander.py | 26 +- sw/BadgeCommander/LICENSE | 21 + sw/BadgeCommander/STM32HID.py | 3 +- sw/BadgeCommander/ScanCode.py | 271 +++++++++++ sw/BadgeCommander/demo_windows.txt | 81 ++++ 7 files changed, 1034 insertions(+), 3 deletions(-) create mode 100644 sw/BadgeCommander/.test.swp create mode 100644 sw/BadgeCommander/LICENSE create mode 100644 sw/BadgeCommander/ScanCode.py create mode 100644 sw/BadgeCommander/demo_windows.txt diff --git a/sw/BadgeCommander/.test.swp b/sw/BadgeCommander/.test.swp new file mode 100644 index 0000000000000000000000000000000000000000..0aacb0ba3ac3ef65c0982e2c20a4c31e1a4ca0d8 GIT binary patch literal 12288 zcmeI2y>8S%5XU!&3JBjN#Re!Wr1)lcZQmXxAQ6HP0x5{rceeQumqg?u(Eu-iL`%UF zAbJ`K9)U-oqUH_YKfCMb5-A9!i6UmBwH3EIEn^ln+xhK0za05KbOu6d(P=sIf(%=AO^&M7!U(uKn#chF(3xSfEW-1N63E5CdZ1KQ%zy4AFJnwPZDox>nohk$KV%&pR{x>#ebXD}c}k{BZ}umdbNK_$`{6-%YVRmGkOtJ8?hObi%l z52*79Nes_>i7yF)v7W}T3mS^MidFAiNKU_(Ebb$B;3UQnjQLltUo-8G-!^_B4bA12 zDFKxj74OA_m3HMZ%uEjeDry|G;n_hcuCmoEG0HxU`SF3~Osop)i#i5_yo9+sr^G10 z2&4Ytpt1C>pTuxr5O0W!G^`%9P*(|@ylS9iMCPw%; h?W%$&ajl2dLBoIgVs*=P=TTl%po(?g#Mw4c)E|0nQbPa$ literal 0 HcmV?d00001 diff --git a/sw/BadgeCommander/BadUSBTranslation.py b/sw/BadgeCommander/BadUSBTranslation.py index e69de29b..ffab2cf5 100644 --- a/sw/BadgeCommander/BadUSBTranslation.py +++ b/sw/BadgeCommander/BadUSBTranslation.py @@ -0,0 +1,635 @@ +import ScanCode + +def scriptToHex(scriptPath): + hexData = [] + with open(scriptPath, 'r') as file: + # read a list of lines into data + data = file.readlines() + data = [x.strip() for x in data] + for line in data: + if line != "" and not line.startswith("REM"): + print(line) + hexData=hexData+lineToHex(line) + hexData.append(0xFD) + return hexData + + +def lineToHex(line): + if line.startswith("DELAY"): + return [0xFF, int(int(line.split(" ")[1])/10)] + elif line.startswith("STRING"): + return stringToHex(line.split(" ")[1]) + elif line.startswith("STRINGLN"): + return stringToHex(line.split(" ")[1])+[ScanCode.KEY_ENTER] + elif line.startswith("ALTCHAR"): + return [0xFE, ScanCode.KEY_MOD_LALT]+modCharToHex(line.split(" ")[1])+[0xFE, 0x00] + elif line.startswith("GUI") or line.startswith("WINDOWS"): + data=[0xFE, ScanCode.KEY_MOD_LMETA] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: #check other key + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + elif line.startswith("ALT"): + data=[0xFE, ScanCode.KEY_MOD_LALT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + elif line.startswith("CTRL"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + elif line.startswith("SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LSHIFT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + # combie the modifier keys + # CTRL-ALT CTRL+ALT + # CTRL-SHIFT CTRL+SHIFT + # ALT-SHIFT ALT+SHIFT + # ALT-GUI ALT+WIN + # GUI-SHIFT WIN+SHIFT + # GUI-CTRL WIN+CTRL + elif line.startswith("CTRL-ALT"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LALT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + elif line.startswith("CTRL-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LSHIFT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + elif line.startswith("ALT-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LSHIFT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + elif line.startswith("ALT-GUI"): + data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LMETA] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + elif line.startswith("GUI-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LSHIFT] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + + elif line.startswith("GUI-CTRL"): + data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LCTRL] + + #check if the command is only one character + if len(line.split(" ")[1])==1: + data.extend(modCharToHex(line.split(" ")[1])) + else: + data.extend(modKeyToHex(line.split(" ")[1])) + data.extend([0xFE, 0x00]) + return data + #special keys + elif line.startswith("DOWNARROW") or line.startswith("DOWN"): + return [ScanCode.KEY_DOWN] + elif line.startswith("LEFTARROW") or line.startswith("LEFT"): + return [ScanCode.KEY_LEFT] + elif line.startswith("RIGHTARROW") or line.startswith("RIGHT"): + return [ScanCode.KEY_RIGHT] + elif line.startswith("UPARROW") or line.startswith("UP"): + return [ScanCode.KEY_UP] + elif line.startswith("ENTER"): + return [ScanCode.KEY_ENTER] + elif line.startswith("DELETE"): + return [ScanCode.KEY_DELETE] + elif line.startswith("BACKSPACE"): + return [ScanCode.KEY_BACKSPACE] + elif line.startswith("END"): + return [ScanCode.KEY_END] + elif line.startswith("HOME"): + return [ScanCode.KEY_HOME] + elif line.startswith("ESCAPE") or line.startswith("ESC"): + return [ScanCode.KEY_ESC] + elif line.startswith("INSERT"): + return [ScanCode.KEY_INSERT] + elif line.startswith("PAGEUP"): + return [ScanCode.KEY_PAGEUP] + elif line.startswith("PAGEDOWN"): + return [ScanCode.KEY_PAGEDOWN] + elif line.startswith("CAPSLOCK"): + return [ScanCode.KEY_CAPSLOCK] + elif line.startswith("NUMLOCK"): + return [ScanCode.KEY_NUMLOCK] + elif line.startswith("SCROLLLOCK"): + return [ScanCode.KEY_SCROLLLOCK] + elif line.startswith("PRINTSCREEN"): + return [ScanCode.KEY_SYSRQ] + elif line.startswith("BREAK") or line.startswith("PAUSE"): + return [ScanCode.KEY_PAUSE] + elif line.startswith("SPACE"): + return [ScanCode.KEY_SPACE] + elif line.startswith("TAB"): + return [ScanCode.KEY_TAB] + elif line.startswith("MENU") or line.startswith("APP"): + return [ScanCode.KEY_MENU] + elif line.startswith("F1"): + return [ScanCode.KEY_F1] + elif line.startswith("F2"): + return [ScanCode.KEY_F2] + elif line.startswith("F3"): + return [ScanCode.KEY_F3] + elif line.startswith("F4"): + return [ScanCode.KEY_F4] + elif line.startswith("F5"): + return [ScanCode.KEY_F5] + elif line.startswith("F6"): + return [ScanCode.KEY_F6] + elif line.startswith("F7"): + return [ScanCode.KEY_F7] + elif line.startswith("F8"): + return [ScanCode.KEY_F8] + elif line.startswith("F9"): + return [ScanCode.KEY_F9] + elif line.startswith("F10"): + return [ScanCode.KEY_F10] + elif line.startswith("F11"): + return [ScanCode.KEY_F11] + elif line.startswith("F12"): + return [ScanCode.KEY_F12] + else: + return [0xFC] + + +def stringToHex(string): + hexData = [] + for char in string: + hexData.extend(charToHex(char)) + return hexData + +def modKeyToHex(key): + # DOWNARROW / DOWN + # LEFTARROW / LEFT + # RIGHTARROW / RIGHT + # UPARROW / UP + # ENTER + # DELETE + # BACKSPACE + # END + # HOME + # ESCAPE / ESC + # INSERT + # PAGEUP + # PAGEDOWN + # CAPSLOCK + # NUMLOCK + # SCROLLLOCK + # PRINTSCREEN + # BREAK Pause/Break key + # PAUSE Pause/Break key + # SPACE + # TAB + # MENU Context menu key + # APP Same as MENU + # Fx + if key == "DOWNARROW" or key == "DOWN": + return [ScanCode.KEY_DOWN] + elif key == "LEFTARROW" or key == "LEFT": + return [ScanCode.KEY_LEFT] + elif key == "RIGHTARROW" or key == "RIGHT": + return [ScanCode.KEY_RIGHT] + elif key == "UPARROW" or key == "UP": + return [ScanCode.KEY_UP] + elif key == "ENTER": + return [ScanCode.KEY_ENTER] + elif key == "DELETE": + return [ScanCode.KEY_DELETE] + elif key == "BACKSPACE": + return [ScanCode.KEY_BACKSPACE] + elif key == "END": + return [ScanCode.KEY_END] + elif key == "HOME": + return [ScanCode.KEY_HOME] + elif key == "ESCAPE" or key == "ESC": + return [ScanCode.KEY_ESC] + elif key == "INSERT": + return [ScanCode.KEY_INSERT] + elif key == "PAGEUP": + return [ScanCode.KEY_PAGEUP] + elif key == "PAGEDOWN": + return [ScanCode.KEY_PAGEDOWN] + elif key == "CAPSLOCK": + return [ScanCode.KEY_CAPSLOCK] + elif key == "NUMLOCK": + return [ScanCode.KEY_NUMLOCK] + elif key == "SCROLLLOCK": + return [ScanCode.KEY_SCROLLLOCK] + elif key == "PRINTSCREEN": + return [ScanCode.KEY_SYSRQ] + elif key == "BREAK" or key == "PAUSE": + return [ScanCode.KEY_PAUSE] + elif key == "SPACE": + return [ScanCode.KEY_SPACE] + elif key == "TAB": + return [ScanCode.KEY_TAB] + elif key == "MENU" or key == "APP": + return [ScanCode.KEY_MENU] + elif key == "F1": + return [ScanCode.KEY_F1] + elif key == "F2": + return [ScanCode.KEY_F2] + elif key == "F3": + return [ScanCode.KEY_F3] + elif key == "F4": + return [ScanCode.KEY_F4] + elif key == "F5": + return [ScanCode.KEY_F5] + elif key == "F6": + return [ScanCode.KEY_F6] + elif key == "F7": + return [ScanCode.KEY_F7] + elif key == "F8": + return [ScanCode.KEY_F8] + elif key == "F9": + return [ScanCode.KEY_F9] + elif key == "F10": + return [ScanCode.KEY_F10] + elif key == "F11": + return [ScanCode.KEY_F11] + elif key == "F12": + return [ScanCode.KEY_F12] + else: + return [0xFC] + +#Use for the Modifier + Key combinations +def modCharToHex(char): + if char == "a" or char == "A": + return [ScanCode.KEY_A] + elif char == "b" or char == "B": + return [ScanCode.KEY_B] + elif char == "c" or char == "C": + return [ScanCode.KEY_C] + elif char == "d" or char == "D": + return [ScanCode.KEY_D] + elif char == "e" or char == "E": + return [ScanCode.KEY_E] + elif char == "f" or char == "F": + return [ScanCode.KEY_F] + elif char == "g" or char == "G": + return [ScanCode.KEY_G] + elif char == "h" or char == "H": + return [ScanCode.KEY_H] + elif char == "i" or char == "I": + return [ScanCode.KEY_I] + elif char == "j" or char == "J": + return [ScanCode.KEY_J] + elif char == "k" or char == "K": + return [ScanCode.KEY_K] + elif char == "l" or char == "L": + return [ScanCode.KEY_L] + elif char == "m" or char == "M": + return [ScanCode.KEY_M] + elif char == "n" or char == "N": + return [ScanCode.KEY_N] + elif char == "o" or char == "O": + return [ScanCode.KEY_O] + elif char == "p" or char == "P": + return [ScanCode.KEY_P] + elif char == "q" or char == "Q": + return [ScanCode.KEY_Q] + elif char == "r" or char == "R": + return [ScanCode.KEY_R] + elif char == "s" or char == "S": + return [ScanCode.KEY_S] + elif char == "t" or char == "T": + return [ScanCode.KEY_T] + elif char == "u" or char == "U": + return [ScanCode.KEY_U] + elif char == "v" or char == "V": + return [ScanCode.KEY_V] + elif char == "w" or char == "W": + return [ScanCode.KEY_W] + elif char == "x" or char == "X": + return [ScanCode.KEY_X] + elif char == "y" or char == "Y": + return [ScanCode.KEY_Y] + elif char == "z" or char == "Z": + return [ScanCode.KEY_Z] + elif char == "1": + return [ScanCode.KEY_1] + elif char == "2": + return [ScanCode.KEY_2] + elif char == "3": + return [ScanCode.KEY_3] + elif char == "4": + return [ScanCode.KEY_4] + elif char == "5": + return [ScanCode.KEY_5] + elif char == "6": + return [ScanCode.KEY_6] + elif char == "7": + return [ScanCode.KEY_7] + elif char == "8": + return [ScanCode.KEY_8] + elif char == "9": + return [ScanCode.KEY_9] + elif char == "0": + return [ScanCode.KEY_0] + elif char == " ": + return [ScanCode.KEY_SPACE] + elif char == "-": + return [ScanCode.KEY_MINUS] + elif char == "=": + return [ScanCode.KEY_EQUAL] + elif char == "[": + return [ScanCode.KEY_LEFTBRACE] + elif char == "]": + return [ScanCode.KEY_RIGHTBRACE] + elif char == "\\": + return [ScanCode.KEY_BACKSLASH] + elif char == "#": + return [ScanCode.KEY_HASHTILDE] + elif char == ";": + return [ScanCode.KEY_SEMICOLON] + elif char == "'": + return [ScanCode.KEY_APOSTROPHE] + elif char == "`": + return [ScanCode.KEY_GRAVE] + elif char == ",": + return [ScanCode.KEY_COMMA] + elif char == ".": + return [ScanCode.KEY_DOT] + elif char == "/": + return [ScanCode.KEY_SLASH] + else: + return [0xFC] + +#Use for the stringToHex function +def charToHex(char): + if char == "a": + return [ScanCode.KEY_A] + elif char == "A": + # Shift + a + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_A, 0xFE, 0x00] + elif char == "b": + return [ScanCode.KEY_B] + elif char == "B": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_B, 0xFE, 0x00] + elif char == "c": + return [ScanCode.KEY_C] + elif char == "C": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_C, 0xFE, 0x00] + elif char == "d": + return [ScanCode.KEY_D] + elif char == "D": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_D, 0xFE, 0x00] + elif char == "e": + return [ScanCode.KEY_E] + elif char == "E": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_E, 0xFE, 0x00] + elif char == "f": + return [ScanCode.KEY_F] + elif char == "F": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_F, 0xFE, 0x00] + elif char == "g": + return [ScanCode.KEY_G] + elif char == "G": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_G, 0xFE, 0x00] + elif char == "h": + return [ScanCode.KEY_H] + elif char == "H": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_H, 0xFE, 0x00] + elif char == "i": + return [ScanCode.KEY_I] + elif char == "I": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_I, 0xFE, 0x00] + elif char == "j": + return [ScanCode.KEY_J] + elif char == "J": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_J, 0xFE, 0x00] + elif char == "k": + return [ScanCode.KEY_K] + elif char == "K": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_K, 0xFE, 0x00] + elif char == "l": + return [ScanCode.KEY_L] + elif char == "L": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_L, 0xFE, 0x00] + elif char == "m": + return [ScanCode.KEY_M] + elif char == "M": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_M, 0xFE, 0x00] + elif char == "n": + return [ScanCode.KEY_N] + elif char == "N": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_N, 0xFE, 0x00] + elif char == "o": + return [ScanCode.KEY_O] + elif char == "O": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_O, 0xFE, 0x00] + elif char == "p": + return [ScanCode.KEY_P] + elif char == "P": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_P, 0xFE, 0x00] + elif char == "q": + return [ScanCode.KEY_Q] + elif char == "Q": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Q, 0xFE, 0x00] + elif char == "r": + return [ScanCode.KEY_R] + elif char == "R": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_R, 0xFE, 0x00] + elif char == "s": + return [ScanCode.KEY_S] + elif char == "S": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_S, 0xFE, 0x00] + elif char == "t": + return [ScanCode.KEY_T] + elif char == "T": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_T, 0xFE, 0x00] + elif char == "u": + return [ScanCode.KEY_U] + elif char == "U": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_U, 0xFE, 0x00] + elif char == "v": + return [ScanCode.KEY_V] + elif char == "V": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_V, 0xFE, 0x00] + elif char == "w": + return [ScanCode.KEY_W] + elif char == "W": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_W, 0xFE, 0x00] + elif char == "x": + return [ScanCode.KEY_X] + elif char == "X": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_X, 0xFE, 0x00] + elif char == "y": + return [ScanCode.KEY_Y] + elif char == "Y": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Y, 0xFE, 0x00] + elif char == "z": + return [ScanCode.KEY_Z] + elif char == "Z": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Z, 0xFE, 0x00] + elif char == "1": + return [ScanCode.KEY_1] + elif char == "!": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_1, 0xFE, 0x00] + elif char == "2": + return [ScanCode.KEY_2] + elif char == "@": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_2, 0xFE, 0x00] + elif char == "3": + return [ScanCode.KEY_3] + elif char == "#": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_3, 0xFE, 0x00] + elif char == "4": + return [ScanCode.KEY_4] + elif char == "$": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_4, 0xFE, 0x00] + elif char == "5": + return [ScanCode.KEY_5] + elif char == "%": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_5, 0xFE, 0x00] + elif char == "6": + return [ScanCode.KEY_6] + elif char == "^": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_6, 0xFE, 0x00] + elif char == "7": + return [ScanCode.KEY_7] + elif char == "&": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_7, 0xFE, 0x00] + elif char == "8": + return [ScanCode.KEY_8] + elif char == "*": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_8, 0xFE, 0x00] + elif char == "9": + return [ScanCode.KEY_9] + elif char == "(": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_9, 0xFE, 0x00] + elif char == "0": + return [ScanCode.KEY_0] + elif char == ")": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_0, 0xFE, 0x00] + + # KEY_SPACE =0x2c # Keyboard Spacebar + # KEY_MINUS =0x2d # Keyboard - and _ + # KEY_EQUAL =0x2e # Keyboard = and + + # KEY_LEFTBRACE =0x2f # Keyboard [ and { + # KEY_RIGHTBRACE =0x30 # Keyboard ] and } + # KEY_BACKSLASH =0x31 # Keyboard \ and | + # KEY_HASHTILDE =0x32 # Keyboard Non-US # and ~ + # KEY_SEMICOLON =0x33 # Keyboard ; and : + # KEY_APOSTROPHE =0x34 # Keyboard ' and " + # KEY_GRAVE =0x35 # Keyboard ` and ~ + # KEY_COMMA =0x36 # Keyboard , and < + # KEY_DOT =0x37 # Keyboard . and > + # KEY_SLASH =0x38 # Keyboard / and ? + + elif char == " ": + return [ScanCode.KEY_SPACE] + elif char == "-": + return [ScanCode.KEY_MINUS] + elif char == "_": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_MINUS, 0xFE, 0x00] + elif char == "=": + return [ScanCode.KEY_EQUAL] + elif char == "+": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_EQUAL, 0xFE, 0x00] + elif char == "[": + return [ScanCode.KEY_LEFTBRACE] + elif char == "{": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_LEFTBRACE, 0xFE, 0x00] + elif char == "]": + return [ScanCode.KEY_RIGHTBRACE] + elif char == "}": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_RIGHTBRACE, 0xFE, 0x00] + elif char == "\\": + return [ScanCode.KEY_BACKSLASH] + elif char == "|": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_BACKSLASH, 0xFE, 0x00] + elif char == "#": + return [ScanCode.KEY_HASHTILDE] + elif char == "~": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_HASHTILDE, 0xFE, 0x00] + elif char == ";": + return [ScanCode.KEY_SEMICOLON] + elif char == ":": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SEMICOLON, 0xFE, 0x00] + elif char == "'": + return [ScanCode.KEY_APOSTROPHE] + elif char == "\"": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_APOSTROPHE, 0xFE, 0x00] + elif char == "`": + return [ScanCode.KEY_GRAVE] + elif char == "~": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_GRAVE, 0xFE, 0x00] + elif char == ",": + return [ScanCode.KEY_COMMA] + elif char == "<": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_COMMA, 0xFE, 0x00] + elif char == ".": + return [ScanCode.KEY_DOT] + elif char == ">": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_DOT, 0xFE, 0x00] + elif char == "/": + return [ScanCode.KEY_SLASH] + elif char == "?": + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SLASH, 0xFE, 0x00] + else: + return [0xFC] + + + +if __name__ == '__main__': + print(list(map(hex, scriptToHex("/home/justin/Downloads/demo_windows.txt")))) + data=scriptToHex("/home/justin/Downloads/demo_windows.txt") + with open('test', 'wb') as f: + for i in data: + f.write(bytes((i,))) \ No newline at end of file diff --git a/sw/BadgeCommander/BadgeCommander.py b/sw/BadgeCommander/BadgeCommander.py index b112fba8..04240f8d 100644 --- a/sw/BadgeCommander/BadgeCommander.py +++ b/sw/BadgeCommander/BadgeCommander.py @@ -2,12 +2,12 @@ import ttkbootstrap as ttk import imageres from tkinter import filedialog -import ttkbootstrap.scrolled as scrolled from ttkbootstrap.dialogs import Messagebox from tkinter import font as tkFont import sys import STM32HID import tkinter as tk +import BadUSBTranslation #Check the connection of the Badge @@ -51,6 +51,15 @@ def setName(Name): if k==-1: #error checkBadgeConnection() + +def writeBadUSB(scriptPath): + try: + rawData=BadUSBTranslation.scriptToHex(scriptPath) + print(rawData) + STM32HID.send_badusb_script(rawData) + except: + Messagebox.show_error('Please Connect the PCB Badge to the Computer and try again', 'Error') + checkBadgeConnection() # Get the zoom value of the system ZOOM_VALUE = getZoomValue() @@ -131,8 +140,21 @@ def character_limit(entry_text): BadUSBFrame = ttk.Frame() +badUSBLabel = ttk.Label(BadUSBFrame, text='Please Select the BadUSB script File:', font=('SquareFont', 12)) +badUSBLabel.pack(side='top', fill='x', padx=int(10*ZOOM_VALUE), pady=int(10*ZOOM_VALUE)) +scriptPathFrame = ttk.Frame(BadUSBFrame) +scriptPathFrame.pack(side='top', fill='x', padx=int(10*ZOOM_VALUE)) +scriptPathLabel = ttk.Label(scriptPathFrame, text='Please Select Script File', font=('SquareFont', 10), bootstyle='light', width=25) +scriptPathLabel.pack(side='left', fill='x', expand=True, ipadx=int(10*ZOOM_VALUE), ipady=int(5*ZOOM_VALUE)) +scriptBrowseButton = ttk.Button(scriptPathFrame, text='Browse', command=lambda: scriptPathLabel.config(text=filedialog.askopenfilename()), bootstyle='light') +scriptBrowseButton.pack(side='right', ipadx=int(10*ZOOM_VALUE), ipady=int(5*ZOOM_VALUE)) +writeButton = ttk.Button(BadUSBFrame, text='Write Script to Badge', command=lambda: writeBadUSB(scriptPathLabel.cget('text')), bootstyle='light') +writeButton.pack(side='right', padx=int(10*ZOOM_VALUE), pady=int(10*ZOOM_VALUE), ipadx=int(10*ZOOM_VALUE), ipady=int(0*ZOOM_VALUE)) + + + notebook.add(SetNameFrame, text=' Set Name ', padding=int(10*ZOOM_VALUE)) -notebook.add(BadUSBFrame, text=' BadUSB ') +notebook.add(BadUSBFrame, text=' BadUSB ', padding=int(10*ZOOM_VALUE)) notebook.pack(side='bottom', fill='both', expand=True, padx=int(10*ZOOM_VALUE), pady=int(10*ZOOM_VALUE)) # Apply the custom font to widgets diff --git a/sw/BadgeCommander/LICENSE b/sw/BadgeCommander/LICENSE new file mode 100644 index 00000000..0961f915 --- /dev/null +++ b/sw/BadgeCommander/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Justin Lin + +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. diff --git a/sw/BadgeCommander/STM32HID.py b/sw/BadgeCommander/STM32HID.py index bb7d77a1..392c0870 100644 --- a/sw/BadgeCommander/STM32HID.py +++ b/sw/BadgeCommander/STM32HID.py @@ -33,7 +33,8 @@ def clear_badusb(): def send_badusb_script(script): datatosend = [0x00]*3 datatosend[0] = 0x03 - datatosend[1:2] = len(script) + datatosend[1:3] = len(script).to_bytes(2, 'big') + print(datatosend+ script) send_command(datatosend + script) def send_command(command): diff --git a/sw/BadgeCommander/ScanCode.py b/sw/BadgeCommander/ScanCode.py new file mode 100644 index 00000000..9573a4ed --- /dev/null +++ b/sw/BadgeCommander/ScanCode.py @@ -0,0 +1,271 @@ +# /** +# * Modifier masks - used for the first byte in the HID report. +# * NOTE: The second byte in the report is reserved, =0x00 +# */ +KEY_MOD_LCTRL =0x01 +KEY_MOD_LSHIFT =0x02 +KEY_MOD_LALT =0x04 +KEY_MOD_LMETA =0x08 +KEY_MOD_RCTRL =0x10 +KEY_MOD_RSHIFT =0x20 +KEY_MOD_RALT =0x40 +KEY_MOD_RMETA =0x80 + +# /** +# * Scan codes - last N slots in the HID report (usually 6). +# * =0x00 if no key pressed. +# * +# * If more than N keys are pressed, the HID reports +# * KEY_ERR_OVF in all slots to indicate this condition. +# */ + +KEY_NONE =0x00 # No key pressed +KEY_ERR_OVF =0x01 # Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key") +# =0x02 # Keyboard POST Fail +# =0x03 # Keyboard Error Undefined +KEY_A =0x04 # Keyboard a and A +KEY_B =0x05 # Keyboard b and B +KEY_C =0x06 # Keyboard c and C +KEY_D =0x07 # Keyboard d and D +KEY_E =0x08 # Keyboard e and E +KEY_F =0x09 # Keyboard f and F +KEY_G =0x0a # Keyboard g and G +KEY_H =0x0b # Keyboard h and H +KEY_I =0x0c # Keyboard i and I +KEY_J =0x0d # Keyboard j and J +KEY_K =0x0e # Keyboard k and K +KEY_L =0x0f # Keyboard l and L +KEY_M =0x10 # Keyboard m and M +KEY_N =0x11 # Keyboard n and N +KEY_O =0x12 # Keyboard o and O +KEY_P =0x13 # Keyboard p and P +KEY_Q =0x14 # Keyboard q and Q +KEY_R =0x15 # Keyboard r and R +KEY_S =0x16 # Keyboard s and S +KEY_T =0x17 # Keyboard t and T +KEY_U =0x18 # Keyboard u and U +KEY_V =0x19 # Keyboard v and V +KEY_W =0x1a # Keyboard w and W +KEY_X =0x1b # Keyboard x and X +KEY_Y =0x1c # Keyboard y and Y +KEY_Z =0x1d # Keyboard z and Z + +KEY_1 =0x1e # Keyboard 1 and ! +KEY_2 =0x1f # Keyboard 2 and @ +KEY_3 =0x20 # Keyboard 3 and # +KEY_4 =0x21 # Keyboard 4 and $ +KEY_5 =0x22 # Keyboard 5 and % +KEY_6 =0x23 # Keyboard 6 and ^ +KEY_7 =0x24 # Keyboard 7 and & +KEY_8 =0x25 # Keyboard 8 and * +KEY_9 =0x26 # Keyboard 9 and ( +KEY_0 =0x27 # Keyboard 0 and ) + +KEY_ENTER =0x28 # Keyboard Return (ENTER) +KEY_ESC =0x29 # Keyboard ESCAPE +KEY_BACKSPACE =0x2a # Keyboard DELETE (Backspace) +KEY_TAB =0x2b # Keyboard Tab +KEY_SPACE =0x2c # Keyboard Spacebar +KEY_MINUS =0x2d # Keyboard - and _ +KEY_EQUAL =0x2e # Keyboard = and + +KEY_LEFTBRACE =0x2f # Keyboard [ and { +KEY_RIGHTBRACE =0x30 # Keyboard ] and } +KEY_BACKSLASH =0x31 # Keyboard \ and | +KEY_HASHTILDE =0x32 # Keyboard Non-US # and ~ +KEY_SEMICOLON =0x33 # Keyboard ; and : +KEY_APOSTROPHE =0x34 # Keyboard ' and " +KEY_GRAVE =0x35 # Keyboard ` and ~ +KEY_COMMA =0x36 # Keyboard , and < +KEY_DOT =0x37 # Keyboard . and > +KEY_SLASH =0x38 # Keyboard / and ? +KEY_CAPSLOCK =0x39 # Keyboard Caps Lock + +KEY_F1 =0x3a # Keyboard F1 +KEY_F2 =0x3b # Keyboard F2 +KEY_F3 =0x3c # Keyboard F3 +KEY_F4 =0x3d # Keyboard F4 +KEY_F5 =0x3e # Keyboard F5 +KEY_F6 =0x3f # Keyboard F6 +KEY_F7 =0x40 # Keyboard F7 +KEY_F8 =0x41 # Keyboard F8 +KEY_F9 =0x42 # Keyboard F9 +KEY_F10 =0x43 # Keyboard F10 +KEY_F11 =0x44 # Keyboard F11 +KEY_F12 =0x45 # Keyboard F12 + +KEY_SYSRQ =0x46 # Keyboard Print Screen +KEY_SCROLLLOCK =0x47 # Keyboard Scroll Lock +KEY_PAUSE =0x48 # Keyboard Pause +KEY_INSERT =0x49 # Keyboard Insert +KEY_HOME =0x4a # Keyboard Home +KEY_PAGEUP =0x4b # Keyboard Page Up +KEY_DELETE =0x4c # Keyboard Delete Forward +KEY_END =0x4d # Keyboard End +KEY_PAGEDOWN =0x4e # Keyboard Page Down +KEY_RIGHT =0x4f # Keyboard Right Arrow +KEY_LEFT =0x50 # Keyboard Left Arrow +KEY_DOWN =0x51 # Keyboard Down Arrow +KEY_UP =0x52 # Keyboard Up Arrow + +KEY_NUMLOCK =0x53 # Keyboard Num Lock and Clear +KEY_KPSLASH =0x54 # Keypad / +KEY_KPASTERISK =0x55 # Keypad * +KEY_KPMINUS =0x56 # Keypad - +KEY_KPPLUS =0x57 # Keypad + +KEY_KPENTER =0x58 # Keypad ENTER +KEY_KP1 =0x59 # Keypad 1 and End +KEY_KP2 =0x5a # Keypad 2 and Down Arrow +KEY_KP3 =0x5b # Keypad 3 and PageDn +KEY_KP4 =0x5c # Keypad 4 and Left Arrow +KEY_KP5 =0x5d # Keypad 5 +KEY_KP6 =0x5e # Keypad 6 and Right Arrow +KEY_KP7 =0x5f # Keypad 7 and Home +KEY_KP8 =0x60 # Keypad 8 and Up Arrow +KEY_KP9 =0x61 # Keypad 9 and Page Up +KEY_KP0 =0x62 # Keypad 0 and Insert +KEY_KPDOT =0x63 # Keypad . and Delete + +KEY_102ND =0x64 # Keyboard Non-US \ and | +KEY_COMPOSE =0x65 # Keyboard Application +KEY_POWER =0x66 # Keyboard Power +KEY_KPEQUAL =0x67 # Keypad = + +KEY_F13 =0x68 # Keyboard F13 +KEY_F14 =0x69 # Keyboard F14 +KEY_F15 =0x6a # Keyboard F15 +KEY_F16 =0x6b # Keyboard F16 +KEY_F17 =0x6c # Keyboard F17 +KEY_F18 =0x6d # Keyboard F18 +KEY_F19 =0x6e # Keyboard F19 +KEY_F20 =0x6f # Keyboard F20 +KEY_F21 =0x70 # Keyboard F21 +KEY_F22 =0x71 # Keyboard F22 +KEY_F23 =0x72 # Keyboard F23 +KEY_F24 =0x73 # Keyboard F24 + +KEY_OPEN =0x74 # Keyboard Execute +KEY_HELP =0x75 # Keyboard Help +KEY_PROPS =0x76 # Keyboard Menu +KEY_FRONT =0x77 # Keyboard Select +KEY_STOP =0x78 # Keyboard Stop +KEY_AGAIN =0x79 # Keyboard Again +KEY_UNDO =0x7a # Keyboard Undo +KEY_CUT =0x7b # Keyboard Cut +KEY_COPY =0x7c # Keyboard Copy +KEY_PASTE =0x7d # Keyboard Paste +KEY_FIND =0x7e # Keyboard Find +KEY_MUTE =0x7f # Keyboard Mute +KEY_VOLUMEUP =0x80 # Keyboard Volume Up +KEY_VOLUMEDOWN =0x81 # Keyboard Volume Down +# =0x82 Keyboard Locking Caps Lock +# =0x83 Keyboard Locking Num Lock +# =0x84 Keyboard Locking Scroll Lock +KEY_KPCOMMA =0x85 # Keypad Comma +# =0x86 Keypad Equal Sign +KEY_RO =0x87 # Keyboard International1 +KEY_KATAKANAHIRAGANA =0x88 # Keyboard International2 +KEY_YEN =0x89 # Keyboard International3 +KEY_HENKAN =0x8a # Keyboard International4 +KEY_MUHENKAN =0x8b # Keyboard International5 +KEY_KPJPCOMMA =0x8c # Keyboard International6 +# =0x8d Keyboard International7 +# =0x8e Keyboard International8 +# =0x8f Keyboard International9 +KEY_HANGEUL =0x90 # Keyboard LANG1 +KEY_HANJA =0x91 # Keyboard LANG2 +KEY_KATAKANA =0x92 # Keyboard LANG3 +KEY_HIRAGANA =0x93 # Keyboard LANG4 +KEY_ZENKAKUHANKAKU =0x94 # Keyboard LANG5 +# =0x95 Keyboard LANG6 +# =0x96 Keyboard LANG7 +# =0x97 Keyboard LANG8 +# =0x98 Keyboard LANG9 +# =0x99 Keyboard Alternate Erase +# =0x9a Keyboard SysReq/Attention +# =0x9b Keyboard Cancel +# =0x9c Keyboard Clear +# =0x9d Keyboard Prior +# =0x9e Keyboard Return +# =0x9f Keyboard Separator +# =0xa0 Keyboard Out +# =0xa1 Keyboard Oper +# =0xa2 Keyboard Clear/Again +# =0xa3 Keyboard CrSel/Props +# =0xa4 Keyboard ExSel + +# =0xb0 Keypad 00 +# =0xb1 Keypad 000 +# =0xb2 Thousands Separator +# =0xb3 Decimal Separator +# =0xb4 Currency Unit +# =0xb5 Currency Sub-unit +KEY_KPLEFTPAREN =0xb6 # Keypad ( +KEY_KPRIGHTPAREN =0xb7 # Keypad ) +# =0xb8 Keypad { +# =0xb9 Keypad } +# =0xba Keypad Tab +# =0xbb Keypad Backspace +# =0xbc Keypad A +# =0xbd Keypad B +# =0xbe Keypad C +# =0xbf Keypad D +# =0xc0 Keypad E +# =0xc1 Keypad F +# =0xc2 Keypad XOR +# =0xc3 Keypad ^ +# =0xc4 Keypad % +# =0xc5 Keypad < +# =0xc6 Keypad > +# =0xc7 Keypad & +# =0xc8 Keypad && +# =0xc9 Keypad | +# =0xca Keypad || +# =0xcb Keypad : +# =0xcc Keypad # +# =0xcd Keypad Space +# =0xce Keypad @ +# =0xcf Keypad ! +# =0xd0 Keypad Memory Store +# =0xd1 Keypad Memory Recall +# =0xd2 Keypad Memory Clear +# =0xd3 Keypad Memory Add +# =0xd4 Keypad Memory Subtract +# =0xd5 Keypad Memory Multiply +# =0xd6 Keypad Memory Divide +# =0xd7 Keypad +/- +# =0xd8 Keypad Clear +# =0xd9 Keypad Clear Entry +# =0xda Keypad Binary +# =0xdb Keypad Octal +# =0xdc Keypad Decimal +# =0xdd Keypad Hexadecimal + +KEY_LEFTCTRL =0xe0 # Keyboard Left Control +KEY_LEFTSHIFT =0xe1 # Keyboard Left Shift +KEY_LEFTALT =0xe2 # Keyboard Left Alt +KEY_LEFTMETA =0xe3 # Keyboard Left GUI +KEY_RIGHTCTRL =0xe4 # Keyboard Right Control +KEY_RIGHTSHIFT =0xe5 # Keyboard Right Shift +KEY_RIGHTALT =0xe6 # Keyboard Right Alt +KEY_RIGHTMETA =0xe7 # Keyboard Right GUI + +KEY_MEDIA_PLAYPAUSE =0xe8 +KEY_MEDIA_STOPCD =0xe9 +KEY_MEDIA_PREVIOUSSONG =0xea +KEY_MEDIA_NEXTSONG =0xeb +KEY_MEDIA_EJECTCD =0xec +KEY_MEDIA_VOLUMEUP =0xed +KEY_MEDIA_VOLUMEDOWN =0xee +KEY_MEDIA_MUTE =0xef +KEY_MEDIA_WWW =0xf0 +KEY_MEDIA_BACK =0xf1 +KEY_MEDIA_FORWARD =0xf2 +KEY_MEDIA_STOP =0xf3 +KEY_MEDIA_FIND =0xf4 +KEY_MEDIA_SCROLLUP =0xf5 +KEY_MEDIA_SCROLLDOWN =0xf6 +KEY_MEDIA_EDIT =0xf7 +KEY_MEDIA_SLEEP =0xf8 +KEY_MEDIA_COFFEE =0xf9 +KEY_MEDIA_REFRESH =0xfa +KEY_MEDIA_CALC =0xfb \ No newline at end of file diff --git a/sw/BadgeCommander/demo_windows.txt b/sw/BadgeCommander/demo_windows.txt new file mode 100644 index 00000000..4ae69ecd --- /dev/null +++ b/sw/BadgeCommander/demo_windows.txt @@ -0,0 +1,81 @@ +REM This is BadUSB demo script for windows + +REM Open windows notepad +DELAY 1000 +GUI r +DELAY 500 +STRING notepad +DELAY 500 +ENTER +DELAY 750 + +STRING Hello World! +ENTER + +REM Copy-Paste previous string +UP +HOME +SHIFT DOWN +CTRL c +RIGHT +CTRL v +CTRL v + +REM Alt code input demo + +ENTER + +STRING = +ENTER +ENTER + +STRING _.-------.._ -, +ENTER +HOME +STRING .-"```"--..,,_/ /`-, -, \ +ENTER +HOME +STRING .:" /:/ /'\ \ ,_..., `. | | +ENTER +HOME +STRING / ,----/:/ /`\ _\~`_-"` _; +ENTER +HOME +STRING ' / /`"""'\ \ \.~`_-' ,-"'/ +ENTER +HOME +STRING | | | 0 | | .-' ,/` / +ENTER +HOME +STRING | ,..\ \ ,.-"` ,/` / +ENTER +HOME +STRING ; : `/`""\` ,/--==,/-----, +ENTER +HOME +STRING | `-...| -.___-Z:_______J...---; +ENTER +HOME +STRING : ` _-' +ENTER +HOME +STRING _L_ _ ___ ___ ___ ___ ____--"` +ENTER +HOME +STRING | __|| | |_ _|| _ \| _ \| __|| _ \ +ENTER +HOME +STRING | _| | |__ | | | _/| _/| _| | / +ENTER +HOME +STRING |_| |____||___||_| |_| |___||_|_\ +ENTER +HOME +ENTER + +STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script format +ENTER +STRING More information about script syntax can be found here: +ENTER +STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md +ENTER From b8e9324a2a5379049ffe46e9e4231be818c927fd Mon Sep 17 00:00:00 2001 From: Justin Lin <61717681+justinlin099@users.noreply.github.com> Date: Sat, 10 Aug 2024 17:36:17 +0800 Subject: [PATCH 02/11] Create requirements.txt --- sw/BadgeCommander/requirements.txt | Bin 0 -> 122 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 sw/BadgeCommander/requirements.txt diff --git a/sw/BadgeCommander/requirements.txt b/sw/BadgeCommander/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..c54461a79788b4e360c60ad98672d484c96a1a39 GIT binary patch literal 122 zcmXAhK?;B{3C0@;P2H<%0jYaC;PoS2OA4TdzMB90#VakA#+oi h=;@qEB;6iogENh_yh<>r*6K? Date: Sat, 10 Aug 2024 17:54:11 +0800 Subject: [PATCH 03/11] Update BadgeCommander.py --- sw/BadgeCommander/BadgeCommander.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/BadgeCommander/BadgeCommander.py b/sw/BadgeCommander/BadgeCommander.py index 04240f8d..c7d9e72c 100644 --- a/sw/BadgeCommander/BadgeCommander.py +++ b/sw/BadgeCommander/BadgeCommander.py @@ -37,7 +37,7 @@ def getZoomValue(): if getOS() == "win32": zoomValue = getWinZoomValue() #linux - if getOS() == "linux": + elif getOS() == "linux": import LinuxScale print(LinuxScale.get_scaling_factor()) zoomValue = float(LinuxScale.get_scaling_factor()) From 7a28465f80208b8e21981225754a12dc0fb4b8fd Mon Sep 17 00:00:00 2001 From: Justin Lin <61717681+justinlin099@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:25:53 +0800 Subject: [PATCH 04/11] Update BadUSBTranslation.py --- sw/BadgeCommander/BadUSBTranslation.py | 230 ++++++++++++++----------- 1 file changed, 134 insertions(+), 96 deletions(-) diff --git a/sw/BadgeCommander/BadUSBTranslation.py b/sw/BadgeCommander/BadUSBTranslation.py index ffab2cf5..3af26ea4 100644 --- a/sw/BadgeCommander/BadUSBTranslation.py +++ b/sw/BadgeCommander/BadUSBTranslation.py @@ -1,4 +1,7 @@ import ScanCode +nextStringDelay = 0 +defaultDelay = 0 +defaultStringDelay =0 def scriptToHex(scriptPath): hexData = [] @@ -7,9 +10,26 @@ def scriptToHex(scriptPath): data = file.readlines() data = [x.strip() for x in data] for line in data: - if line != "" and not line.startswith("REM"): + if line.startswith("REPEAT"): + lastCommand=lastCommand*int(line.split(" ")[1]) + elif line.startswith("STRING_DELAY") or line.startswith("STRINGDELAY"): + global nextStringDelay + nextStringDelay=int(int(line.split(" ")[1])/10) + elif line.startswith("DEFAULT_STRING_DELAY") or line.startswith("DEFAULTSTRINGDELAY"): + global defaultStringDelay + defaultStringDelay=int(int(line.split(" ")[1])/10) + elif line.startswith("DEFAULT_DELAY") or line.startswith("DEFAULTDELAY"): + global defaultDelay + defaultDelay=int(int(line.split(" ")[1])/10) + elif line != "" and not line.startswith("REM"): print(line) - hexData=hexData+lineToHex(line) + lastCommand=lineToHex(line) + if defaultDelay != 0: + if defaultDelay>255: + defaultDelay=255 + hexData.append(0xFF) + hexData.append(defaultDelay) + hexData=hexData+lastCommand hexData.append(0xFD) return hexData @@ -17,124 +37,128 @@ def scriptToHex(scriptPath): def lineToHex(line): if line.startswith("DELAY"): return [0xFF, int(int(line.split(" ")[1])/10)] - elif line.startswith("STRING"): - return stringToHex(line.split(" ")[1]) elif line.startswith("STRINGLN"): - return stringToHex(line.split(" ")[1])+[ScanCode.KEY_ENTER] + print (line[9:]) + return stringToHex(line[9:])+[ScanCode.KEY_ENTER] + elif line.startswith("STRING"): + print (line[7:]) + return stringToHex(line[7:]) elif line.startswith("ALTCHAR"): - return [0xFE, ScanCode.KEY_MOD_LALT]+modCharToHex(line.split(" ")[1])+[0xFE, 0x00] - elif line.startswith("GUI") or line.startswith("WINDOWS"): - data=[0xFE, ScanCode.KEY_MOD_LMETA] + return [0xFE, ScanCode.KEY_MOD_LALT]+modCharToHex(line.split(" ")[1])+[0x00] + + + # combie the modifier keys + # CTRL-ALT CTRL+ALT + # CTRL-SHIFT CTRL+SHIFT + # ALT-SHIFT ALT+SHIFT + # ALT-GUI ALT+WIN + # GUI-SHIFT WIN+SHIFT + # GUI-CTRL WIN+CTRL + elif line.startswith("CTRL-ALT"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LALT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) - else: #check other key + else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - elif line.startswith("ALT"): - data=[0xFE, ScanCode.KEY_MOD_LALT] + + elif line.startswith("CTRL-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LSHIFT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - elif line.startswith("CTRL"): - data=[0xFE, ScanCode.KEY_MOD_LCTRL] + + elif line.startswith("ALT-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LSHIFT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - elif line.startswith("SHIFT"): - data=[0xFE, ScanCode.KEY_MOD_LSHIFT] + + elif line.startswith("ALT-GUI"): + data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LMETA] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - # combie the modifier keys - # CTRL-ALT CTRL+ALT - # CTRL-SHIFT CTRL+SHIFT - # ALT-SHIFT ALT+SHIFT - # ALT-GUI ALT+WIN - # GUI-SHIFT WIN+SHIFT - # GUI-CTRL WIN+CTRL - elif line.startswith("CTRL-ALT"): - data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LALT] + elif line.startswith("GUI-SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LSHIFT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - elif line.startswith("CTRL-SHIFT"): - data=[0xFE, ScanCode.KEY_MOD_LCTRL+ScanCode.KEY_MOD_LSHIFT] + elif line.startswith("GUI-CTRL"): + data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LCTRL] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - elif line.startswith("ALT-SHIFT"): - data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LSHIFT] + elif line.startswith("GUI") or line.startswith("WINDOWS"): + data=[0xFE, ScanCode.KEY_MOD_LMETA] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) - else: + else: #check other key data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - - elif line.startswith("ALT-GUI"): - data=[0xFE, ScanCode.KEY_MOD_LALT+ScanCode.KEY_MOD_LMETA] + elif line.startswith("ALT"): + data=[0xFE, ScanCode.KEY_MOD_LALT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - - elif line.startswith("GUI-SHIFT"): - data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LSHIFT] + elif line.startswith("CTRL"): + data=[0xFE, ScanCode.KEY_MOD_LCTRL] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data - - elif line.startswith("GUI-CTRL"): - data=[0xFE, ScanCode.KEY_MOD_LMETA+ScanCode.KEY_MOD_LCTRL] + elif line.startswith("SHIFT"): + data=[0xFE, ScanCode.KEY_MOD_LSHIFT] #check if the command is only one character if len(line.split(" ")[1])==1: data.extend(modCharToHex(line.split(" ")[1])) else: data.extend(modKeyToHex(line.split(" ")[1])) - data.extend([0xFE, 0x00]) + data.extend([0x00]) return data #special keys elif line.startswith("DOWNARROW") or line.startswith("DOWN"): @@ -208,9 +232,22 @@ def lineToHex(line): def stringToHex(string): + global nextStringDelay + global defaultStringDelay + if nextStringDelay != 0: + if nextStringDelay>255: + nextStringDelay=255 + rawDelay=[0xFF]+[nextStringDelay] + elif defaultStringDelay != 0: + if defaultStringDelay>255: + defaultStringDelay=255 + rawDelay=[0xFF]+[defaultStringDelay] hexData = [] for char in string: hexData.extend(charToHex(char)) + if nextStringDelay != 0 or defaultStringDelay != 0: + hexData.extend(rawDelay) + nextStringDelay=0 return hexData def modKeyToHex(key): @@ -416,147 +453,148 @@ def charToHex(char): return [ScanCode.KEY_A] elif char == "A": # Shift + a - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_A, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_A, 0x00] elif char == "b": return [ScanCode.KEY_B] elif char == "B": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_B, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_B, 0x00] elif char == "c": return [ScanCode.KEY_C] elif char == "C": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_C, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_C, 0x00] elif char == "d": return [ScanCode.KEY_D] elif char == "D": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_D, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_D, 0x00] elif char == "e": return [ScanCode.KEY_E] elif char == "E": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_E, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_E, 0x00] elif char == "f": return [ScanCode.KEY_F] elif char == "F": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_F, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_F, 0x00] elif char == "g": return [ScanCode.KEY_G] elif char == "G": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_G, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_G, 0x00] elif char == "h": return [ScanCode.KEY_H] elif char == "H": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_H, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_H, 0x00] elif char == "i": return [ScanCode.KEY_I] elif char == "I": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_I, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_I, 0x00] elif char == "j": return [ScanCode.KEY_J] elif char == "J": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_J, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_J, 0x00] elif char == "k": return [ScanCode.KEY_K] elif char == "K": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_K, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_K, 0x00] elif char == "l": return [ScanCode.KEY_L] elif char == "L": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_L, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_L, 0x00] elif char == "m": return [ScanCode.KEY_M] elif char == "M": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_M, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_M, 0x00] elif char == "n": return [ScanCode.KEY_N] elif char == "N": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_N, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_N, 0x00] elif char == "o": return [ScanCode.KEY_O] elif char == "O": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_O, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_O, 0x00] elif char == "p": return [ScanCode.KEY_P] elif char == "P": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_P, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_P, 0x00] elif char == "q": return [ScanCode.KEY_Q] elif char == "Q": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Q, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Q, 0x00] elif char == "r": return [ScanCode.KEY_R] elif char == "R": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_R, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_R, 0x00] elif char == "s": return [ScanCode.KEY_S] elif char == "S": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_S, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_S, 0x00] elif char == "t": return [ScanCode.KEY_T] elif char == "T": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_T, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_T, 0x00] elif char == "u": return [ScanCode.KEY_U] elif char == "U": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_U, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_U, 0x00] elif char == "v": return [ScanCode.KEY_V] elif char == "V": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_V, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_V, 0x00] elif char == "w": return [ScanCode.KEY_W] elif char == "W": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_W, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_W, 0x00] elif char == "x": return [ScanCode.KEY_X] elif char == "X": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_X, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_X, 0x00] elif char == "y": return [ScanCode.KEY_Y] elif char == "Y": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Y, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Y, 0x00] elif char == "z": return [ScanCode.KEY_Z] elif char == "Z": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Z, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_Z, 0x00] elif char == "1": return [ScanCode.KEY_1] elif char == "!": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_1, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_1, 0x00] elif char == "2": return [ScanCode.KEY_2] elif char == "@": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_2, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_2, 0x00] elif char == "3": return [ScanCode.KEY_3] elif char == "#": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_3, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_3, 0x00] elif char == "4": return [ScanCode.KEY_4] elif char == "$": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_4, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_4, 0x00] elif char == "5": return [ScanCode.KEY_5] elif char == "%": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_5, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_5, 0x00] elif char == "6": return [ScanCode.KEY_6] elif char == "^": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_6, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_6, 0x00] elif char == "7": return [ScanCode.KEY_7] elif char == "&": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_7, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_7, 0x00] elif char == "8": return [ScanCode.KEY_8] elif char == "*": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_8, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_8, 0x00] elif char == "9": return [ScanCode.KEY_9] elif char == "(": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_9, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_9, 0x00] elif char == "0": return [ScanCode.KEY_0] elif char == ")": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_0, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_0, 0x00] + # KEY_SPACE =0x2c # Keyboard Spacebar # KEY_MINUS =0x2d # Keyboard - and _ @@ -577,51 +615,51 @@ def charToHex(char): elif char == "-": return [ScanCode.KEY_MINUS] elif char == "_": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_MINUS, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_MINUS, 0x00] elif char == "=": return [ScanCode.KEY_EQUAL] elif char == "+": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_EQUAL, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_EQUAL, 0x00] elif char == "[": return [ScanCode.KEY_LEFTBRACE] elif char == "{": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_LEFTBRACE, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_LEFTBRACE, 0x00] elif char == "]": return [ScanCode.KEY_RIGHTBRACE] elif char == "}": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_RIGHTBRACE, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_RIGHTBRACE, 0x00] elif char == "\\": return [ScanCode.KEY_BACKSLASH] elif char == "|": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_BACKSLASH, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_BACKSLASH, 0x00] elif char == "#": return [ScanCode.KEY_HASHTILDE] elif char == "~": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_HASHTILDE, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_HASHTILDE, 0x00] elif char == ";": return [ScanCode.KEY_SEMICOLON] elif char == ":": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SEMICOLON, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SEMICOLON, 0x00] elif char == "'": return [ScanCode.KEY_APOSTROPHE] elif char == "\"": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_APOSTROPHE, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_APOSTROPHE, 0x00] elif char == "`": return [ScanCode.KEY_GRAVE] elif char == "~": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_GRAVE, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_GRAVE, 0x00] elif char == ",": return [ScanCode.KEY_COMMA] elif char == "<": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_COMMA, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_COMMA, 0x00] elif char == ".": return [ScanCode.KEY_DOT] elif char == ">": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_DOT, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_DOT, 0x00] elif char == "/": return [ScanCode.KEY_SLASH] elif char == "?": - return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SLASH, 0xFE, 0x00] + return [0xFE, ScanCode.KEY_MOD_LSHIFT, ScanCode.KEY_SLASH, 0x00] else: return [0xFC] From a2720149894ff36e9ae3bbd50c43626fe7a52ea3 Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:30:13 +0800 Subject: [PATCH 05/11] implement usb run script function --- fw/Core/Hitcon/Logic/UsbLogic.cc | 20 ++++++++++++++++---- fw/Core/Hitcon/Logic/UsbLogic.h | 7 ++++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/fw/Core/Hitcon/Logic/UsbLogic.cc b/fw/Core/Hitcon/Logic/UsbLogic.cc index 8771e624..e12d1094 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.cc +++ b/fw/Core/Hitcon/Logic/UsbLogic.cc @@ -83,21 +83,31 @@ void UsbLogic::OnDataRecv(uint8_t* data) { void UsbLogic::RunScript() { _index = -1; keyboard_report = {0, 0, 0, 0, 0, 0, 0, 0}; + empty_report = {0, 0, 0, 0, 0, 0, 0, 0}; scheduler.EnablePeriodic(&_routine_task); + flag = false; } -// run every 10ms +// run every 20ms void UsbLogic::Routine(void* unused) { static uint8_t delay_count = 0; + + if (flag) { + flag = false; + + if (keyboard_report.modifier == 0) + USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, + reinterpret_cast(&empty_report), 8); + return; + } if (delay_count != 0) { delay_count--; return; - } else if (_index == *reinterpret_cast(SCRIPT_BEGIN_ADDR - - 2)) { // finish script + } else if (_index == *reinterpret_cast(SCRIPT_BEGIN_ADDR - 2)) { + // TODO: check behavior when finish script scheduler.DisablePeriodic(&_routine_task); return; } - if (_index == -1) { // new script begin delay_count = 0; } else { @@ -121,6 +131,8 @@ void UsbLogic::Routine(void* unused) { } USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, reinterpret_cast(&keyboard_report), 8); + flag = true; + delay_count++; } _index++; } diff --git a/fw/Core/Hitcon/Logic/UsbLogic.h b/fw/Core/Hitcon/Logic/UsbLogic.h index d9a8bc70..e2b9862c 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.h +++ b/fw/Core/Hitcon/Logic/UsbLogic.h @@ -24,7 +24,7 @@ struct { uint8_t modifier; uint8_t reserved; uint8_t keycode[6]; -} keyboard_report; +} keyboard_report, empty_report; enum usb_state_t { USB_STATE_HEADER = 0, @@ -43,12 +43,13 @@ enum { // script code definition class UsbLogic { private: - // run routine task every 10 ms - static constexpr unsigned DELAY_INTERVAL = 10; + // run routine task every 20 ms + static constexpr unsigned DELAY_INTERVAL = 20; usb_state_t _state; int32_t _index; unsigned char _name[NAME_LEN]; // TODO: remove this + bool flag; hitcon::service::sched::PeriodicTask _routine_task; void Routine(void* unused); From 2664fe00842881f10df716db6714e15ac8e72483 Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:07:23 +0800 Subject: [PATCH 06/11] fix set_name --- fw/Core/Hitcon/Logic/UsbLogic.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/fw/Core/Hitcon/Logic/UsbLogic.cc b/fw/Core/Hitcon/Logic/UsbLogic.cc index e12d1094..602437d1 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.cc +++ b/fw/Core/Hitcon/Logic/UsbLogic.cc @@ -25,8 +25,8 @@ void UsbLogic::Init() { * 1. check recv have buffer? or set * 2. get recv data length * 3. implement write script on flash - * 4. test run script - * 5. fix set_name + * 4. (done) test run script + * 5. (done) fix set_name */ void UsbLogic::OnDataRecv(uint8_t* data) { // check length?, call this function at outevent @@ -46,15 +46,13 @@ void UsbLogic::OnDataRecv(uint8_t* data) { uint32_t error; switch (_state) { case USB_STATE_SET_NAME: - if (_index == NAME_LEN) { - // g_nv_storage.MarkDirty(); - show_name_app.SetName(reinterpret_cast(_name)); - _state = USB_STATE_HEADER; - } for (size_t i = (_index == 0); i < RECV_BUF_LEN; i++, _index++) { - // content.name[_index] = data[i]; - _name[_index] = data[i]; - // TODO: maybe need a temp buffer? + content.name[_index] = data[i]; + if (_index - 1 == NAME_LEN) { + show_name_app.SetName(reinterpret_cast(content.name)); + _state = USB_STATE_HEADER; + break; + } } break; case USB_STATE_CLEAR: From c8a4dd10133db838d03e3aa9634bbb0b1a92b89c Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Sun, 11 Aug 2024 22:30:19 +0800 Subject: [PATCH 07/11] reserve flash page 0 for badusb script --- fw/Core/Hitcon/Logic/NvStorage.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fw/Core/Hitcon/Logic/NvStorage.cc b/fw/Core/Hitcon/Logic/NvStorage.cc index 0add0aaa..9e9db65c 100644 --- a/fw/Core/Hitcon/Logic/NvStorage.cc +++ b/fw/Core/Hitcon/Logic/NvStorage.cc @@ -23,7 +23,7 @@ NvStorage::NvStorage() void NvStorage::Init() { int32_t newest_version = -1; my_assert(!g_flash_service.IsBusy()); - for (size_t i = 0; i < FLASH_PAGE_COUNT; i++) { + for (size_t i = 1; i < FLASH_PAGE_COUNT; i++) { uint8_t* page_data = reinterpret_cast(g_flash_service.GetPagePointer(i)); nv_storage_content* page_content = @@ -64,6 +64,8 @@ void NvStorage::ForceFlushInternal() { storage_dirty_ = false; next_available_page = (next_available_page + 1) % FLASH_PAGE_COUNT; // Increment for the next write + if(next_available_page == 0) + next_available_page = 1; content_.version++; last_flush_cycle = current_cycle; // Record the current cycle } From b654d818e146a3c54a0056d94fcbd5ac92fcb773 Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Tue, 13 Aug 2024 15:21:57 +0800 Subject: [PATCH 08/11] implement write script on flash --- fw/Core/Hitcon/App/MainMenuApp.h | 3 +- fw/Core/Hitcon/Hitcon.cpp | 2 +- fw/Core/Hitcon/Logic/NvStorage.cc | 3 +- fw/Core/Hitcon/Logic/UsbLogic.cc | 115 ++++++++++++++++++++---------- fw/Core/Hitcon/Logic/UsbLogic.h | 29 +++++--- 5 files changed, 98 insertions(+), 54 deletions(-) diff --git a/fw/Core/Hitcon/App/MainMenuApp.h b/fw/Core/Hitcon/App/MainMenuApp.h index b7beaa3a..e91b0ec5 100644 --- a/fw/Core/Hitcon/App/MainMenuApp.h +++ b/fw/Core/Hitcon/App/MainMenuApp.h @@ -3,6 +3,7 @@ #include #include #include +#include #include "MenuApp.h" @@ -14,7 +15,7 @@ using hitcon::app::tetris::tetris_app; constexpr menu_entry_t main_menu_entries[] = { // TODO : change app - {"BadUSB", nullptr, nullptr}, + {"BadUSB", nullptr, &hitcon::usb::RunScriptWrapper}, {"Snake", &snake_app, &hitcon::app::snake::SetSingleplayer}, {"Dino", &dino_app, nullptr}, {"Tetris", &tetris_app, &hitcon::app::tetris::SetSingleplayer}, diff --git a/fw/Core/Hitcon/Hitcon.cpp b/fw/Core/Hitcon/Hitcon.cpp index ccfbd522..18ca0eca 100644 --- a/fw/Core/Hitcon/Hitcon.cpp +++ b/fw/Core/Hitcon/Hitcon.cpp @@ -77,8 +77,8 @@ void hitcon_run() { hitcon::ir::irController.Init(); hitcon::app::snake::snake_app.Init(); hitcon::app::dino::dino_app.Init(); - g_usb_logic.Init(); g_xboard_game_controller.Init(); + hitcon::usb::g_usb_logic.Init(); // run hardware test mode if MODE/SETTINGS Button is pressed during // initializing diff --git a/fw/Core/Hitcon/Logic/NvStorage.cc b/fw/Core/Hitcon/Logic/NvStorage.cc index 9e9db65c..47a06c4a 100644 --- a/fw/Core/Hitcon/Logic/NvStorage.cc +++ b/fw/Core/Hitcon/Logic/NvStorage.cc @@ -64,8 +64,7 @@ void NvStorage::ForceFlushInternal() { storage_dirty_ = false; next_available_page = (next_available_page + 1) % FLASH_PAGE_COUNT; // Increment for the next write - if(next_available_page == 0) - next_available_page = 1; + if (next_available_page == 0) next_available_page = 1; content_.version++; last_flush_cycle = current_cycle; // Record the current cycle } diff --git a/fw/Core/Hitcon/Logic/UsbLogic.cc b/fw/Core/Hitcon/Logic/UsbLogic.cc index 602437d1..4481d727 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.cc +++ b/fw/Core/Hitcon/Logic/UsbLogic.cc @@ -1,35 +1,49 @@ #include #include #include +#include #include #include #include #include using namespace hitcon::service::sched; -// TODO: check name length + +/* TODO: + * 1. check name length + * 2. add usb on connect + * 3. add run script progress (XX%) + * 4. add hack api + */ namespace hitcon { +namespace usb { + UsbLogic g_usb_logic; UsbLogic::UsbLogic() - : _routine_task(810, (task_callback_t)&UsbLogic::Routine, (void*)this, - DELAY_INTERVAL) {} + : on_recv_task(823, (task_callback_t)&UsbLogic::OnDataRecv, this), + _routine_task(810, (task_callback_t)&UsbLogic::Routine, (void*)this, + DELAY_INTERVAL), + _write_routine_task(810, (task_callback_t)&UsbLogic::WriteRoutine, + (void*)this, WAIT_INTERVAL) {} void UsbLogic::Init() { _state = USB_STATE_HEADER; _index = 0; scheduler.Queue(&_routine_task, nullptr); + scheduler.Queue(&_write_routine_task, nullptr); } -/* TODO: - * 1. check recv have buffer? or set - * 2. get recv data length - * 3. implement write script on flash - * 4. (done) test run script - * 5. (done) fix set_name - */ -void UsbLogic::OnDataRecv(uint8_t* data) { - // check length?, call this function at outevent + +void UsbLogic::OnDataRecv(void* arg) { + uint8_t* data = reinterpret_cast(arg); + static size_t counter = 0; + counter++; + if (_state == USB_STATE_ERASE) return; // erase not finish + for (uint8_t i = 0; i < RECV_BUF_LEN; i++) { + _temp[i] = data[i]; + } + if (_state == USB_STATE_HEADER) { if (data[0]) { _state = static_cast(data[0]); @@ -37,47 +51,69 @@ void UsbLogic::OnDataRecv(uint8_t* data) { } } nv_storage_content& content = g_nv_storage.GetCurrentStorage(); - - FLASH_EraseInitTypeDef erase_struct = { - .TypeErase = FLASH_TYPEERASE_PAGES, - .PageAddress = SCRIPT_BEGIN_ADDR, - .NbPages = MY_FLASH_PAGE_SIZE / FLASH_PAGE_SIZE, - }; - uint32_t error; switch (_state) { case USB_STATE_SET_NAME: for (size_t i = (_index == 0); i < RECV_BUF_LEN; i++, _index++) { content.name[_index] = data[i]; - if (_index - 1 == NAME_LEN) { + if (_index - 1 == hitcon::ShowNameApp::NAME_LEN) { show_name_app.SetName(reinterpret_cast(content.name)); _state = USB_STATE_HEADER; break; } } break; - case USB_STATE_CLEAR: - HAL_FLASH_Unlock(); - HAL_FLASHEx_Erase(&erase_struct, &error); - HAL_FLASH_Lock(); - if (error != 0xFFFFFFFF) { - // TODO: error erase flash - return; - } - _state = USB_STATE_HEADER; + case USB_STATE_ERASE: + g_flash_service.ErasePage(SCRIPT_FLASH_INDEX); // TODO: check is busy + scheduler.EnablePeriodic(&_write_routine_task); break; case USB_STATE_START_WRITE: - // TODO: use flash service to program page // TODO: add checksum - - break; - case USB_STATE_STOP_WRITE: - _state = USB_STATE_HEADER; + _script_len = (data[1] << 8) | data[2]; + memcpy(_temp, data, RECV_BUF_LEN); + _state = USB_STATE_WRITING; + _new_data = true; + scheduler.EnablePeriodic(&_write_routine_task); + case USB_STATE_WRITING: + // it seems like first byte of data cannot be 0 so use 0xFC instead + if (data[0] == 0xFC) data[0] = 0; + memcpy(_temp, data, RECV_BUF_LEN); + _new_data = true; break; default: break; } } +void UsbLogic::WriteRoutine(void* unused) { + if (_state == USB_STATE_ERASE) { + if (!g_flash_service.IsBusy()) { + _state = USB_STATE_HEADER; + scheduler.DisablePeriodic(&_write_routine_task); + keyboard_report = {0, 0, 0xFF, 0, 0, 0, 0, 0}; + USBD_CUSTOM_HID_SendReport( + &hUsbDeviceFS, reinterpret_cast(&keyboard_report), 8); + } + } else if (_state == USB_STATE_WRITING) { + if (!g_flash_service.IsBusy() && _new_data) { + keyboard_report = {0, 0, 0xFF, 0, 0, 0, 0, 0}; + USBD_CUSTOM_HID_SendReport( + &hUsbDeviceFS, reinterpret_cast(&keyboard_report), 8); + g_flash_service.ProgramOnly(SCRIPT_FLASH_INDEX, _index, + reinterpret_cast(_temp), 8); + _index += 8; + _new_data = false; + if (_index >= _script_len + 8) { + _state = USB_STATE_HEADER; + scheduler.DisablePeriodic(&_write_routine_task); + } + } + } +} + +void RunScriptWrapper() { + g_usb_logic.RunScript(); +} + void UsbLogic::RunScript() { _index = -1; keyboard_report = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -89,7 +125,8 @@ void UsbLogic::RunScript() { // run every 20ms void UsbLogic::Routine(void* unused) { static uint8_t delay_count = 0; - + uint16_t len = (*(uint8_t*)(SCRIPT_BEGIN_ADDR - 2) << 8) | + *(uint8_t*)(SCRIPT_BEGIN_ADDR - 1); if (flag) { flag = false; @@ -101,7 +138,7 @@ void UsbLogic::Routine(void* unused) { if (delay_count != 0) { delay_count--; return; - } else if (_index == *reinterpret_cast(SCRIPT_BEGIN_ADDR - 2)) { + } else if (_index == len) { // TODO: check behavior when finish script scheduler.DisablePeriodic(&_routine_task); return; @@ -134,10 +171,10 @@ void UsbLogic::Routine(void* unused) { } _index++; } - +} // namespace usb } // namespace hitcon void UsbServiceOnDataReceived(uint8_t* data) { - hitcon::g_usb_logic.OnDataRecv(data); - // TODO: queue task + scheduler.Queue(&hitcon::usb::g_usb_logic.on_recv_task, + reinterpret_cast(data)); } diff --git a/fw/Core/Hitcon/Logic/UsbLogic.h b/fw/Core/Hitcon/Logic/UsbLogic.h index e2b9862c..b0b7f5c5 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.h +++ b/fw/Core/Hitcon/Logic/UsbLogic.h @@ -10,15 +10,14 @@ void UsbServiceOnDataReceived(uint8_t* data); } namespace hitcon { -// TODO: change to logic +namespace usb { constexpr unsigned RECV_BUF_LEN = 8; // first 2 bytes is script length constexpr unsigned SCRIPT_BEGIN_ADDR = - (FLASH_END_ADDR - MY_FLASH_PAGE_SIZE + 1) + 2; + FLASH_END_ADDR - FLASH_PAGE_COUNT * MY_FLASH_PAGE_SIZE + 1 + 3; +constexpr unsigned SCRIPT_FLASH_INDEX = 0; -// TODO: partial program -// TODO: change to last page from flash service -constexpr unsigned NAME_LEN = 16; +void RunScriptWrapper(); struct { uint8_t modifier; @@ -27,17 +26,18 @@ struct { } keyboard_report, empty_report; enum usb_state_t { - USB_STATE_HEADER = 0, + USB_STATE_HEADER = 0, // idle USB_STATE_SET_NAME = 1, - USB_STATE_CLEAR, + USB_STATE_ERASE, USB_STATE_START_WRITE, - USB_STATE_STOP_WRITE, + USB_STATE_READ_MEM, + USB_STATE_WRITING, + USB_STATE_WAITING // waiting for flash service done }; enum { // script code definition CODE_DELAY = 0xFF, CODE_MODIFIER = 0xFE, - CODE_FINISH = 0xFD, CODE_RELEASE = 0x00 }; @@ -45,23 +45,30 @@ class UsbLogic { private: // run routine task every 20 ms static constexpr unsigned DELAY_INTERVAL = 20; + static constexpr unsigned WAIT_INTERVAL = 10; usb_state_t _state; int32_t _index; - unsigned char _name[NAME_LEN]; // TODO: remove this + uint16_t _script_len; bool flag; + bool _new_data; hitcon::service::sched::PeriodicTask _routine_task; + hitcon::service::sched::PeriodicTask _write_routine_task; void Routine(void* unused); + void WriteRoutine(void* unused); + uint8_t _temp[RECV_BUF_LEN]; public: + hitcon::service::sched::Task on_recv_task; UsbLogic(); - void OnDataRecv(uint8_t* data); + void OnDataRecv(void* arg); void RunScript(); // TODO: check connection status void Init(); }; extern UsbLogic g_usb_logic; +} // namespace usb } // namespace hitcon #endif From 95c88cbb4b2e021d3e872d04f6894ba6d949f83b Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Wed, 14 Aug 2024 00:54:53 +0800 Subject: [PATCH 09/11] add progress text when running script --- fw/Core/Hitcon/App/BadUsbApp.cc | 23 +++++++++++++++++++++++ fw/Core/Hitcon/App/BadUsbApp.h | 26 ++++++++++++++++++++++++++ fw/Core/Hitcon/App/MainMenuApp.h | 4 ++-- fw/Core/Hitcon/Logic/UsbLogic.cc | 18 +++++++++++------- fw/Core/Hitcon/Logic/UsbLogic.h | 6 +++++- 5 files changed, 67 insertions(+), 10 deletions(-) create mode 100644 fw/Core/Hitcon/App/BadUsbApp.cc create mode 100644 fw/Core/Hitcon/App/BadUsbApp.h diff --git a/fw/Core/Hitcon/App/BadUsbApp.cc b/fw/Core/Hitcon/App/BadUsbApp.cc new file mode 100644 index 00000000..e94bb7a3 --- /dev/null +++ b/fw/Core/Hitcon/App/BadUsbApp.cc @@ -0,0 +1,23 @@ +#include +#include +#include + +namespace hitcon { +namespace usb { +BadUsbApp bad_usb_app; + +BadUsbApp::BadUsbApp() {} + +void BadUsbApp::OnEntry() { + g_usb_logic.RunScript((callback_t)&BadUsbApp::OnScriptFinished, this); +} + +void BadUsbApp::OnExit() { g_usb_logic.StopScript(); } + +void BadUsbApp::OnButton(button_t button) {} + +void BadUsbApp::OnScriptFinished(void *unsed) { + badge_controller.OnAppEnd(this); +} +} // namespace usb +} // namespace hitcon \ No newline at end of file diff --git a/fw/Core/Hitcon/App/BadUsbApp.h b/fw/Core/Hitcon/App/BadUsbApp.h new file mode 100644 index 00000000..2b4bb6bf --- /dev/null +++ b/fw/Core/Hitcon/App/BadUsbApp.h @@ -0,0 +1,26 @@ +#ifndef BAD_USB_APP_H +#define BAD_USB_APP_H + +#include + +namespace hitcon { +namespace usb { + +class BadUsbApp : public App { + private: + void OnScriptFinished(void* unused); + + public: + BadUsbApp(); + virtual ~BadUsbApp() = default; + + void OnEntry() override; + void OnExit() override; + void OnButton(button_t button) override; +}; + +extern BadUsbApp bad_usb_app; +} // namespace usb +} // namespace hitcon + +#endif \ No newline at end of file diff --git a/fw/Core/Hitcon/App/MainMenuApp.h b/fw/Core/Hitcon/App/MainMenuApp.h index e91b0ec5..76ea893c 100644 --- a/fw/Core/Hitcon/App/MainMenuApp.h +++ b/fw/Core/Hitcon/App/MainMenuApp.h @@ -1,9 +1,9 @@ +#include #include #include #include #include #include -#include #include "MenuApp.h" @@ -15,7 +15,7 @@ using hitcon::app::tetris::tetris_app; constexpr menu_entry_t main_menu_entries[] = { // TODO : change app - {"BadUSB", nullptr, &hitcon::usb::RunScriptWrapper}, + {"BadUSB", &hitcon::usb::bad_usb_app, nullptr}, {"Snake", &snake_app, &hitcon::app::snake::SetSingleplayer}, {"Dino", &dino_app, nullptr}, {"Tetris", &tetris_app, &hitcon::app::tetris::SetSingleplayer}, diff --git a/fw/Core/Hitcon/Logic/UsbLogic.cc b/fw/Core/Hitcon/Logic/UsbLogic.cc index 4481d727..ceb5f7da 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.cc +++ b/fw/Core/Hitcon/Logic/UsbLogic.cc @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -110,11 +109,9 @@ void UsbLogic::WriteRoutine(void* unused) { } } -void RunScriptWrapper() { - g_usb_logic.RunScript(); -} - -void UsbLogic::RunScript() { +void UsbLogic::RunScript(callback_t cb, void* arg1) { + _on_finish_cb = cb; + _on_finish_arg1 = arg1; _index = -1; keyboard_report = {0, 0, 0, 0, 0, 0, 0, 0}; empty_report = {0, 0, 0, 0, 0, 0, 0, 0}; @@ -122,6 +119,8 @@ void UsbLogic::RunScript() { flag = false; } +void UsbLogic::StopScript() { scheduler.DisablePeriodic(&_routine_task); } + // run every 20ms void UsbLogic::Routine(void* unused) { static uint8_t delay_count = 0; @@ -139,13 +138,18 @@ void UsbLogic::Routine(void* unused) { delay_count--; return; } else if (_index == len) { - // TODO: check behavior when finish script scheduler.DisablePeriodic(&_routine_task); + _on_finish_cb(_on_finish_arg1, nullptr); return; } if (_index == -1) { // new script begin delay_count = 0; } else { + uint8_t progress = _index * 100 / len; + char str[4] = "XX%"; + str[0] = progress / 10 + '0'; + str[1] = progress % 10 + '0'; + display_set_mode_text((str)); uint8_t* addr = reinterpret_cast(SCRIPT_BEGIN_ADDR + _index); switch (*addr) { case CODE_DELAY: diff --git a/fw/Core/Hitcon/Logic/UsbLogic.h b/fw/Core/Hitcon/Logic/UsbLogic.h index b0b7f5c5..91672c66 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.h +++ b/fw/Core/Hitcon/Logic/UsbLogic.h @@ -57,12 +57,16 @@ class UsbLogic { void Routine(void* unused); void WriteRoutine(void* unused); uint8_t _temp[RECV_BUF_LEN]; + callback_t _on_finish_cb; + void* _on_finish_arg1; public: hitcon::service::sched::Task on_recv_task; UsbLogic(); void OnDataRecv(void* arg); - void RunScript(); // TODO: check connection status + // TODO: check connection status + void RunScript(callback_t _on_finish_cb, void* on_finish_arg1); + void StopScript(); void Init(); }; From ea59d0bf02bf56551bf51ff2ce43065aba1594b7 Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Sat, 17 Aug 2024 15:01:11 +0800 Subject: [PATCH 10/11] add IsEnabled() for PeriodicTask --- fw/Core/Hitcon/Service/Sched/PeriodicTask.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fw/Core/Hitcon/Service/Sched/PeriodicTask.h b/fw/Core/Hitcon/Service/Sched/PeriodicTask.h index 5f640ae7..6633977a 100644 --- a/fw/Core/Hitcon/Service/Sched/PeriodicTask.h +++ b/fw/Core/Hitcon/Service/Sched/PeriodicTask.h @@ -34,6 +34,7 @@ class PeriodicTask : public DelayedTask { virtual ~PeriodicTask(); void Enable(); void Disable(); + bool IsEnabled() { return enabled; } }; } /* namespace sched */ From 008657fbb2a47be065ef02cdac6b5237fa35ab66 Mon Sep 17 00:00:00 2001 From: Lance798 <32232417+Lance798@users.noreply.github.com> Date: Sat, 17 Aug 2024 15:01:32 +0800 Subject: [PATCH 11/11] fix bug when exit badusb app --- fw/Core/Hitcon/App/BadUsbApp.cc | 10 ++++++++-- fw/Core/Hitcon/Logic/UsbLogic.cc | 9 ++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/fw/Core/Hitcon/App/BadUsbApp.cc b/fw/Core/Hitcon/App/BadUsbApp.cc index e94bb7a3..798546c8 100644 --- a/fw/Core/Hitcon/App/BadUsbApp.cc +++ b/fw/Core/Hitcon/App/BadUsbApp.cc @@ -14,10 +14,16 @@ void BadUsbApp::OnEntry() { void BadUsbApp::OnExit() { g_usb_logic.StopScript(); } -void BadUsbApp::OnButton(button_t button) {} +void BadUsbApp::OnButton(button_t button) { + switch (button & BUTTON_VALUE_MASK) { + case BUTTON_BACK: + badge_controller.OnAppEnd(this); + break; + } +} void BadUsbApp::OnScriptFinished(void *unsed) { badge_controller.OnAppEnd(this); } } // namespace usb -} // namespace hitcon \ No newline at end of file +} // namespace hitcon diff --git a/fw/Core/Hitcon/Logic/UsbLogic.cc b/fw/Core/Hitcon/Logic/UsbLogic.cc index ceb5f7da..6269d0ff 100644 --- a/fw/Core/Hitcon/Logic/UsbLogic.cc +++ b/fw/Core/Hitcon/Logic/UsbLogic.cc @@ -119,7 +119,14 @@ void UsbLogic::RunScript(callback_t cb, void* arg1) { flag = false; } -void UsbLogic::StopScript() { scheduler.DisablePeriodic(&_routine_task); } +void UsbLogic::StopScript() { + if (_routine_task.IsEnabled()) scheduler.DisablePeriodic(&_routine_task); + if (_write_routine_task.IsEnabled()) + scheduler.DisablePeriodic(&_write_routine_task); + + USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, + reinterpret_cast(&empty_report), 8); +} // run every 20ms void UsbLogic::Routine(void* unused) {