"""This code, designed to run on an Adafruit Neo Trinkey, sends a password to the connected system as if it was a keyboard.""" import os import sys import time import board import touchio import usb_hid import neopixel import storage from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS #from adafruit_hid.keycode import Keycode def isdir(possible_dir): """Returns whether possible_dir is a directory or not, as os.path.* is not currently available in micropython.""" try: _ = os.listdir(possible_dir) return True except OSError: return False def obj_exists(possible_object): """Returns whether possible_object exists in the filesystem or not, as os.path.* is not currently available in micropython. Does not distinguish between directories and files. """ try: os.stat(possible_object) return True except OSError: return False def get_keypress(k1, k2): """Waits for a key to be pressed, then returns which one(s) were pressed and the total time from first press to last release (in 10ths of a second).""" t1press = False t2press = False timecycles = 0 while (not t1press) and (not t2press): while (k1.value ^ key_invert) or (k2.value ^ key_invert): oldt1 = t1press oldt2 = t2press t1press = t1press or (k1.value ^ key_invert) t2press = t2press or (k2.value ^ key_invert) if oldt1 != t1press or oldt2 != t2press: if t1press and t2press: set_neo(pixels, [1, 2], color_keypress, False) elif t1press: set_neo(pixels, [2], color_keypress, False) elif t2press: set_neo(pixels, [1], color_keypress, False) time.sleep(0.1) timecycles += 1 set_neo(pixels, default_pixels, default_color, True) return t1press, t2press, timecycles def load_file_into_string(filename): """Reads the entire contents of a file into the returned string. First returned object is string form, second is raw bytes.""" file_string = None raw_bytes = None if obj_exists(filename) and not isdir(filename): with open(filename, 'rb') as read_h: raw_bytes = read_h.read() file_string = str(raw_bytes, 'ascii') return file_string, raw_bytes def load_raw_keyfile(passfile_dir, key_filename): """Load the contents of the requested key.""" content = None filename = passfile_dir + key_filename if obj_exists(filename) and not isdir(filename): content, _ = load_file_into_string(filename) else: print("Unable to locate " + filename) return content # # # # if xform_key[s_index % len(xform_key)]: # output_text = output_text + str(9 - int(orig_char)) def flash_neo(pixel_h, which_ones, color, how_long): """Flash all neopixels in the which_ones list to a given color for the given time.""" for pix in which_ones: pixel_h[pix] = color pixel_h.brightness = neo_brightness pixel_h.show() time.sleep(how_long) set_neo(pixel_h, default_pixels, default_color, True) def set_neo(pixel_h, which_ones, color, clean_slate): """Set all neopixels in the which_ones list to a given color.""" for pix in range(0, 4): if pix in which_ones: pixel_h[pix] = color elif clean_slate: pixel_h[pix] = color_blank pixel_h.brightness = neo_brightness pixel_h.show() num_to_neo = [ [], [0], [1], [0,1], [2], [0,2], [1,2], [0,1,2], [3], [0,3], [1,3], [0,1,3], [2,3], [0,2,3], [1,2,3], [0,1,2,3] ] red = (32, 0, 0) green = (0, 32, 0) blue = (0, 0, 32) cyan = (0, 32, 32) purple = (32, 0, 32) yellow = (32, 32, 0) white = (32, 32, 32) black = (0, 0, 0) zero_pads = '0000' seconds_to_erase = 7 max_unlock_failures = 7 neo_brightness = 0.2 color_keynum = green color_wakeup = blue color_keypress = purple color_blank = black color_unlock_mode = yellow color_error = red if os.uname().machine == 'Adafruit NeoPixel Trinkey M0 with samd21e18': key_invert = False pixels = neopixel.NeoPixel(board.NEOPIXEL, 4, brightness=neo_brightness, auto_write=False) keyboard = Keyboard(usb_hid.devices) keyboard_layout = KeyboardLayoutUS(keyboard) touch1 = touchio.TouchIn(board.TOUCH1) touch2 = touchio.TouchIn(board.TOUCH2) else: print("I don't know how to run on this platform: " + os.uname().machine) print("Here are its hardware features: " + str(dir(board))) sys.exit(1) selected_keynum = 0 unlock_entry_mode = False unlock_code = "" unlock_failures = 0 default_color = color_keynum if obj_exists('/sd/') and isdir('/sd/'): data_dir = '/sd/' else: data_dir = '/' pw_subdir = '' default_pixels = [] for led in [0, 1, 2, 3]: flash_neo(pixels, [led], color_wakeup, 1) while True: (t1, t2, cycles) = get_keypress(touch1, touch2) if t1 and t2: if cycles >= (seconds_to_erase * 10): storage.erase_filesystem() # elif unlock_entry_mode: default_color = color_keynum default_pixels = num_to_neo[selected_keynum % 16] if not obj_exists(data_dir + unlock_code) or not isdir(data_dir + unlock_code): unlock_failures += 1 if unlock_failures > max_unlock_failures: storage.erase_filesystem() elif obj_exists(data_dir + unlock_code) and isdir(data_dir + unlock_code): pw_subdir = unlock_code + '/' selected_keynum = 0 default_pixels = num_to_neo[selected_keynum % 16] if unlock_code: unlock_failures = 0 else: default_color = color_unlock_mode default_pixels = [0,3] unlock_code = "" set_neo(pixels, default_pixels, default_color, True) unlock_entry_mode = unlock_entry_mode ^ True elif t1: if unlock_entry_mode: unlock_code = unlock_code + '1' else: if selected_keynum == 9999: selected_keynum = 0 elif obj_exists(data_dir + pw_subdir + (zero_pads + str(selected_keynum + 1))[-4:] + '.txt'): selected_keynum += 1 else: selected_keynum = 0 default_pixels = num_to_neo[selected_keynum % 16] set_neo(pixels, default_pixels, color_keynum, True) elif t2: if unlock_entry_mode: unlock_code = unlock_code + '2' else: target_string = load_raw_keyfile(data_dir + pw_subdir, (zero_pads + str(selected_keynum))[-4:] + '.txt') if target_string: keyboard_layout.write(target_string)