├── image.jpg ├── src ├── Enums │ ├── ContextEnum.h │ ├── IconEnum.h │ ├── KeyboardLayoutEnum.h │ └── ActionEnum.h ├── Inputs │ ├── IInput.h │ ├── InputKeys.h │ ├── CardputerInput.h │ └── CardputerInput.cpp ├── Services │ ├── LedService.h │ ├── LedService.cpp │ ├── UsbService.h │ ├── NvsService.h │ ├── CategoryService.h │ ├── EntryService.h │ ├── NvsService.cpp │ ├── CryptoService.h │ ├── UsbService.cpp │ ├── CategoryService.cpp │ ├── SdService.h │ └── EntryService.cpp ├── Selectors │ ├── ConfirmationSelector.h │ ├── FieldActionSelector.h │ ├── ConfirmationSelector.cpp │ ├── FieldEditorSelector.h │ ├── HorizontalSelector.h │ ├── StringPromptSelector.h │ ├── FieldActionSelectior.cpp │ ├── VerticalSelector.h │ ├── StringPromptSelector.cpp │ ├── HorizontalSelector.cpp │ ├── FieldEditorSelector.cpp │ └── VerticalSelector.cpp ├── Transformers │ ├── TimeTransformer.h │ ├── JsonTransformer.h │ ├── ModelTransformer.h │ ├── ModelTransformer.cpp │ └── TimeTransformer.cpp ├── Repositories │ ├── CategoryRepository.h │ ├── EntryRepository.h │ ├── CategoryRepository.cpp │ └── EntryRepository.cpp ├── main.cpp ├── Dispatchers │ ├── ActionDispatcher.h │ └── ActionDispatcher.cpp ├── Models │ ├── Field.h │ ├── Category.h │ ├── VaultFile.h │ └── Entry.h ├── Views │ ├── IView.h │ └── CardputerView.h ├── Controllers │ ├── UtilityController.h │ ├── VaultController.h │ └── EntryController.h ├── Managers │ └── InactivityManager.h └── Providers │ ├── DependencyProvider.h │ └── DependencyProvider.cpp ├── test ├── Inputs │ └── MockInput.h ├── Enums │ ├── TestKeyboardLayoutEnumMapper.cpp │ ├── TestActionEnumMapper.cpp │ ├── TestIconEnumMapper.cpp │ └── TestBaseColorEnumMapper.cpp ├── Services │ ├── TestNvsService.cpp │ ├── TestCategoryService.cpp │ ├── TestEntryService.cpp │ ├── TestCryptoService.cpp │ └── TestSdService.cpp ├── Selectors │ ├── TestConfirmationSelector.cpp │ ├── TestStringPromptSelector.cpp │ ├── TestHorizontalSelector.cpp │ ├── TestFieldActionSelector.cpp │ ├── TestVerticalSelector.cpp │ └── TestFieldEditorSelector.cpp ├── Transformers │ ├── TestTimeTransformer.cpp │ ├── TestModelTransformer.cpp │ └── TestJsonTransformer.cpp ├── Controllers │ └── TestUtilityController.cpp ├── Views │ └── MockView.h └── main.cpp ├── LICENSE ├── platformio.ini ├── lib └── USBHIDKeyboard │ ├── Keyboard_sv_SE.h │ ├── Keyboard_da_DK.h │ ├── Keyboard_it_IT.h │ ├── Keyboard_pt_PT.h │ ├── Keyboard_pt_PT-BR.h │ ├── Keyboard_de_DE.h │ ├── Keyboard_fr_FR.h │ ├── Keyboard_es_ES.h │ ├── Keyboard_hu_HU.h │ ├── USBHID.h │ ├── KeyboardLayout.h │ ├── Keyboard_en_UK.h │ ├── KeyboardLayout_en_US.cpp │ ├── KeyboardLayout_fr_FR.cpp │ ├── KeyboardLayout_en_UK.cpp │ ├── KeyboardLayout_hu_HU.cpp │ ├── KeyboardLayout_de_DE.cpp │ ├── KeyboardLayout_it_IT.cpp │ ├── KeyboardLayout_da_DK.cpp │ ├── KeyboardLayout_es_ES.cpp │ ├── KeyboardLayout_sv_SE.cpp │ ├── KeyboardLayout_pt_PT.cpp │ ├── KeyboardLayout_pt_PT-BR.cpp │ └── USBHIDKeyboard.h └── README.md /image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geo-tp/Password-Manager/HEAD/image.jpg -------------------------------------------------------------------------------- /src/Enums/ContextEnum.h: -------------------------------------------------------------------------------- 1 | #ifndef STATE_ENUM_H 2 | #define STATE_ENUM_H 3 | 4 | enum class ContextEnum { 5 | NoVault, 6 | VaultSelected, 7 | VaultLoaded, 8 | EntrySelected, 9 | FieldSelected, 10 | }; 11 | 12 | #endif // STATE_ENUM_H 13 | -------------------------------------------------------------------------------- /src/Inputs/IInput.h: -------------------------------------------------------------------------------- 1 | #ifndef I_INPUT_H 2 | #define I_INPUT_H 3 | 4 | #include "InputKeys.h" 5 | 6 | class IInput { 7 | public: 8 | virtual ~IInput() = default; 9 | virtual char handler() = 0; 10 | virtual void waitPress() = 0; 11 | }; 12 | 13 | #endif // I_INPUT_H 14 | -------------------------------------------------------------------------------- /src/Inputs/InputKeys.h: -------------------------------------------------------------------------------- 1 | #ifndef INPUT_KEYS_H 2 | #define INPUT_KEYS_H 3 | 4 | #define KEY_OK '\n' 5 | #define KEY_DEL '\b' 6 | #define KEY_ESC_CUSTOM '`' 7 | #define KEY_NONE '\0' 8 | #define KEY_RETURN_CUSTOM '\r' 9 | #define KEY_ARROW_UP ';' 10 | #define KEY_ARROW_DOWN '.' 11 | #define KEY_ARROW_LEFT ',' 12 | #define KEY_ARROW_RIGHT '/' 13 | 14 | #endif // INPUT_KEYS_H 15 | -------------------------------------------------------------------------------- /src/Inputs/CardputerInput.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDPUTER_INPUT_H 2 | #define CARDPUTER_INPUT_H 3 | 4 | #include 5 | #include 6 | #include "IInput.h" 7 | 8 | namespace inputs { 9 | 10 | class CardputerInput : public IInput { 11 | public: 12 | char handler() override; 13 | void waitPress() override; 14 | }; 15 | 16 | } 17 | 18 | #endif // CARDPUTER_INPUT_H 19 | -------------------------------------------------------------------------------- /src/Services/LedService.h: -------------------------------------------------------------------------------- 1 | #ifndef LED_SERVICE_H 2 | #define LED_SERVICE_H 3 | 4 | #include 5 | #include 6 | 7 | #define LED_PIN 21 // Builtin, TODO: use context 8 | 9 | class LedService { 10 | public: 11 | void blink(); 12 | void showLed(); 13 | void clearLed(); 14 | 15 | private: 16 | GlobalState& globalState = GlobalState::getInstance(); 17 | CRGB leds[1]; 18 | }; 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/Services/LedService.cpp: -------------------------------------------------------------------------------- 1 | #include "LedService.h" 2 | 3 | void LedService::blink() { 4 | showLed(); 5 | delay(30); 6 | clearLed(); 7 | } 8 | 9 | void LedService::showLed() { 10 | const int ledPin = globalState.getLedPin(); // TODO: no way to pass this to FastLED atm 11 | FastLED.addLeds(leds, 1); // we use define LED_PIN Builtin for now 12 | leds[0] = CRGB::OrangeRed; 13 | FastLED.show(); 14 | } 15 | 16 | void LedService::clearLed() { 17 | FastLED.clear(true); 18 | } -------------------------------------------------------------------------------- /src/Selectors/ConfirmationSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIRMATION_SELECTOR_H 2 | #define CONFIRMATION_SELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class ConfirmationSelector { 10 | public: 11 | ConfirmationSelector(IView& display, IInput& input); 12 | bool select(const std::string& title, const std::string& description); 13 | 14 | private: 15 | IView& display; 16 | IInput& input; 17 | }; 18 | 19 | #endif // CONFIRMATION_SELECTOR_H 20 | -------------------------------------------------------------------------------- /src/Transformers/TimeTransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_TRANSFORMER_H 2 | #define TIME_TRANSFORMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class TimeTransformer { 9 | public: 10 | TimeTransformer(); 11 | 12 | std::string toLabel(uint32_t timeMs) const; 13 | uint32_t toMilliseconds(const std::string& label) const; 14 | const std::vector& getAllTimeLabels() const; 15 | const std::vector& getAllTimeValues() const; 16 | 17 | private: 18 | std::vector timeLabels; 19 | std::vector timeValues; 20 | }; 21 | 22 | #endif // TIME_TRANSFORMER_H 23 | -------------------------------------------------------------------------------- /src/Selectors/FieldActionSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef FIELDACTIONSELECTOR_H 2 | #define FIELDACTIONSELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class FieldActionSelector { 13 | public: 14 | FieldActionSelector(IView& display, IInput& input, InactivityManager& inactivityManager); 15 | 16 | ActionEnum select(const std::string& label, const std::string& value); 17 | 18 | private: 19 | IView& display; 20 | IInput& input; 21 | InactivityManager& inactivityManager; 22 | }; 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/Repositories/CategoryRepository.h: -------------------------------------------------------------------------------- 1 | #ifndef CATEGORY_REPOSITORY_H 2 | #define CATEGORY_REPOSITORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class CategoryRepository { 9 | private: 10 | std::vector categories; 11 | 12 | public: 13 | void addCategory(const Category& category); 14 | const std::vector& getAllCategories() const; 15 | void setCategories(std::vector& cats); 16 | const Category& findCategoryByIndex(size_t index) const; 17 | bool deleteCategoryByIndex(size_t index); 18 | bool updateCategory(size_t index, const Category& updatedCategory); 19 | }; 20 | 21 | #endif // CATEGORY_REPOSITORY_H 22 | -------------------------------------------------------------------------------- /src/Selectors/ConfirmationSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "ConfirmationSelector.h" 2 | 3 | ConfirmationSelector::ConfirmationSelector(IView& display, IInput& input) 4 | : display(display), input(input) {} 5 | 6 | bool ConfirmationSelector::select(const std::string& title, const std::string& description) { 7 | char key = KEY_NONE; 8 | display.topBar(title, false, false); 9 | display.confirmationPrompt(description); 10 | while (true) { 11 | key = input.handler(); 12 | if (key == KEY_OK) { 13 | return true; 14 | } 15 | if (key == KEY_ESC_CUSTOM || key == KEY_ARROW_LEFT) { 16 | return false; 17 | } 18 | delay(5); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/Inputs/MockInput.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCK_INPUT_H 2 | #define MOCK_INPUT_H 3 | 4 | #include 5 | #include "../src/Inputs/IInput.h" 6 | 7 | class MockInput : public IInput { 8 | public: 9 | MockInput() {} 10 | 11 | // Queue to mock input 12 | void enqueueKey(char key) { 13 | inputQueue.push(key); 14 | } 15 | 16 | char handler() override { 17 | if (inputQueue.empty()) { 18 | return KEY_NONE; 19 | } 20 | char key = inputQueue.front(); 21 | inputQueue.pop(); 22 | return key; 23 | } 24 | 25 | void waitPress() override {} 26 | 27 | private: 28 | std::queue inputQueue; 29 | }; 30 | 31 | #endif // MOCK_INPUT_H 32 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #ifndef UNIT_TEST 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace views; 10 | using namespace inputs; 11 | 12 | void setup() { 13 | auto cfg = M5.config(); 14 | M5Cardputer.begin(cfg, true); 15 | 16 | CardputerView display; 17 | CardputerInput input; 18 | 19 | DependencyProvider provider(display, input); 20 | provider.setup(); 21 | 22 | ActionDispatcher dispatcher(provider); 23 | dispatcher.setup(); 24 | dispatcher.run(); 25 | } 26 | 27 | void loop() { 28 | // Empty as all logic is handled in dispatcher 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/Services/UsbService.h: -------------------------------------------------------------------------------- 1 | #ifndef USBSERVICE_H 2 | #define USBSERVICE_H 3 | 4 | #include 5 | #include 6 | #include // custom from local lib 7 | #include 8 | #include 9 | 10 | class UsbService { 11 | public: 12 | UsbService(); 13 | void begin(); 14 | void end(); 15 | void sendString(const std::string& text); 16 | void sendChunkedString(const std::string& data, size_t chunkSize=128, unsigned long delayBetweenChunks=50); 17 | bool isReady() const; 18 | void setLayout(const uint8_t* newLayout); 19 | 20 | private: 21 | USBHIDKeyboard keyboard; 22 | const uint8_t* layout; 23 | bool initialized = false; 24 | uint32_t initTime; 25 | }; 26 | 27 | #endif // USBSERVICE_H 28 | -------------------------------------------------------------------------------- /src/Selectors/FieldEditorSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef FIELD_EDITOR_SELECTOR_H 2 | #define FIELD_EDITOR_SELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class FieldEditorSelector { 11 | public: 12 | FieldEditorSelector(IView& display, IInput& input); 13 | std::vector select(const std::vector& fieldNames, 14 | const std::vector& fieldValues, 15 | const std::string& title); 16 | 17 | private: 18 | IView& display; 19 | IInput& input; 20 | 21 | std::string processUserInput(const std::string& currentValue, char key); 22 | }; 23 | 24 | #endif // FIELD_EDITOR_SELECTOR_H 25 | -------------------------------------------------------------------------------- /src/Transformers/JsonTransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef JSON_TRANSFORMER_H 2 | #define JSON_TRANSFORMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | class JsonTransformer { 12 | public: 13 | std::string emptyJsonStructure(); 14 | 15 | std::string toJson(const std::vector& vault); 16 | std::vector fromJsonToEntries(const std::string& jsonContent); 17 | std::string toJson(const std::vector& categories); 18 | std::vector fromJsonToCategories(const std::string& jsonContent); 19 | std::string mergeEntriesAndCategoriesToJson(const std::vector& entries, const std::vector& categories); 20 | }; 21 | 22 | #endif // JSON_TRANSFORMER_H 23 | -------------------------------------------------------------------------------- /src/Selectors/HorizontalSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef HORIZONTAL_SELECTOR_H 2 | #define HORIZONTAL_SELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class HorizontalSelector { 12 | public: 13 | HorizontalSelector(IView& display, IInput& input, InactivityManager& inactivityManager); 14 | int select(const std::string& title, const std::vector& options, const std::string& description1="", const std::string& description2="", const std::vector& icons={}, bool handleInactivity=true); 15 | 16 | private: 17 | IView& display; 18 | IInput& input; 19 | InactivityManager& inactivityManager; 20 | }; 21 | 22 | #endif // HORIZONTAL_SELECTOR_H 23 | -------------------------------------------------------------------------------- /src/Repositories/EntryRepository.h: -------------------------------------------------------------------------------- 1 | #ifndef PASSWORD_REPOSITORY_H 2 | #define PASSWORD_REPOSITORY_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class EntryRepository { 10 | private: 11 | std::vector entries; 12 | std::string containerName; 13 | 14 | public: 15 | void addEntry(const Entry& entry); 16 | const std::vector& getAllEntries() const; 17 | void setEntries(std::vector& ents); 18 | const Entry& findEntryById(const std::string& id) const; 19 | bool deleteEntry(const Entry& entry); 20 | bool updateEntry(const Entry& oldEntry, const Entry& newEntry); 21 | 22 | void setContainerName(std::string& name); 23 | std::string getContainerName(); 24 | }; 25 | 26 | #endif // PASSWORD_REPOSITORY_H 27 | -------------------------------------------------------------------------------- /src/Transformers/ModelTransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef MODEL_TRANSFORMER_H 2 | #define MODEL_TRANSFORMER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class ModelTransformer { 11 | public: 12 | // Template 13 | template 14 | static std::vector toStrings(const std::vector& models, std::function extractor); 15 | 16 | // Surcharge pour Entry 17 | static std::vector toStrings(const std::vector& models); 18 | static std::vector toStrings(const Entry& entry); 19 | 20 | // Surcharge pour Category 21 | static std::vector toStrings(const std::vector& models); 22 | }; 23 | 24 | #endif // MODEL_TRANSFORMER_H 25 | -------------------------------------------------------------------------------- /src/Services/NvsService.h: -------------------------------------------------------------------------------- 1 | #ifndef NVS_SERVICE_H 2 | #define NVS_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include "States/GlobalState.h" 7 | 8 | class NvsService { 9 | public: 10 | NvsService(); 11 | ~NvsService(); 12 | 13 | // Read/write string 14 | void saveString(const std::string& key, const std::string& value); 15 | std::string getString(const std::string& key, const std::string& defaultValue = ""); 16 | 17 | // Read/write int 18 | void saveInt(const std::string& key, int value); 19 | int getInt(const std::string& key, int defaultValue = 0); 20 | 21 | // Utils 22 | void remove(const std::string& key); 23 | void clearNamespace(); 24 | 25 | private: 26 | Preferences preferences; 27 | GlobalState& globalState; 28 | }; 29 | 30 | #endif // NVS_SERVICE_H 31 | -------------------------------------------------------------------------------- /src/Selectors/StringPromptSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_PROMPT_SELECTOR_H 2 | #define STRING_PROMPT_SELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | class StringPromptSelector { 13 | public: 14 | StringPromptSelector(IView& display, IInput& input); 15 | 16 | std::string select(const std::string& title, const std::string& label, const std::string& value = "", bool backButton = true, bool maxInput = false, bool isalnumOnly=false, size_t minLength=3, bool autoDelete=false); 17 | 18 | private: 19 | IView& display; 20 | IInput& input; 21 | GlobalState& globalState = GlobalState::getInstance(); 22 | size_t getMaxInputLimit(bool password) const; 23 | }; 24 | 25 | #endif // STRING_PROMPT_SELECTOR_H 26 | -------------------------------------------------------------------------------- /test/Enums/TestKeyboardLayoutEnumMapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_KEYBOARD_LAYOUT_ENUM_H 2 | #define TEST_KEYBOARD_LAYOUT_ENUM_H 3 | 4 | #include 5 | #include "../src/Enums/KeyboardLayoutEnum.h" 6 | 7 | void test_to_layout_valid_name() { 8 | TEST_ASSERT_EQUAL_PTR(KeyboardLayout_fr_FR, KeyboardLayoutMapper::toLayout("French (FR)")); 9 | } 10 | 11 | void test_to_layout_invalid_name() { 12 | TEST_ASSERT_EQUAL_PTR(KeyboardLayout_en_US, KeyboardLayoutMapper::toLayout("Invalid Layout")); 13 | TEST_ASSERT_EQUAL_PTR(KeyboardLayout_en_US, KeyboardLayoutMapper::toLayout("")); 14 | } 15 | 16 | void test_get_all_layout_names() { 17 | std::vector layouts = KeyboardLayoutMapper::getAllLayoutNames(); 18 | TEST_ASSERT_FALSE(layouts.empty()); 19 | std::string us = "English (US)"; 20 | TEST_ASSERT_EQUAL_STRING(layouts[2].c_str(), us.c_str()); 21 | } 22 | 23 | #endif // TEST_KEYBOARD_LAYOUT_ENUM_H 24 | -------------------------------------------------------------------------------- /src/Dispatchers/ActionDispatcher.h: -------------------------------------------------------------------------------- 1 | #ifndef APP_DISPATCHER_H 2 | #define APP_DISPATCHER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class ActionDispatcher { 15 | public: 16 | explicit ActionDispatcher(DependencyProvider& provider); 17 | 18 | void setup(); 19 | void run(); 20 | 21 | private: 22 | DependencyProvider& provider; 23 | ContextEnum context; // Selection Context 24 | Entry selectedEntry; 25 | Field selectedField; 26 | 27 | // Méthodes privées 28 | ActionEnum determineActionByContext(); 29 | void executeAction(ActionEnum action); 30 | 31 | GlobalState& globalState = GlobalState::getInstance(); 32 | }; 33 | 34 | #endif // APP_DISPATCHER_H 35 | -------------------------------------------------------------------------------- /src/Services/CategoryService.h: -------------------------------------------------------------------------------- 1 | #ifndef CATEGORY_SERVICE_H 2 | #define CATEGORY_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class CategoryService { 12 | private: 13 | CategoryRepository& repository; 14 | 15 | public: 16 | // Constructeur 17 | CategoryService(CategoryRepository& repo) : repository(repo) {} 18 | 19 | // Validation 20 | bool validateCategory(const Category& category) const; 21 | 22 | // CRUD 23 | void addCategory(const Category& category); 24 | void updateCategory(size_t index, const Category& updatedCategory); 25 | Category findCategoryByIndex(size_t index) const; 26 | std::vector getAllCategories() const; 27 | void setCategories(std::vector& cats); 28 | 29 | // Méthodes utilitaires 30 | std::vector sortCategoriesByName() const; 31 | }; 32 | 33 | #endif // CATEGORY_SERVICE_H 34 | -------------------------------------------------------------------------------- /src/Transformers/ModelTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "ModelTransformer.h" 2 | 3 | template 4 | std::vector ModelTransformer::toStrings(const std::vector& models, std::function extractor) { 5 | std::vector result; 6 | for (const auto& model : models) { 7 | result.push_back(extractor(model)); 8 | } 9 | return result; 10 | } 11 | 12 | std::vector ModelTransformer::toStrings(const std::vector& models) { 13 | return toStrings(models, [](const Entry& entry) { return entry.getServiceName(); }); 14 | } 15 | 16 | std::vector ModelTransformer::toStrings(const std::vector& models) { 17 | return toStrings(models, [](const Category& category) { return category.getName(); }); 18 | } 19 | 20 | std::vector ModelTransformer::toStrings(const Entry& entry) { 21 | return { 22 | entry.getUsername(), 23 | entry.getPassword(), 24 | entry.getNotes() 25 | }; 26 | } -------------------------------------------------------------------------------- /src/Services/EntryService.h: -------------------------------------------------------------------------------- 1 | #ifndef ENTRY_SERVICE_H 2 | #define ENTRY_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class EntryService { 13 | private: 14 | EntryRepository& repository; 15 | 16 | public: 17 | EntryService(EntryRepository& repo) : repository(repo) {} 18 | 19 | bool isEntryExpired(const Entry& entry); 20 | 21 | void addEntry(const Entry& entry); 22 | void deleteEntry(const Entry& entry); 23 | bool updateEntry(const Entry& oldEntry, const Entry& newEntry); 24 | Entry findEntryById(const std::string& id); 25 | std::vector getAllEntries(); 26 | void setEntries(std::vector& ents); 27 | void setContainerName(std::string& name); 28 | std::string getVaultName(); 29 | Entry getEmptyEntry(); 30 | std::vector getEmptyEntries(size_t count); 31 | bool updateField(Entry& entry, const Field& field); 32 | }; 33 | 34 | #endif // ENTRY_SERVICE_H 35 | -------------------------------------------------------------------------------- /src/Models/Field.h: -------------------------------------------------------------------------------- 1 | #ifndef FIELD_H 2 | #define FIELD_H 3 | 4 | #include 5 | 6 | class Field { 7 | private: 8 | std::string label; 9 | std::string value; 10 | std::string shortcut; 11 | 12 | public: 13 | // Constructeurs 14 | Field() : label(""), value(""), shortcut("") {} 15 | Field(const std::string& label, const std::string& value, const std::string& shortcut = "") 16 | : label(label), value(value), shortcut(shortcut) {} 17 | 18 | // Accesseurs 19 | const std::string& getLabel() const { return label; } 20 | const std::string& getValue() const { return value; } 21 | const std::string& getShortcut() const { return shortcut; } 22 | 23 | // Mutateurs 24 | void setLabel(const std::string& newLabel) { label = newLabel; } 25 | void setValue(const std::string& newValue) { value = newValue; } 26 | void setShortcut(const std::string& newShortcut) { shortcut = newShortcut; } 27 | 28 | // Méthodes utils 29 | bool empty() const { return label.empty() && value.empty() && shortcut.empty(); } 30 | }; 31 | 32 | #endif // FIELD_H 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /src/Services/NvsService.cpp: -------------------------------------------------------------------------------- 1 | #include "NvsService.h" 2 | 3 | NvsService::NvsService() 4 | : globalState(GlobalState::getInstance()) { 5 | // Open nvs namespace 6 | preferences.begin(globalState.getNvsNamespace().c_str(), false); 7 | } 8 | 9 | NvsService::~NvsService() { 10 | preferences.end(); // Close namespace 11 | } 12 | 13 | void NvsService::saveString(const std::string& key, const std::string& value) { 14 | preferences.putString(key.c_str(), value.c_str()); 15 | } 16 | 17 | std::string NvsService::getString(const std::string& key, const std::string& defaultValue) { 18 | return preferences.getString(key.c_str(), defaultValue.c_str()).c_str(); 19 | } 20 | 21 | void NvsService::saveInt(const std::string& key, int value) { 22 | preferences.putInt(key.c_str(), value); 23 | } 24 | 25 | int NvsService::getInt(const std::string& key, int defaultValue) { 26 | return preferences.getInt(key.c_str(), defaultValue); 27 | } 28 | 29 | void NvsService::remove(const std::string& key) { 30 | preferences.remove(key.c_str()); 31 | } 32 | 33 | void NvsService::clearNamespace() { 34 | preferences.clear(); 35 | } 36 | -------------------------------------------------------------------------------- /src/Selectors/FieldActionSelectior.cpp: -------------------------------------------------------------------------------- 1 | #include "FieldActionSelector.h" 2 | 3 | FieldActionSelector::FieldActionSelector(IView& display, IInput& input, InactivityManager& inactivityManager) 4 | : display(display), input(input), inactivityManager(inactivityManager) {} 5 | 6 | ActionEnum FieldActionSelector::select(const std::string& label, const std::string& value) { 7 | char key = KEY_NONE; 8 | inactivityManager.reset(); 9 | 10 | display.topBar(label, true, false); 11 | display.value(label, value); 12 | 13 | while (true) { 14 | inactivityManager.update(); 15 | 16 | if (inactivityManager.getVaultIsLocked()) { 17 | return ActionEnum::None; 18 | } 19 | 20 | key = input.handler(); 21 | 22 | if (key != KEY_NONE) { 23 | inactivityManager.reset(); 24 | } 25 | 26 | switch (key) { 27 | case KEY_ESC_CUSTOM: 28 | case KEY_ARROW_LEFT: 29 | return ActionEnum::None; 30 | case KEY_OK: 31 | return ActionEnum::SendToUsb; 32 | case 'm': 33 | return ActionEnum::UpdateField; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Selectors/VerticalSelector.h: -------------------------------------------------------------------------------- 1 | #ifndef VERTICAL_SELECTOR_H 2 | #define VERTICAL_SELECTOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class VerticalSelector { 13 | public: 14 | VerticalSelector(IView& display, IInput& input, InactivityManager& inactivityManager); 15 | int select(const std::string& title, const std::vector& options, bool subMenu = false, bool searchBar = false, const std::vector& options2={}, const std::vector& shortcuts={}, bool visibleMention=false, bool handleInactivity=true); 16 | 17 | private: 18 | IView& display; 19 | IInput& input; 20 | InactivityManager& inactivityManager; 21 | 22 | std::string toLowerCase(const std::string& input); 23 | std::vector filterOptions(const std::vector& options, const std::string& query); 24 | int checkShortcut(const std::vector& shortcuts, char key); 25 | GlobalState& globalState = GlobalState::getInstance(); 26 | }; 27 | 28 | #endif // VERTICAL_SELECTOR_H 29 | -------------------------------------------------------------------------------- /test/Services/TestNvsService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_NVS_SERVICE 2 | #define TEST_NVS_SERVICE 3 | 4 | #include 5 | #include "../src/Services/NvsService.h" 6 | 7 | void test_save_and_get_string() { 8 | NvsService nvsService; 9 | std::string key = "unitTestKey"; 10 | std::string value = "Hello NVS"; 11 | 12 | nvsService.saveString(key, value); 13 | std::string retrievedValue = nvsService.getString(key, "default"); 14 | 15 | TEST_ASSERT_EQUAL_STRING(value.c_str(), retrievedValue.c_str()); 16 | } 17 | 18 | void test_save_and_get_int() { 19 | NvsService nvsService; 20 | std::string key = "unitTestInt"; 21 | int value = 42; 22 | 23 | nvsService.saveInt(key, value); 24 | int retrievedValue = nvsService.getInt(key, 0); 25 | 26 | TEST_ASSERT_EQUAL(value, retrievedValue); 27 | } 28 | 29 | void test_remove_key() { 30 | NvsService nvsService; 31 | std::string key = "testToBeRemoved"; 32 | std::string value = "TempData"; 33 | 34 | nvsService.saveString(key, value); 35 | nvsService.remove(key); 36 | 37 | std::string retrievedValue = nvsService.getString(key, "default"); 38 | TEST_ASSERT_EQUAL_STRING("default", retrievedValue.c_str()); 39 | } 40 | 41 | #endif // TEST_NVS_SERVICE 42 | -------------------------------------------------------------------------------- /test/Enums/TestActionEnumMapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ACTION_ENUM_MAPPER_H 2 | #define TEST_ACTION_ENUM_MAPPER_H 3 | 4 | #include 5 | #include "../src/Enums/ActionEnum.h" 6 | 7 | void test_action_enum_to_string() { 8 | TEST_ASSERT_EQUAL_STRING("Open Vault", ActionEnumMapper::toString(ActionEnum::OpenVault).c_str()); 9 | TEST_ASSERT_EQUAL_STRING("Close Vault", ActionEnumMapper::toString(ActionEnum::CloseVault).c_str()); 10 | TEST_ASSERT_EQUAL_STRING("Unknown Action", ActionEnumMapper::toString(static_cast(999)).c_str()); 11 | } 12 | 13 | void test_action_enum_get_action_names() { 14 | std::vector actions = { 15 | ActionEnum::OpenVault, 16 | ActionEnum::CreateVault, 17 | ActionEnum::ShowHelp 18 | }; 19 | std::vector expected = { 20 | "Open Vault", 21 | "Create Vault", 22 | "Show Help" 23 | }; 24 | 25 | std::vector result = ActionEnumMapper::getActionNames(actions); 26 | 27 | TEST_ASSERT_EQUAL(expected.size(), result.size()); 28 | for (size_t i = 0; i < expected.size(); ++i) { 29 | TEST_ASSERT_EQUAL_STRING(expected[i].c_str(), result[i].c_str()); 30 | } 31 | } 32 | 33 | #endif // TEST_ACTION_ENUM_MAPPER_H 34 | -------------------------------------------------------------------------------- /test/Enums/TestIconEnumMapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ICON_ENUM_MAPPER_H 2 | #define TEST_ICON_ENUM_MAPPER_H 3 | 4 | #include 5 | #include "../src/Enums/IconEnum.h" 6 | 7 | void test_icon_enum_to_string() { 8 | TEST_ASSERT_EQUAL_STRING("Create Vault", IconEnumMapper::toString(IconEnum::CreateVault).c_str()); 9 | TEST_ASSERT_EQUAL_STRING("Load Vault", IconEnumMapper::toString(IconEnum::LoadVault).c_str()); 10 | TEST_ASSERT_EQUAL_STRING("Settings", IconEnumMapper::toString(IconEnum::Settings).c_str()); 11 | TEST_ASSERT_EQUAL_STRING("Unknown Icon", IconEnumMapper::toString(static_cast(999)).c_str()); 12 | } 13 | 14 | void test_icon_enum_get_icon_names() { 15 | std::vector icons = { 16 | IconEnum::CreateVault, 17 | IconEnum::LoadVault, 18 | IconEnum::Settings 19 | }; 20 | std::vector expected = { 21 | "Create Vault", 22 | "Load Vault", 23 | "Settings" 24 | }; 25 | 26 | std::vector result = IconEnumMapper::getIconNames(icons); 27 | 28 | TEST_ASSERT_EQUAL(expected.size(), result.size()); 29 | for (size_t i = 0; i < expected.size(); ++i) { 30 | TEST_ASSERT_EQUAL_STRING(expected[i].c_str(), result[i].c_str()); 31 | } 32 | } 33 | 34 | #endif // TEST_ICON_ENUM_MAPPER_H 35 | -------------------------------------------------------------------------------- /src/Models/Category.h: -------------------------------------------------------------------------------- 1 | #ifndef CATEGORY_H 2 | #define CATEGORY_H 3 | 4 | #include 5 | 6 | class Category { 7 | private: 8 | size_t index; 9 | std::string name; 10 | std::string colorCode; 11 | std::string iconPath; 12 | 13 | public: 14 | // Constructeur default 15 | Category() 16 | : index(0), name(""), colorCode(""), iconPath("") {} 17 | 18 | // Constructeur 19 | Category(size_t index, const std::string& name, const std::string& colorCode = "", const std::string& iconPath = "") 20 | : index(index), name(name), colorCode(colorCode), iconPath(iconPath) {} 21 | 22 | // Accesseurs 23 | size_t getIndex() const { return index; } 24 | const std::string& getName() const { return name; } 25 | const std::string& getColorCode() const { return colorCode; } 26 | const std::string& getIconPath() const { return iconPath; } 27 | 28 | // Mutateurs 29 | void setIndex(size_t newIndex) { index = newIndex; } 30 | void setName(const std::string& newName) { name = newName; } 31 | void setColorCode(const std::string& newColorCode) { colorCode = newColorCode; } 32 | void setIconPath(const std::string& newIconPath) { iconPath = newIconPath; } 33 | 34 | // Méthode utilitaire 35 | bool empty() const { return name.empty(); } 36 | }; 37 | 38 | #endif // CATEGORY_H 39 | -------------------------------------------------------------------------------- /src/Views/IView.h: -------------------------------------------------------------------------------- 1 | #ifndef IVIEW_H 2 | #define IVIEW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class IView { 9 | public: 10 | virtual ~IView() = default; 11 | 12 | virtual void initialize() = 0; 13 | virtual void welcome(uint8_t defaultBrightness=100) = 0; 14 | virtual void setBrightness(uint16_t brightness) = 0; 15 | virtual uint8_t getBrightness() = 0; 16 | virtual void topBar(const std::string& title, bool submenu, bool searchBar) = 0; 17 | virtual void horizontalSelection(const std::vector& options, uint16_t selectedIndex, const std::string& description1="", const std::string& description2="", const std::vector& icons={}) = 0; 18 | virtual void verticalSelection(const std::vector& options, uint16_t selectedIndex, size_t visibleRows = 4, const std::vector& optionLabels = {}, const std::vector& shortcuts = {}, bool visibleMention=false) = 0; 19 | virtual void value(std::string label, std::string val) = 0; 20 | virtual void subMessage(std::string message, int delayMs) = 0; 21 | virtual void stringPrompt(std::string label, std::string value, bool backButton, size_t minLength) = 0; 22 | virtual void confirmationPrompt(std::string label) = 0; 23 | virtual void debug(const std::string& message) = 0; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/Enums/IconEnum.h: -------------------------------------------------------------------------------- 1 | #ifndef ICON_ENUM_H 2 | #define ICON_ENUM_H 3 | 4 | #include 5 | #include 6 | 7 | enum class IconEnum { 8 | None, 9 | CreateVault, 10 | LoadVault, 11 | SdCard, 12 | Settings, 13 | AddEntry, 14 | SelectEntry, 15 | DeleteEntry, 16 | }; 17 | 18 | class IconEnumMapper { 19 | public: 20 | static std::string toString(IconEnum icon) { 21 | static const std::unordered_map iconToStringMap = { 22 | {IconEnum::None, "None"}, 23 | {IconEnum::CreateVault, "Create Vault"}, 24 | {IconEnum::LoadVault, "Load Vault"}, 25 | {IconEnum::SdCard, "Load File"}, 26 | {IconEnum::Settings, "Settings"}, 27 | {IconEnum::AddEntry, "New Password"}, 28 | {IconEnum::SelectEntry, "My Passwords"}, 29 | {IconEnum::DeleteEntry, "Del Password"} 30 | }; 31 | 32 | auto it = iconToStringMap.find(icon); 33 | return it != iconToStringMap.end() ? it->second : "Unknown Icon"; 34 | } 35 | 36 | static std::vector getIconNames(const std::vector& icons) { 37 | std::vector iconNames; 38 | for (const auto& icon : icons) { 39 | iconNames.push_back(toString(icon)); 40 | } 41 | return iconNames; 42 | } 43 | }; 44 | 45 | #endif // ICON_ENUM_H 46 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:m5stack-stamps3] 12 | platform = espressif32 13 | board = m5stack-stamps3 14 | framework = arduino 15 | lib_deps = 16 | m5stack/M5Cardputer@^1.0.3 17 | fastled/FastLED@^3.3.3 18 | bblanchon/ArduinoJson@^7.3.0 19 | build_flags = 20 | -D CONFIG_TINYUSB_HID_ENABLED 21 | -D ARDUINO_USB_MODE=1 22 | 23 | ; Debugger 24 | debug_tool = esp-builtin ; USB-JTAG 25 | upload_protocol = esp-builtin 26 | debug_speed = 20000 27 | monitor_speed = 115200 28 | upload_speed = 921600 29 | debug_build_flags = -Og -ggdb3 -DCORE_DEBUG_LEVEL=5 30 | debug_init_break = tbreak setup 31 | 32 | 33 | [env:test] 34 | platform = espressif32 35 | board = m5stack-stamps3 36 | framework = arduino 37 | build_type = debug 38 | test_framework = unity 39 | lib_deps = 40 | m5stack/M5Cardputer@^1.0.3 41 | throwtheswitch/Unity 42 | fastled/FastLED@^3.3.3 43 | bblanchon/ArduinoJson@^7.3.0 44 | test_build_src = yes 45 | monitor_speed = 115200 46 | 47 | [platformio] 48 | default_envs = test 49 | 50 | [test] 51 | test_ignore = m5stack-stamps3 -------------------------------------------------------------------------------- /test/Selectors/TestConfirmationSelector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_CONFIRMATION_SELECTOR_H 2 | #define TEST_CONFIRMATION_SELECTOR_H 3 | 4 | #include 5 | #include "../src/Selectors/ConfirmationSelector.h" 6 | #include "../Views/MockView.h" 7 | #include "../Inputs/MockInput.h" 8 | 9 | void test_confirmation_selector_confirm() { 10 | MockView mockView; 11 | MockInput mockInput; 12 | 13 | ConfirmationSelector confirmationSelector(mockView, mockInput); 14 | 15 | std::string description = "Are you sure?"; 16 | mockInput.enqueueKey(KEY_OK); 17 | 18 | bool result = confirmationSelector.select("Title", description); 19 | 20 | TEST_ASSERT_TRUE(result); 21 | TEST_ASSERT_TRUE(mockView.topBarCalled); 22 | TEST_ASSERT_TRUE(mockView.confirmationPromptCalled); 23 | TEST_ASSERT_EQUAL_STRING("Title", mockView.lastTitle.c_str()); 24 | } 25 | 26 | void test_confirmation_selector_cancel() { 27 | MockView mockView; 28 | MockInput mockInput; 29 | 30 | ConfirmationSelector confirmationSelector(mockView, mockInput); 31 | 32 | std::string description = "Are you sure?"; 33 | mockInput.enqueueKey(KEY_ESC_CUSTOM); 34 | 35 | bool result = confirmationSelector.select("Test", description); 36 | 37 | TEST_ASSERT_FALSE(result); 38 | TEST_ASSERT_TRUE(mockView.topBarCalled); 39 | TEST_ASSERT_EQUAL_STRING("Test", mockView.lastTitle.c_str()); 40 | } 41 | 42 | #endif // TEST_CONFIRMATION_SELECTOR_H 43 | -------------------------------------------------------------------------------- /src/Transformers/TimeTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "TimeTransformer.h" 2 | 3 | TimeTransformer::TimeTransformer() { 4 | timeLabels = {"30 secondes", "1 minute", "3 minutes", "5 minutes", "10 minutes", "30 minutes", "1 hour", "5 hours"}; 5 | timeValues = { 6 | 30 * 1000, // 30 sec = 30 000 ms 7 | 1 * 60 * 1000, // 1 minute = 60 000 ms 8 | 3 * 60 * 1000, // 3 minutes = 180 000 ms 9 | 5 * 60 * 1000, // 5 minutes = 300 000 ms 10 | 10 * 60 * 1000, // 10 minutes = 600 000 ms 11 | 30 * 60 * 1000, // 30 minutes = 1 800 000 ms 12 | 1 * 60 * 60 * 1000, // 1 heure = 3 600 000 ms 13 | 5 * 60 * 60 * 1000 // 5 heures 14 | }; 15 | } 16 | 17 | std::string TimeTransformer::toLabel(uint32_t timeMs) const { 18 | for (size_t i = 0; i < timeValues.size(); ++i) { 19 | if (timeValues[i] == timeMs) { 20 | return timeLabels[i]; 21 | } 22 | } 23 | return "Unknown"; 24 | } 25 | 26 | uint32_t TimeTransformer::toMilliseconds(const std::string& label) const { 27 | for (size_t i = 0; i < timeLabels.size(); ++i) { 28 | if (timeLabels[i] == label) { 29 | return timeValues[i]; 30 | } 31 | } 32 | return 0; 33 | } 34 | 35 | const std::vector& TimeTransformer::getAllTimeLabels() const { 36 | return timeLabels; 37 | } 38 | 39 | const std::vector& TimeTransformer::getAllTimeValues() const { 40 | return timeValues; 41 | } 42 | -------------------------------------------------------------------------------- /test/Enums/TestBaseColorEnumMapper.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_BASE_COLOR_ENUM_MAPPER_H 2 | #define TEST_BASE_COLOR_ENUM_MAPPER_H 3 | 4 | #include 5 | #include "../src/Enums/BaseColorEnum.h" 6 | 7 | void test_base_color_enum_to_string() { 8 | TEST_ASSERT_EQUAL_STRING("Black", BaseColorEnumMapper::toString(BaseColorEnum::Black).c_str()); 9 | TEST_ASSERT_EQUAL_STRING("Sky Blue", BaseColorEnumMapper::toString(BaseColorEnum::SkyBlue).c_str()); 10 | TEST_ASSERT_EQUAL_STRING("Unknown Color", BaseColorEnumMapper::toString(static_cast(999)).c_str()); 11 | } 12 | 13 | void test_base_color_enum_to_color_value() { 14 | TEST_ASSERT_EQUAL(TFT_BLACK, BaseColorEnumMapper::toColorValue(BaseColorEnum::Black)); 15 | TEST_ASSERT_EQUAL(TFT_SKYBLUE, BaseColorEnumMapper::toColorValue(BaseColorEnum::SkyBlue)); 16 | TEST_ASSERT_EQUAL(TFT_BLACK, BaseColorEnumMapper::toColorValue(static_cast(999))); // Valeur inconnue 17 | } 18 | 19 | void test_base_color_enum_get_all_color_names() { 20 | std::vector result = BaseColorEnumMapper::getAllColorNames(); 21 | 22 | TEST_ASSERT_TRUE(std::find(result.begin(), result.end(), "Black") != result.end()); 23 | TEST_ASSERT_TRUE(std::find(result.begin(), result.end(), "Sky Blue") != result.end()); 24 | TEST_ASSERT_TRUE(std::find(result.begin(), result.end(), "Transparent") != result.end()); 25 | 26 | TEST_ASSERT_EQUAL(27, result.size()); 27 | } 28 | 29 | #endif // TEST_BASE_COLOR_ENUM_MAPPER_H 30 | -------------------------------------------------------------------------------- /src/Repositories/CategoryRepository.cpp: -------------------------------------------------------------------------------- 1 | #include "CategoryRepository.h" 2 | #include 3 | 4 | void CategoryRepository::addCategory(const Category& category) { 5 | categories.push_back(category); 6 | } 7 | 8 | const std::vector& CategoryRepository::getAllCategories() const { 9 | return categories; 10 | } 11 | 12 | void CategoryRepository::setCategories(std::vector& cats) { 13 | categories = cats; 14 | } 15 | 16 | const Category& CategoryRepository::findCategoryByIndex(size_t index) const { 17 | static const Category emptyCategory; 18 | for (const auto& category : categories) { 19 | if (category.getIndex() == index) { 20 | return category; 21 | } 22 | } 23 | return emptyCategory; 24 | } 25 | 26 | bool CategoryRepository::deleteCategoryByIndex(size_t index) { 27 | auto it = std::remove_if(categories.begin(), categories.end(), 28 | [index](const Category& category) { return category.getIndex() == index; }); 29 | if (it != categories.end()) { 30 | categories.erase(it, categories.end()); 31 | return true; 32 | } 33 | return false; 34 | } 35 | 36 | bool CategoryRepository::updateCategory(size_t index, const Category& updatedCategory) { 37 | for (auto& category : categories) { 38 | if (category.getIndex() == index) { 39 | category = updatedCategory; 40 | return true; 41 | } 42 | } 43 | return false; 44 | } 45 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_sv_SE.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_sv_SE.h 3 | 4 | Copyright (c) 2021, Peter John 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_SV_SE_h 22 | #define KEYBOARD_SV_SE_h 23 | 24 | #if !defined(_USING_HID) 25 | 26 | #warning "Using legacy HID core (non pluggable)" 27 | 28 | #else 29 | 30 | //================================================================================ 31 | //================================================================================ 32 | // Keyboard 33 | 34 | // SV_SE keys 35 | #define KEY_A_RING (136+0x2f) 36 | #define KEY_A_UMLAUT (136+0x34) 37 | #define KEY_O_UMLAUT (136+0x33) 38 | #define KEY_UMLAUT (136+0x30) 39 | #define KEY_ACUTE_ACC (136+0x2e) 40 | 41 | #endif 42 | #endif 43 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_da_DK.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_da_DK.h 3 | 4 | Copyright (c) 2021, Peter John 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_DA_DK_h 22 | #define KEYBOARD_DA_DK_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | //================================================================================ 33 | //================================================================================ 34 | // Keyboard 35 | 36 | // DA_DK keys 37 | #define KEY_A_RING (136+0x2f) 38 | #define KEY_SLASHED_O (136+0x34) 39 | #define KEY_ASH (136+0x33) 40 | #define KEY_UMLAUT (136+0x30) 41 | #define KEY_ACUTE_ACC (136+0x2e) 42 | 43 | #endif 44 | #endif 45 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_it_IT.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_it_IT.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_IT_IT_h 22 | #define KEYBOARD_IT_IT_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | //================================================================================ 33 | //================================================================================ 34 | // Keyboard 35 | 36 | // it_IT keys 37 | #define KEY_I_GRAVE (136+0x2e) 38 | #define KEY_E_GRAVE (136+0x2f) 39 | #define KEY_O_GRAVE (136+0x33) 40 | #define KEY_A_GRAVE (136+0x34) 41 | #define KEY_U_GRAVE (136+0x31) 42 | 43 | #endif 44 | #endif 45 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_pt_PT.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_pt_PT.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_PT_PT_h 22 | #define KEYBOARD_PT_PT_h 23 | 24 | #if !defined(_USING_HID) 25 | 26 | #warning "Using legacy HID core (non pluggable)" 27 | 28 | #else 29 | 30 | //================================================================================ 31 | //================================================================================ 32 | // Keyboard 33 | 34 | // pt_PT keys 35 | #define KEY_LEFT_GUILLEMET (136+0x2e) 36 | #define KEY_ACUTE (136+0x30) 37 | #define KEY_C_CEDILLA (136+0x33) 38 | #define KEY_MASCULINE_ORDINAL (136+0x34) 39 | #define KEY_TILDE (136+0x31) 40 | 41 | #endif 42 | #endif 43 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_pt_PT-BR.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_pt_PT.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_PT_PT_h 22 | #define KEYBOARD_PT_PT_h 23 | 24 | #if !defined(_USING_HID) 25 | 26 | #warning "Using legacy HID core (non pluggable)" 27 | 28 | #else 29 | 30 | //================================================================================ 31 | //================================================================================ 32 | // Keyboard 33 | 34 | // pt_PT keys 35 | #define KEY_LEFT_GUILLEMET (136+0x2e) 36 | #define KEY_ACUTE (136+0x30) 37 | #define KEY_C_CEDILLA (136+0x33) 38 | #define KEY_MASCULINE_ORDINAL (136+0x34) 39 | #define KEY_TILDE (136+0x31) 40 | 41 | #endif 42 | #endif 43 | -------------------------------------------------------------------------------- /src/Services/CryptoService.h: -------------------------------------------------------------------------------- 1 | #ifndef CRYPTO_SERVICE_H 2 | #define CRYPTO_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class CryptoService { 15 | public: 16 | CryptoService(); 17 | 18 | // Key derivation and passphrase handling 19 | std::vector deriveKeyFromPassphrase(const std::string& passphrase, const std::string& salt, size_t keySize); 20 | 21 | // AES encryption and decryption 22 | std::vector encryptAES(const std::vector& data, const std::vector& key); 23 | std::vector decryptAES(const std::vector& encrypted, const std::vector& key); 24 | 25 | // Passphrase-based encryption/decryption of private data 26 | std::vector encryptWithPassphrase(const std::string& data, const std::string& passphrase, const std::vector& salt); 27 | std::string decryptWithPassphrase(const std::vector& encryptedData, const std::string& passphrase, const std::vector& salt); 28 | 29 | // Utility 30 | std::vector generateChecksum(const std::string& data, size_t size); 31 | std::vector generateSalt(size_t saltSize); 32 | std::vector generateHardwareRandom(size_t size); 33 | std::string generateRandomString(size_t length); 34 | }; 35 | 36 | #endif // CRYPTO_SERVICE_H 37 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_de_DE.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_de_DE.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_DE_DE_h 22 | #define KEYBOARD_DE_DE_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | //================================================================================ 33 | //================================================================================ 34 | // Keyboard 35 | 36 | // de_DE keys 37 | #define KEY_CIRCUMFLEX (136+0x35) 38 | #define KEY_ESZETT (136+0x2d) 39 | #define KEY_ACUTE (136+0x2e) 40 | #define KEY_U_UMLAUT (136+0x2f) 41 | #define KEY_O_UMLAUT (136+0x33) 42 | #define KEY_A_UMLAUT (136+0x34) 43 | 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /src/Services/UsbService.cpp: -------------------------------------------------------------------------------- 1 | #include "UsbService.h" 2 | 3 | UsbService::UsbService() 4 | : keyboard(), layout(KeyboardLayout_en_US), initialized(false), initTime(0) {} 5 | 6 | void UsbService::setLayout(const uint8_t* newLayout) { 7 | layout = newLayout; 8 | } 9 | 10 | void UsbService::begin() { 11 | if (!initialized) { 12 | USB.begin(); 13 | keyboard.begin(layout); 14 | initialized = true; 15 | initTime = millis(); // HID needs approx 1.5sec to initialize 16 | } 17 | } 18 | 19 | void UsbService::end() { 20 | keyboard.end(); 21 | } 22 | 23 | void UsbService::sendString(const std::string& text) { 24 | // We wait 1.5sec for hid init 25 | while (millis() - initTime < 1500) { 26 | delay(10); 27 | } 28 | 29 | keyboard.releaseAll(); 30 | for (const char& c : text) { 31 | keyboard.write(c); 32 | } 33 | } 34 | 35 | bool UsbService::isReady() const { 36 | return initialized; 37 | } 38 | 39 | void UsbService::sendChunkedString(const std::string& data, size_t chunkSize, unsigned long delayBetweenChunks) { 40 | size_t totalLength = data.length(); 41 | size_t sentLength = 0; 42 | 43 | while (sentLength < totalLength) { 44 | size_t remainingLength = totalLength - sentLength; 45 | size_t currentChunkSize = (remainingLength > chunkSize) ? chunkSize : remainingLength; 46 | 47 | std::string chunk = data.substr(sentLength, currentChunkSize); 48 | sendString(chunk); 49 | 50 | sentLength += currentChunkSize; 51 | delay(delayBetweenChunks); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_fr_FR.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_fr_FR.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_FR_FR_h 22 | #define KEYBOARD_FR_FR_h 23 | 24 | #if !defined(_USING_HID) 25 | 26 | #warning "Using legacy HID core (non pluggable)" 27 | 28 | #else 29 | 30 | //================================================================================ 31 | //================================================================================ 32 | // Keyboard 33 | 34 | // fr_FR keys 35 | #define KEY_SUPERSCRIPT_TWO (136+0x35) 36 | #define KEY_E_ACUTE (136+0x1f) 37 | #define KEY_E_GRAVE (136+0x24) 38 | #define KEY_C_CEDILLA (136+0x26) 39 | #define KEY_A_GRAVE (136+0x27) 40 | #define KEY_CIRCUMFLEX (136+0x2f) 41 | #define KEY_U_GRAVE (136+0x34) 42 | 43 | #endif 44 | #endif 45 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_es_ES.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_es_ES.h 3 | 4 | Copyright (c) 2022, Edgar Bonet 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_ES_ES_h 22 | #define KEYBOARD_ES_ES_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | //================================================================================ 33 | //================================================================================ 34 | // Keyboard 35 | 36 | // es_ES keys 37 | #define KEY_MASCULINE_ORDINAL (136+0x35) 38 | #define KEY_INVERTED_EXCLAMATION (136+0x2e) 39 | #define KEY_GRAVE (136+0x2f) 40 | #define KEY_N_TILDE (136+0x33) 41 | #define KEY_ACUTE (136+0x34) 42 | #define KEY_C_CEDILLA (136+0x31) 43 | 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /src/Services/CategoryService.cpp: -------------------------------------------------------------------------------- 1 | #include "CategoryService.h" 2 | 3 | 4 | bool CategoryService::validateCategory(const Category& category) const { 5 | return !category.getName().empty(); 6 | } 7 | 8 | void CategoryService::addCategory(const Category& category) { 9 | if (!validateCategory(category)) { 10 | throw std::runtime_error("Invalid category: Name is required."); 11 | } 12 | repository.addCategory(category); 13 | } 14 | 15 | void CategoryService::updateCategory(size_t index, const Category& updatedCategory) { 16 | auto existingCategory = repository.findCategoryByIndex(index); 17 | if (existingCategory.empty()) { 18 | throw std::runtime_error("Category not found."); 19 | } 20 | repository.updateCategory(index, updatedCategory); 21 | } 22 | 23 | Category CategoryService::findCategoryByIndex(size_t index) const { 24 | auto category = repository.findCategoryByIndex(index); 25 | if (category.empty()) { 26 | return Category(); // return empty model 27 | } 28 | return category; 29 | } 30 | 31 | std::vector CategoryService::getAllCategories() const { 32 | return repository.getAllCategories(); 33 | } 34 | 35 | void CategoryService::setCategories(std::vector& cats) { 36 | repository.setCategories(cats); 37 | } 38 | 39 | std::vector CategoryService::sortCategoriesByName() const { 40 | auto categories = repository.getAllCategories(); 41 | std::sort(categories.begin(), categories.end(), [](const Category& a, const Category& b) { 42 | return a.getName() < b.getName(); 43 | }); 44 | return categories; 45 | } 46 | -------------------------------------------------------------------------------- /test/Selectors/TestStringPromptSelector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_STRING_SELECTOR_H 2 | #define TEST_STRING_SELECTOR_H 3 | 4 | #include 5 | #include "../src/Selectors/StringPromptSelector.h" 6 | #include "../Views/MockView.h" 7 | #include "../Inputs/MockInput.h" 8 | 9 | void test_string_selector_confirm() { 10 | MockView mockView; 11 | MockInput mockInput; 12 | 13 | StringPromptSelector stringPrompt(mockView, mockInput); 14 | 15 | std::string description = "Enter your name:"; 16 | mockInput.enqueueKey('J'); 17 | mockInput.enqueueKey('o'); 18 | mockInput.enqueueKey('h'); 19 | mockInput.enqueueKey('n'); 20 | mockInput.enqueueKey(KEY_OK); 21 | 22 | std::string result = stringPrompt.select("Test", description); 23 | 24 | TEST_ASSERT_EQUAL_STRING("John", result.c_str()); 25 | TEST_ASSERT_TRUE(mockView.topBarCalled); 26 | TEST_ASSERT_TRUE(mockView.stringPromptCalled); 27 | TEST_ASSERT_EQUAL_STRING("Test", mockView.lastTitle.c_str()); 28 | } 29 | 30 | void test_string_selector_cancel() { 31 | MockView mockView; 32 | MockInput mockInput; 33 | 34 | StringPromptSelector stringPrompt(mockView, mockInput); 35 | 36 | std::string description = "Enter your name:"; 37 | mockInput.enqueueKey(KEY_ESC_CUSTOM); 38 | 39 | std::string result = stringPrompt.select("Title", description); 40 | 41 | TEST_ASSERT_EQUAL_STRING("", result.c_str()); 42 | TEST_ASSERT_TRUE(mockView.topBarCalled); 43 | TEST_ASSERT_TRUE(mockView.stringPromptCalled); 44 | TEST_ASSERT_EQUAL_STRING("Title", mockView.lastTitle.c_str()); 45 | } 46 | 47 | #endif // TEST_STRING_SELECTOR_H 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Password Manager for ESP32 2 | 3 | **Password Manager** designed for the ESP32. It provides **secure password storage, encryption, and USB emulation for typing passwords automatically**. 4 | 5 | ![](/image.jpg) 6 | 7 | ## Features 8 | 9 | - **AES-128 Encryption**: All stored passwords are encrypted for security. 10 | - **Storage on SD Card**: Encrypted password storage on an SD card for persistent data. 11 | - **Random Password Generation**: Generate secure passwords. 12 | - **HID Keyboard Mode**: ESP32 can act as a USB keyboard to automatically type credentials. 13 | - **User Authentication**: Requires a master password to unlock stored credentials. 14 | - **Auto-Lock Vault**: The vault will be automatically locked after a selected amount of time. 15 | 16 | ## Installation 17 | 18 | - M5Burner : Search into M5CARDPUTER section and burn it 19 | - Github : Build or take the firmware.bin from the [github release](https://github.com/geo-tp/Password-Manager/releases) and flash it 20 | 21 | ## Usage 22 | - **Create a Vault**: Create a new encrypted vault to securely store your passwords. **Each vault is stored as an encrypted file on the SD card.** 23 | 24 | - **Manage Password Entries**: Add, update, delete password entries to the vault. **Up to 100 passwords per vault.** 25 | 26 | - **Auto-Type**: Select a field and press `OK`, the ESP32 type it via USB HID. 27 | 28 | - **Update Settings**: Adjust app settings as keyboard layout, brightness and vault lock timings. 29 | 30 | **NOTE:** You can update a vault name by modifying the filename in the `/vaults/` folder, the file extension must remains `.vault`. **The master password used to create0 a vault can't be modified.** 31 | -------------------------------------------------------------------------------- /src/Enums/KeyboardLayoutEnum.h: -------------------------------------------------------------------------------- 1 | #ifndef KEYBOARD_LAYOUT_ENUM_H 2 | #define KEYBOARD_LAYOUT_ENUM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | enum class KeyboardLayoutEnum { 11 | EnglishUS, 12 | EnglishUK, 13 | FrenchFR, 14 | GermanDE, 15 | SpanishES, 16 | ItalianIT, 17 | PortuguesePT, 18 | PortugueseBR, 19 | SwedishSE, 20 | DanishDK, 21 | HungarianHU, 22 | None 23 | }; 24 | 25 | class KeyboardLayoutMapper { 26 | public: 27 | // Associated label and layout 28 | inline static const std::map layoutMap = { 29 | {"English (US)", KeyboardLayout_en_US}, 30 | {"English (UK)", KeyboardLayout_en_UK}, 31 | {"French (FR)", KeyboardLayout_fr_FR}, 32 | {"German (DE)", KeyboardLayout_de_DE}, 33 | {"Italian (IT)", KeyboardLayout_it_IT}, 34 | {"Spanish (ES)", KeyboardLayout_es_ES}, 35 | {"Portuguese (PT)", KeyboardLayout_pt_PT}, 36 | {"Portuguese (BR)", KeyboardLayout_pt_BR}, 37 | {"Danish (DK)", KeyboardLayout_da_DK}, 38 | {"Swedish (SE)", KeyboardLayout_sv_SE}, 39 | {"Hungarian (HU)", KeyboardLayout_hu_HU} 40 | }; 41 | 42 | static const uint8_t* toLayout(const std::string& layoutName) { 43 | auto it = layoutMap.find(layoutName); 44 | return it != layoutMap.end() ? it->second : KeyboardLayout_en_US; 45 | } 46 | 47 | static std::vector getAllLayoutNames() { 48 | std::vector names; 49 | for (const auto& pair : layoutMap) { 50 | names.push_back(pair.first); 51 | } 52 | return names; 53 | } 54 | }; 55 | 56 | #endif // KEYBOARD_LAYOUT_ENUM_H 57 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_hu_HU.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard_hu_HU.h 3 | 4 | Copyright (c) 2023, Barab(0x34)si Rich(0x34)rd 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef KEYBOARD_HU_HU_h 22 | #define KEYBOARD_HU_HU_h 23 | 24 | #include "HID.h" 25 | 26 | #if !defined(_USING_HID) 27 | 28 | #warning "Using legacy HID core (non pluggable)" 29 | 30 | #else 31 | 32 | //================================================================================ 33 | //================================================================================ 34 | // Keyboard 35 | 36 | // hu_HU keys 37 | #define KEY_O_ACUTE (136+0x2e) 38 | #define KEY_O_UMLAUT (136+0x27) 39 | #define KEY_O_DOUBLE_ACUTE (136+0x2f) 40 | 41 | #define KEY_U_ACUTE (136+0x30) 42 | #define KEY_U_UMLAUT (136+0x2d) 43 | #define KEY_U_DOUBLE_ACUTE (136+0x31) 44 | 45 | #define KEY_A_ACUTE (136+0x34) 46 | 47 | #define KEY_E_ACUTE (136+0x33) 48 | 49 | #define KEY_I_ACUTE (136+0x32) 50 | 51 | #endif 52 | #endif 53 | -------------------------------------------------------------------------------- /src/Services/SdService.h: -------------------------------------------------------------------------------- 1 | #ifndef SD_SERVICE_H 2 | #define SD_SERVICE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class SdService { 12 | private: 13 | SPIClass sdCardSPI; 14 | bool sdCardMounted = false; 15 | GlobalState& globalState = GlobalState::getInstance(); 16 | std::unordered_map> cachedDirectoryElements; 17 | public: 18 | SdService(); 19 | 20 | bool begin(); 21 | void close(); 22 | bool isFile(const std::string& filePath); 23 | bool isDirectory(const std::string& path); 24 | bool getSdState(); 25 | 26 | std::vector listElements(const std::string& dirPath, size_t limit = 0); 27 | std::vector readBinaryFile(const std::string& filePath); 28 | std::string readFile(const std::string& filePath); 29 | 30 | bool writeFile(const std::string& filePath, const std::string& data); 31 | bool writeBinaryFile(const std::string& filePath, const std::vector& data); 32 | bool appendToFile(const std::string& filePath, const std::string& data); 33 | bool deleteFile(const std::string& filePath); 34 | bool validateVaultFile(const std::string& filePath); 35 | bool ensureDirectory(const std::string& directory); 36 | 37 | std::string getFileExt(const std::string& path); 38 | std::string getParentDirectory(const std::string& path); 39 | std::string getFileName(const std::string& path); 40 | std::vector getCachedDirectoryElements(const std::string& path); 41 | void setCachedDirectoryElements(const std::string& path, const std::vector& elements); 42 | void removeCachedPath(const std::string& path); 43 | }; 44 | 45 | #endif // SD_SERVICE_H 46 | -------------------------------------------------------------------------------- /src/Inputs/CardputerInput.cpp: -------------------------------------------------------------------------------- 1 | #include "CardputerInput.h" 2 | 3 | namespace inputs { 4 | 5 | 6 | char CardputerInput::handler() { 7 | 8 | // Update keyboard state 9 | M5Cardputer.update(); 10 | 11 | // Bouton GO 12 | if (M5Cardputer.BtnA.isPressed()) { 13 | delay(150); // debounce 14 | return KEY_ESC_CUSTOM; 15 | } 16 | 17 | if (M5Cardputer.Keyboard.isChange()) { 18 | 19 | if (M5Cardputer.Keyboard.isPressed()) { 20 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 21 | 22 | if (status.enter) { // go to next menu 23 | return KEY_OK; 24 | } 25 | if (status.del) { 26 | return KEY_DEL; 27 | } 28 | 29 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_LEFT)) { // go back to previous menu 30 | return KEY_ARROW_LEFT; 31 | } 32 | 33 | if(M5Cardputer.Keyboard.isKeyPressed(KEY_ARROW_RIGHT)) { // go to next menu 34 | return KEY_ARROW_RIGHT; 35 | } 36 | 37 | for (auto c : status.word) { 38 | // Issue with %, the only key that requires 2 inputs to display 39 | if (c == '%') { 40 | return '5'; 41 | } 42 | return c; // retourner le premier char saisi 43 | } 44 | } 45 | } 46 | delay(10); // debounce 47 | return KEY_NONE; 48 | } 49 | 50 | void CardputerInput::waitPress() { 51 | while(1){ 52 | M5Cardputer.update(); 53 | if (M5Cardputer.Keyboard.isChange()) { 54 | if (M5Cardputer.Keyboard.isPressed()) { 55 | Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState(); 56 | return; 57 | } 58 | } 59 | delay(10); 60 | } 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /test/Transformers/TestTimeTransformer.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_TIME_TRANSFORMER 2 | #define TEST_TIME_TRANSFORMER 3 | 4 | #include 5 | #include "../src/Transformers/TimeTransformer.h" 6 | 7 | void test_to_label() { 8 | TimeTransformer transformer; 9 | 10 | TEST_ASSERT_EQUAL_STRING("1 minute", transformer.toLabel(60000).c_str()); 11 | TEST_ASSERT_EQUAL_STRING("30 minutes", transformer.toLabel(1800000).c_str()); 12 | TEST_ASSERT_EQUAL_STRING("1 hour", transformer.toLabel(3600000).c_str()); 13 | 14 | // Unknow value 15 | TEST_ASSERT_EQUAL_STRING("Unknown", transformer.toLabel(9999999).c_str()); 16 | } 17 | 18 | void test_to_milliseconds() { 19 | TimeTransformer transformer; 20 | 21 | TEST_ASSERT_EQUAL(60000, transformer.toMilliseconds("1 minute")); 22 | TEST_ASSERT_EQUAL(180000, transformer.toMilliseconds("3 minutes")); 23 | TEST_ASSERT_EQUAL(1800000, transformer.toMilliseconds("30 minutes")); 24 | TEST_ASSERT_EQUAL(3600000, transformer.toMilliseconds("1 hour")); 25 | 26 | // Test d'une valeur inconnue 27 | TEST_ASSERT_EQUAL(0, transformer.toMilliseconds("Unknown time")); 28 | } 29 | 30 | void test_get_all_time_labels() { 31 | TimeTransformer transformer; 32 | auto labels = transformer.getAllTimeLabels(); 33 | 34 | TEST_ASSERT_EQUAL_STRING("1 minute", labels[1].c_str()); 35 | TEST_ASSERT_EQUAL_STRING("10 minutes", labels[4].c_str()); 36 | TEST_ASSERT_EQUAL_STRING("30 minutes", labels[5].c_str()); 37 | } 38 | 39 | void test_get_all_time_values() { 40 | TimeTransformer transformer; 41 | auto values = transformer.getAllTimeValues(); 42 | 43 | TEST_ASSERT_EQUAL(60000, values[1]); 44 | TEST_ASSERT_EQUAL(180000, values[2]); 45 | TEST_ASSERT_EQUAL(1800000, values[5]); 46 | TEST_ASSERT_EQUAL(3600000, values[6]); 47 | } 48 | 49 | #endif // TEST_TIME_TRANSFORMER 50 | -------------------------------------------------------------------------------- /src/Selectors/StringPromptSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "StringPromptSelector.h" 2 | 3 | StringPromptSelector::StringPromptSelector(IView& display, IInput& input) 4 | : display(display), input(input) {} 5 | 6 | std::string StringPromptSelector::select( 7 | const std::string& title, 8 | const std::string& label, 9 | const std::string& value, 10 | bool backButton, 11 | bool maxInput, 12 | bool isalnumOnly, 13 | size_t minLength, 14 | bool autoDelete 15 | ) { 16 | std::string output = value; 17 | char key = KEY_NONE; 18 | size_t limit = getMaxInputLimit(maxInput); 19 | 20 | display.topBar(title, false, false); 21 | display.stringPrompt(label, output, backButton, minLength); 22 | 23 | while (true) { 24 | key = input.handler(); 25 | 26 | if (key == KEY_OK && output.length() >= minLength) { 27 | break; // confirm if minLength 28 | } 29 | if ((key == KEY_ARROW_LEFT || key == KEY_ESC_CUSTOM) && backButton) { 30 | return ""; // return 31 | } 32 | if (key == KEY_DEL && !output.empty()) { 33 | if (autoDelete) { 34 | output = ""; 35 | autoDelete = false; 36 | } else { 37 | output.pop_back(); 38 | } 39 | } 40 | else if ((isalnumOnly ? std::isalnum(key) : std::isprint(key)) && output.size() < limit) { 41 | output += key; 42 | autoDelete = false; 43 | } 44 | 45 | if (key != KEY_NONE) { 46 | display.stringPrompt(label, output, backButton, minLength); 47 | } 48 | delay(5); 49 | } 50 | 51 | return output; 52 | } 53 | 54 | size_t StringPromptSelector::getMaxInputLimit(bool password) const { 55 | return password ? globalState.getMaxInputCharPasswordCount() : globalState.getMaxInputCharCount(); 56 | } 57 | -------------------------------------------------------------------------------- /src/Repositories/EntryRepository.cpp: -------------------------------------------------------------------------------- 1 | #include "EntryRepository.h" 2 | 3 | void EntryRepository::addEntry(const Entry& entry) { 4 | entries.push_back(entry); 5 | } 6 | 7 | const std::vector& EntryRepository::getAllEntries() const { 8 | return entries; 9 | } 10 | 11 | void EntryRepository::setEntries(std::vector& ents) { 12 | entries = ents; 13 | } 14 | 15 | const Entry& EntryRepository::findEntryById(const std::string& id) const { 16 | static const Entry emptyEntry; 17 | for (const auto& entry : entries) { 18 | if (entry.getId() == id) { 19 | return entry; 20 | } 21 | } 22 | return emptyEntry; 23 | } 24 | 25 | bool EntryRepository::deleteEntry(const Entry& entry) { 26 | auto it = std::remove_if(entries.begin(), entries.end(), 27 | [&entry](const Entry& currentEntry) { 28 | return currentEntry.getServiceName() == entry.getServiceName() && 29 | currentEntry.getUsername() == entry.getUsername(); 30 | }); 31 | if (it != entries.end()) { 32 | entries.erase(it, entries.end()); 33 | return true; 34 | } 35 | return false; 36 | } 37 | 38 | bool EntryRepository::updateEntry(const Entry& oldEntry, const Entry& newEntry) { 39 | for (auto& entry : entries) { 40 | if (entry.getServiceName() == oldEntry.getServiceName() && 41 | entry.getUsername() == oldEntry.getUsername() && 42 | entry.getPassword() == oldEntry.getPassword() && 43 | entry.getNotes() == oldEntry.getNotes()) { 44 | entry = newEntry; 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | 52 | std::string EntryRepository::getContainerName() { 53 | return containerName; 54 | } 55 | 56 | void EntryRepository::setContainerName(std::string& name) { 57 | containerName = name; 58 | } 59 | -------------------------------------------------------------------------------- /test/Controllers/TestUtilityController.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_UTILITY_CONTROLLER 2 | #define TEST_UTILITY_CONTROLLER 3 | 4 | #include 5 | #include "../src/Controllers/UtilityController.h" 6 | #include "../src/Services/NvsService.h" 7 | #include "../src/Services/UsbService.h" 8 | #include "../src/Services/LedService.h" 9 | #include "../src/Services/SdService.h" 10 | #include "../src/Selectors/HorizontalSelector.h" 11 | #include "../src/Selectors/VerticalSelector.h" 12 | #include "../src/Selectors/FieldEditorSelector.h" 13 | #include "../src/Selectors/StringPromptSelector.h" 14 | #include "../src/Selectors/ConfirmationSelector.h" 15 | #include "../src/Managers/InactivityManager.h" 16 | #include "../src/Transformers/TimeTransformer.h" 17 | #include "../Views/MockView.h" 18 | #include "../Inputs/MockInput.h" 19 | 20 | void test_handleGeneralSettings() { 21 | MockView mockDisplay; 22 | MockInput mockInput; 23 | NvsService nvsService; 24 | UsbService usbService; 25 | LedService ledService; 26 | SdService sdService; 27 | InactivityManager inactivityManager(mockDisplay); 28 | TimeTransformer timeTransformer; 29 | 30 | HorizontalSelector horizontalSelector(mockDisplay, mockInput, inactivityManager); 31 | VerticalSelector verticalSelector(mockDisplay, mockInput, inactivityManager); 32 | FieldEditorSelector fieldEditorSelector(mockDisplay, mockInput); 33 | StringPromptSelector stringPromptSelector(mockDisplay, mockInput); 34 | ConfirmationSelector confirmationSelector(mockDisplay, mockInput); 35 | 36 | UtilityController controller(mockDisplay, mockInput, horizontalSelector, verticalSelector, 37 | fieldEditorSelector, stringPromptSelector, confirmationSelector, 38 | usbService, ledService, nvsService, sdService, timeTransformer); 39 | 40 | // Not really usefull to test it 41 | TEST_ASSERT_TRUE(true); 42 | } 43 | 44 | #endif // TEST_UTILITY_CONTROLLER 45 | -------------------------------------------------------------------------------- /test/Selectors/TestHorizontalSelector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_HORIZONTAL_SELECTORS_H 2 | #define TEST_HORIZONTAL_SELECTORS_H 3 | 4 | #include 5 | #include "../src/Selectors/HorizontalSelector.h" 6 | #include "../Views/MockView.h" 7 | #include "../Inputs/MockInput.h" 8 | 9 | void test_horizontal_selector_confirm() { 10 | MockView mockView; 11 | MockInput mockInput; 12 | InactivityManager manager(mockView); 13 | 14 | HorizontalSelector horizontalSelector(mockView, mockInput, manager); 15 | 16 | std::vector options = {"OptionA", "OptionB", "OptionC"}; 17 | std::string title = "Horizontal Selector Test"; 18 | 19 | // Mock Input 20 | mockInput.enqueueKey(KEY_ARROW_RIGHT); 21 | mockInput.enqueueKey(KEY_ARROW_RIGHT); 22 | mockInput.enqueueKey(KEY_ARROW_LEFT); 23 | mockInput.enqueueKey(KEY_OK); 24 | 25 | int selectedIndex = horizontalSelector.select(title, options); 26 | 27 | TEST_ASSERT_EQUAL(1, selectedIndex); // La deuxième option est sélectionnée 28 | TEST_ASSERT_TRUE(mockView.topBarCalled); 29 | TEST_ASSERT_TRUE(mockView.horizontalSelectionCalled); 30 | TEST_ASSERT_EQUAL_STRING(title.c_str(), mockView.lastTitle.c_str()); 31 | TEST_ASSERT_EQUAL_STRING("OptionB", mockView.displayedOptions[selectedIndex].c_str()); 32 | } 33 | 34 | void test_horizontal_selector_cancel() { 35 | MockView mockView; 36 | MockInput mockInput; 37 | InactivityManager manager(mockView); 38 | 39 | HorizontalSelector horizontalSelector(mockView, mockInput, manager); 40 | 41 | std::vector options = {"OptionA", "OptionB", "OptionC"}; 42 | std::string title = "Horizontal Selector Test"; 43 | 44 | // Mock Input 45 | mockInput.enqueueKey(KEY_ESC_CUSTOM); 46 | 47 | int selectedIndex = horizontalSelector.select(title, options); 48 | 49 | TEST_ASSERT_EQUAL(-1, selectedIndex); // Retourne -1 si l'utilisateur appuie sur RETURN 50 | } 51 | 52 | #endif // TEST_HORIZONTAL_SELECTORS_H 53 | -------------------------------------------------------------------------------- /test/Transformers/TestModelTransformer.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_MODEL_TRANSFORMER_H 2 | #define TEST_MODEL_TRANSFORMER_H 3 | 4 | #include 5 | #include "../src/Transformers/ModelTransformer.h" 6 | #include "../src/Models/Entry.h" 7 | #include "../src/Models/Category.h" 8 | 9 | void test_transform_entries_to_strings() { 10 | std::vector entries = { 11 | Entry("1", "Service1", "User1", "Pass1", 0), 12 | Entry("2", "Service2", "User2", "Pass2", 1) 13 | }; 14 | 15 | auto strings = ModelTransformer::toStrings( 16 | entries, 17 | [](const Entry& entry) { return entry.getServiceName(); } 18 | ); 19 | 20 | TEST_ASSERT_EQUAL(2, strings.size()); 21 | TEST_ASSERT_EQUAL_STRING("Service1", strings[0].c_str()); 22 | TEST_ASSERT_EQUAL_STRING("Service2", strings[1].c_str()); 23 | } 24 | 25 | void test_transform_categories_to_strings() { 26 | std::vector categories = { 27 | Category(1, "Personal", "#FF5733", "icon1.png"), 28 | Category(2, "Work", "#33FF57", "icon2.png") 29 | }; 30 | 31 | auto strings = ModelTransformer::toStrings( 32 | categories, 33 | [](const Category& category) { return category.getName(); } 34 | ); 35 | 36 | TEST_ASSERT_EQUAL(2, strings.size()); 37 | TEST_ASSERT_EQUAL_STRING("Personal", strings[0].c_str()); 38 | TEST_ASSERT_EQUAL_STRING("Work", strings[1].c_str()); 39 | } 40 | 41 | void test_transform_single_entry_to_strings() { 42 | Entry entry("1", "Service1", "User1", "encryptedPass1", 0); 43 | entry.setNotes("This is a note"); 44 | entry.setCreatedAt(1672531200); 45 | entry.setUpdatedAt(1672617600); 46 | 47 | auto strings = ModelTransformer::toStrings(entry); 48 | 49 | TEST_ASSERT_EQUAL(3, strings.size()); 50 | TEST_ASSERT_EQUAL_STRING("User1", strings[0].c_str()); 51 | TEST_ASSERT_EQUAL_STRING("encryptedPass1", strings[1].c_str()); 52 | TEST_ASSERT_EQUAL_STRING("This is a note", strings[2].c_str()); 53 | } 54 | 55 | #endif // TEST_MODEL_TRANSFORMER_H 56 | -------------------------------------------------------------------------------- /src/Selectors/HorizontalSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "HorizontalSelector.h" 2 | 3 | HorizontalSelector::HorizontalSelector(IView& display, IInput& input , InactivityManager& inactivityManager) 4 | : display(display), input(input), inactivityManager(inactivityManager) {} 5 | 6 | int HorizontalSelector::select( 7 | const std::string& title, 8 | const std::vector& options, 9 | const std::string& description1, 10 | const std::string& description2, 11 | const std::vector& icons, 12 | bool handleInactivity) { 13 | 14 | int currentIndex = 0; 15 | int lastIndex = -1; 16 | inactivityManager.reset(); 17 | 18 | display.topBar(title, false, false); 19 | 20 | while (true) { 21 | if (handleInactivity) { 22 | inactivityManager.update(); 23 | if (inactivityManager.getVaultIsLocked()) { 24 | return -1; 25 | } 26 | } 27 | 28 | // Display the current options horizontally with the selection 29 | if (lastIndex != currentIndex) { 30 | display.horizontalSelection(options, currentIndex, description1, description2, icons); 31 | lastIndex = currentIndex; 32 | } 33 | 34 | // Capture user input 35 | char key = input.handler(); 36 | 37 | if (handleInactivity && key != KEY_NONE) { 38 | inactivityManager.reset(); 39 | } 40 | 41 | switch (key) { 42 | case KEY_ARROW_LEFT: // Move left 43 | currentIndex = (currentIndex > 0) ? currentIndex - 1 : options.size() - 1; 44 | break; 45 | case KEY_ARROW_RIGHT: // Move right 46 | currentIndex = (currentIndex < options.size() - 1) ? currentIndex + 1 : 0; 47 | break; 48 | case KEY_OK: // Select 49 | return currentIndex; 50 | case KEY_ESC_CUSTOM: 51 | if (handleInactivity) { 52 | return -1; 53 | } 54 | default: 55 | break; // Ignore other inputs 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Enums/ActionEnum.h: -------------------------------------------------------------------------------- 1 | #ifndef ACTION_ENUM_H 2 | #define ACTION_ENUM_H 3 | #include 4 | #include 5 | #include 6 | 7 | enum class ActionEnum { 8 | None = -1, 9 | 10 | // File-related actions 11 | OpenVault, 12 | CreateVault, 13 | CloseVault, 14 | LoadSdVault, 15 | LoadNvsVault, 16 | 17 | // Entry-related actions 18 | SelectEntry, 19 | CreateEntry, 20 | DeleteEntry, 21 | 22 | // Field-related actions 23 | SelectField, 24 | UpdateField, 25 | 26 | // App-level actions 27 | SendToUsb, 28 | ShowHelp, 29 | UpdateSettings 30 | }; 31 | 32 | class ActionEnumMapper { 33 | public: 34 | static std::string toString(ActionEnum action) { 35 | static const std::unordered_map actionToStringMap = { 36 | {ActionEnum::None, "None"}, 37 | {ActionEnum::OpenVault, "Open Vault"}, 38 | {ActionEnum::CreateVault, "Create Vault"}, 39 | {ActionEnum::CloseVault, "Close Vault"}, 40 | {ActionEnum::LoadSdVault, "SD Vault"}, 41 | {ActionEnum::LoadNvsVault, "NVS Vault"}, 42 | {ActionEnum::SelectEntry, "My Passwords"}, 43 | {ActionEnum::CreateEntry, "New Password"}, 44 | {ActionEnum::DeleteEntry, "Del Password"}, 45 | {ActionEnum::SelectField, "Select Field"}, 46 | {ActionEnum::UpdateField, "Update Field"}, 47 | {ActionEnum::SendToUsb, "Send to USB"}, 48 | {ActionEnum::ShowHelp, "Show Help"}, 49 | {ActionEnum::UpdateSettings, "Settings"} 50 | }; 51 | 52 | auto it = actionToStringMap.find(action); 53 | return it != actionToStringMap.end() ? it->second : "Unknown Action"; 54 | } 55 | 56 | static std::vector getActionNames(const std::vector& actions) { 57 | std::vector actionNames; 58 | for (const auto& action : actions) { 59 | actionNames.push_back(toString(action)); 60 | } 61 | return actionNames; 62 | } 63 | }; 64 | 65 | #endif // ACTION_ENUM_H 66 | -------------------------------------------------------------------------------- /src/Services/EntryService.cpp: -------------------------------------------------------------------------------- 1 | #include "EntryService.h" 2 | 3 | bool EntryService::isEntryExpired(const Entry& entry) { 4 | if (entry.getExpiresAt() == 0) return false; 5 | return std::time(nullptr) > entry.getExpiresAt(); 6 | } 7 | 8 | void EntryService::addEntry(const Entry& entry) { 9 | repository.addEntry(entry); 10 | } 11 | 12 | void EntryService::deleteEntry(const Entry& entry) { 13 | repository.deleteEntry(entry); 14 | } 15 | 16 | bool EntryService::updateEntry(const Entry& oldEntry, const Entry& newEntry) { 17 | return repository.updateEntry(oldEntry, newEntry); 18 | } 19 | 20 | Entry EntryService::findEntryById(const std::string& id) { 21 | auto entry = repository.findEntryById(id); 22 | return entry; 23 | } 24 | 25 | std::vector EntryService::getAllEntries() { 26 | return repository.getAllEntries(); 27 | } 28 | 29 | void EntryService::setEntries(std::vector& ents) { 30 | repository.setEntries(ents); 31 | } 32 | 33 | std::string EntryService::getVaultName() { 34 | return repository.getContainerName(); 35 | } 36 | 37 | void EntryService::setContainerName(std::string& name) { 38 | repository.setContainerName(name); 39 | } 40 | 41 | Entry EntryService::getEmptyEntry() { 42 | return Entry(); 43 | } 44 | 45 | std::vector EntryService::getEmptyEntries(size_t count) { 46 | std::vector entries; 47 | entries.reserve(count); 48 | 49 | for (size_t i = 0; i < count; ++i) { 50 | entries.push_back(Entry()); 51 | } 52 | 53 | return entries; 54 | } 55 | 56 | bool EntryService::updateField(Entry& entry, const Field& field) { 57 | const std::string& fieldName = field.getLabel(); 58 | const std::string& newValue = field.getValue(); 59 | Entry originalEntry = entry; 60 | 61 | if (fieldName == "User") { 62 | entry.setUsername(newValue); 63 | } else if (fieldName == "Pass") { 64 | entry.setPassword(newValue); 65 | } else if (fieldName == "Note") { 66 | entry.setNotes(newValue); 67 | } else { 68 | return false; 69 | } 70 | 71 | return repository.updateEntry(originalEntry, entry); 72 | } 73 | -------------------------------------------------------------------------------- /src/Controllers/UtilityController.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILITY_CONTROLLER_H 2 | #define UTILITY_CONTROLLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | class UtilityController { 22 | public: 23 | UtilityController(IView& display, 24 | IInput& input, 25 | HorizontalSelector& horizontalSelector, 26 | VerticalSelector& verticalSelector, 27 | FieldEditorSelector& fieldEditorSelector, 28 | StringPromptSelector& stringPromptSelector, 29 | ConfirmationSelector& confirmationSelector, 30 | UsbService& usbService, 31 | LedService& ledService, 32 | NvsService& nvsService, 33 | SdService& sdService, 34 | TimeTransformer& timeTransformer); 35 | 36 | 37 | bool handleUsbTyping(std::string sendString); 38 | bool handleKeyboardInitialization(); 39 | bool handleGeneralSettings(); 40 | void handleLoadNvs(); 41 | void handleWelcome(); 42 | void handleInactivity(); 43 | 44 | private: 45 | IView& display; 46 | IInput& input; 47 | UsbService& usbService; 48 | LedService& ledService; 49 | NvsService& nvsService; 50 | SdService& sdService; 51 | 52 | TimeTransformer& timeTransformer; 53 | 54 | HorizontalSelector& horizontalSelector; 55 | VerticalSelector& verticalSelector; 56 | FieldEditorSelector& fieldEditorSelector; 57 | StringPromptSelector& stringPromptSelector; 58 | ConfirmationSelector& confirmationSelector; 59 | 60 | GlobalState& globalState = GlobalState::getInstance(); 61 | }; 62 | 63 | #endif // UTILITY_CONTROLLER_H 64 | -------------------------------------------------------------------------------- /test/Selectors/TestFieldActionSelector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_FIELD_ACTION_SELECTOR_H 2 | #define TEST_FIELD_ACTION_SELECTOR_H 3 | 4 | #include 5 | #include "../src/Selectors/FieldActionSelector.h" 6 | #include "../src/Managers/InactivityManager.h" 7 | #include "../Views/MockView.h" 8 | #include "../Inputs/MockInput.h" 9 | 10 | void test_field_action_selector_send_to_usb() { 11 | MockView mockView; 12 | MockInput mockInput; 13 | InactivityManager inactivityManager(mockView); 14 | FieldActionSelector fieldActionSelector(mockView, mockInput, inactivityManager); 15 | 16 | std::string label = "Test Label"; 17 | std::string value = "Test Value"; 18 | 19 | mockInput.enqueueKey(KEY_OK); 20 | 21 | ActionEnum action = fieldActionSelector.select(label, value); 22 | 23 | TEST_ASSERT_EQUAL(ActionEnum::SendToUsb, action); 24 | TEST_ASSERT_TRUE(mockView.topBarCalled); 25 | TEST_ASSERT_TRUE(mockView.valueCalled); 26 | } 27 | 28 | void test_field_action_selector_update_field() { 29 | MockView mockView; 30 | MockInput mockInput; 31 | InactivityManager inactivityManager(mockView); 32 | FieldActionSelector fieldActionSelector(mockView, mockInput, inactivityManager); 33 | 34 | std::string label = "Test Label"; 35 | std::string value = "Test Value"; 36 | 37 | // M is Update shortcut 38 | mockInput.enqueueKey('m'); 39 | 40 | ActionEnum action = fieldActionSelector.select(label, value); 41 | 42 | TEST_ASSERT_EQUAL(ActionEnum::UpdateField, action); 43 | TEST_ASSERT_TRUE(mockView.topBarCalled); 44 | TEST_ASSERT_TRUE(mockView.valueCalled); 45 | } 46 | 47 | void test_field_action_selector_cancel() { 48 | MockView mockView; 49 | MockInput mockInput; 50 | InactivityManager inactivityManager(mockView); 51 | FieldActionSelector fieldActionSelector(mockView, mockInput, inactivityManager); 52 | 53 | std::string label = "Test Label"; 54 | std::string value = "Test Value"; 55 | 56 | mockInput.enqueueKey(KEY_ARROW_LEFT); 57 | 58 | ActionEnum action = fieldActionSelector.select(label, value); 59 | 60 | TEST_ASSERT_EQUAL(ActionEnum::None, action); 61 | TEST_ASSERT_TRUE(mockView.topBarCalled); 62 | TEST_ASSERT_TRUE(mockView.valueCalled); 63 | } 64 | 65 | #endif // TEST_FIELD_ACTION_SELECTOR_H 66 | -------------------------------------------------------------------------------- /src/Controllers/VaultController.h: -------------------------------------------------------------------------------- 1 | #ifndef VAULT_CONTROLLER_H 2 | #define VAULT_CONTROLLER_H 3 | 4 | #include "Views/IView.h" 5 | #include "Inputs/IInput.h" 6 | #include "Selectors/HorizontalSelector.h" 7 | #include "Selectors/VerticalSelector.h" 8 | #include 9 | #include 10 | #include "Services/SdService.h" 11 | #include "Services/NvsService.h" 12 | #include "Services/CategoryService.h" 13 | #include "Services/EntryService.h" 14 | #include "Services/CryptoService.h" 15 | #include "Enums/ActionEnum.h" 16 | #include "Transformers/JsonTransformer.h" 17 | #include "Transformers/ModelTransformer.h" 18 | #include "States/GlobalState.h" 19 | #include "Models/VaultFile.h" 20 | 21 | class VaultController { 22 | public: 23 | VaultController(IView& display, 24 | IInput& input, 25 | HorizontalSelector& horizontalSelector, 26 | VerticalSelector& verticalSelector, 27 | ConfirmationSelector& confirmationSelector, 28 | StringPromptSelector& stringPromptSelector, 29 | SdService& sdService, 30 | NvsService& nvsService, 31 | CategoryService& categoryService, 32 | EntryService& entryService, 33 | CryptoService& cryptoService, 34 | JsonTransformer& jsonTransformer, 35 | ModelTransformer& modelTransformer); 36 | 37 | ActionEnum actionNoVault(); 38 | ActionEnum actionVaultSelected(); 39 | bool handleVaultCreation(); 40 | bool handleVaultLoading(); 41 | bool handleVaultSave(); 42 | 43 | private: 44 | bool loadDataFromEncryptedFile(std::string path); 45 | bool loadSdVault(); 46 | 47 | IView& display; 48 | IInput& input; 49 | HorizontalSelector& horizontalSelector; 50 | VerticalSelector& verticalSelector; 51 | ConfirmationSelector& confirmationSelector; 52 | StringPromptSelector& stringPromptSelector; 53 | SdService& sdService; 54 | NvsService& nvsService; 55 | CategoryService& categoryService; 56 | EntryService& entryService; 57 | CryptoService& cryptoService; 58 | JsonTransformer& jsonTransformer; 59 | ModelTransformer& modelTransformer; 60 | 61 | GlobalState& globalState = GlobalState::getInstance(); 62 | }; 63 | 64 | #endif // VAULT_CONTROLLER_H 65 | -------------------------------------------------------------------------------- /src/Controllers/EntryController.h: -------------------------------------------------------------------------------- 1 | #ifndef ENTRY_CONTROLLER_H 2 | #define ENTRY_CONTROLLER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | class EntryController { 25 | public: 26 | EntryController(IView& display, 27 | IInput& input, 28 | HorizontalSelector& horizontalSelector, 29 | VerticalSelector& verticalSelector, 30 | FieldActionSelector& fieldActionSelector, 31 | ConfirmationSelector& confirmationSelector, 32 | StringPromptSelector& stringPromptSelector, 33 | EntryService& entryService, 34 | CryptoService& cryptoService, 35 | UsbService& usbService, 36 | LedService& ledService, 37 | NvsService& nvsService, 38 | ModelTransformer& modelTransformer); 39 | 40 | ActionEnum actionFieldSelected(Field field); 41 | 42 | Entry handleEntrySelection(); 43 | Field handleFieldSelection(Entry& selectedEntry); 44 | 45 | bool handleEntryCreation(); 46 | bool handleEntryUpdate(Entry& entry, Field& field); 47 | bool handleEntryDeletion(); 48 | 49 | private: 50 | IView& display; 51 | IInput& input; 52 | HorizontalSelector& horizontalSelector; 53 | VerticalSelector& verticalSelector; 54 | FieldActionSelector& fieldActionSelector; 55 | ConfirmationSelector& confirmationSelector; 56 | StringPromptSelector& stringPromptSelector; 57 | EntryService& entryService; 58 | CryptoService& cryptoService; 59 | UsbService& usbService; 60 | LedService& ledService; 61 | NvsService& nvsService; 62 | ModelTransformer& modelTransformer; 63 | 64 | GlobalState& globalState = GlobalState::getInstance(); 65 | }; 66 | 67 | #endif // ENTRY_CONTROLLER_H 68 | -------------------------------------------------------------------------------- /src/Selectors/FieldEditorSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "FieldEditorSelector.h" 2 | 3 | FieldEditorSelector::FieldEditorSelector(IView& display, IInput& input) 4 | : display(display), input(input) {} 5 | 6 | std::vector FieldEditorSelector::select(const std::vector& fieldNames, 7 | const std::vector& fieldValues, 8 | const std::string& title) { 9 | 10 | int currentIndex = 0; 11 | std::vector editableFields = fieldValues; 12 | 13 | display.topBar(title.empty() ? "Edit Fields:" : title, false, false); 14 | 15 | while (true) { 16 | std::vector displayLines; 17 | for (size_t i = 0; i < editableFields.size(); ++i) { 18 | std::string line = (i == currentIndex ? "> " : " "); 19 | line += fieldNames[i] + ": " + editableFields[i]; 20 | displayLines.push_back(line); 21 | } 22 | display.verticalSelection(displayLines, currentIndex); 23 | 24 | char key = input.handler(); 25 | 26 | switch (key) { 27 | case KEY_ARROW_UP: 28 | currentIndex = (currentIndex > 0) ? currentIndex - 1 : editableFields.size() - 1; 29 | break; 30 | 31 | case KEY_ARROW_DOWN: 32 | currentIndex = (currentIndex < editableFields.size() - 1) ? currentIndex + 1 : 0; 33 | break; 34 | 35 | case KEY_OK: 36 | case KEY_RETURN_CUSTOM: 37 | return editableFields; 38 | 39 | case KEY_DEL: 40 | editableFields[currentIndex] = processUserInput(editableFields[currentIndex], key); 41 | break; 42 | 43 | default: // add char input 44 | if (std::isalnum(key) || std::ispunct(key)) { 45 | editableFields[currentIndex] = processUserInput(editableFields[currentIndex], key); 46 | } 47 | break; 48 | } 49 | 50 | // Mettre à jour la barre supérieure 51 | display.topBar(title, false, false); 52 | } 53 | } 54 | 55 | std::string FieldEditorSelector::processUserInput(const std::string& currentValue, char key) { 56 | std::string updatedValue = currentValue; 57 | if (key == KEY_DEL && !updatedValue.empty()) { 58 | updatedValue.pop_back(); 59 | } else if (std::isalnum(key) || std::ispunct(key)) { 60 | updatedValue += key; 61 | } 62 | return updatedValue; 63 | } 64 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/USBHID.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | #include 17 | #include 18 | #include "sdkconfig.h" 19 | 20 | #if CONFIG_TINYUSB_HID_ENABLED 21 | #include "esp_event.h" 22 | #include "class/hid/hid.h" 23 | #include "class/hid/hid_device.h" 24 | 25 | // Used by the included TinyUSB drivers 26 | enum { 27 | HID_REPORT_ID_NONE, 28 | HID_REPORT_ID_KEYBOARD, 29 | HID_REPORT_ID_MOUSE, 30 | HID_REPORT_ID_GAMEPAD, 31 | HID_REPORT_ID_CONSUMER_CONTROL, 32 | HID_REPORT_ID_SYSTEM_CONTROL, 33 | HID_REPORT_ID_VENDOR 34 | }; 35 | 36 | ESP_EVENT_DECLARE_BASE(ARDUINO_USB_HID_EVENTS); 37 | 38 | typedef enum { 39 | ARDUINO_USB_HID_ANY_EVENT = ESP_EVENT_ANY_ID, 40 | ARDUINO_USB_HID_SET_PROTOCOL_EVENT = 0, 41 | ARDUINO_USB_HID_SET_IDLE_EVENT, 42 | ARDUINO_USB_HID_MAX_EVENT, 43 | } arduino_usb_hid_event_t; 44 | 45 | typedef struct { 46 | uint8_t instance; 47 | union { 48 | struct { 49 | uint8_t protocol; 50 | } set_protocol; 51 | struct { 52 | uint8_t idle_rate; 53 | } set_idle; 54 | }; 55 | } arduino_usb_hid_event_data_t; 56 | 57 | class USBHIDDevice 58 | { 59 | public: 60 | virtual uint16_t _onGetDescriptor(uint8_t* buffer){return 0;} 61 | virtual uint16_t _onGetFeature(uint8_t report_id, uint8_t* buffer, uint16_t len){return 0;} 62 | virtual void _onSetFeature(uint8_t report_id, const uint8_t* buffer, uint16_t len){} 63 | virtual void _onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t len){} 64 | }; 65 | 66 | class USBHID 67 | { 68 | public: 69 | USBHID(void); 70 | void begin(void); 71 | void end(void); 72 | bool ready(void); 73 | bool SendReport(uint8_t report_id, const void* data, size_t len, uint32_t timeout_ms = 100); 74 | void onEvent(esp_event_handler_t callback); 75 | void onEvent(arduino_usb_hid_event_t event, esp_event_handler_t callback); 76 | static bool addDevice(USBHIDDevice * device, uint16_t descriptor_len); 77 | }; 78 | 79 | #endif /* CONFIG_TINYUSB_HID_ENABLED */ 80 | -------------------------------------------------------------------------------- /test/Selectors/TestVerticalSelector.cpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef TEST_VERTICAL_SELECTORS_H 3 | #define TEST_VERTICAL_SELECTORS_H 4 | 5 | #include 6 | #include "../src/Selectors/VerticalSelector.h" 7 | #include "../src/Selectors/HorizontalSelector.h" 8 | #include "../src/Managers/InactivityManager.h" 9 | #include "../Views/MockView.h" 10 | #include "../Inputs/MockInput.h" 11 | 12 | 13 | void test_vertical_selector_confirm() { 14 | MockView mockView; 15 | MockInput mockInput; 16 | InactivityManager manager(mockView); 17 | VerticalSelector verticalSelector(mockView, mockInput, manager); 18 | 19 | std::vector options = {"Option1", "Option2", "Option3"}; 20 | std::string title = "Vertical Selector Test"; 21 | 22 | // Mock Input 23 | mockInput.enqueueKey(KEY_ARROW_DOWN); 24 | mockInput.enqueueKey(KEY_ARROW_DOWN); 25 | mockInput.enqueueKey(KEY_ARROW_UP); 26 | mockInput.enqueueKey(KEY_OK); 27 | 28 | int selectedIndex = verticalSelector.select(title, options); 29 | 30 | TEST_ASSERT_EQUAL(1, selectedIndex); // Option 2 (index 1) selected 31 | TEST_ASSERT_TRUE(mockView.topBarCalled); 32 | TEST_ASSERT_TRUE(mockView.verticalSelectionCalled); 33 | TEST_ASSERT_EQUAL_STRING(title.c_str(), mockView.lastTitle.c_str()); 34 | TEST_ASSERT_EQUAL_STRING("Option2", mockView.displayedOptions[selectedIndex].c_str()); 35 | } 36 | 37 | void test_vertical_selector_cancel() { 38 | MockView mockView; 39 | MockInput mockInput; 40 | InactivityManager manager(mockView); 41 | VerticalSelector verticalSelector(mockView, mockInput, manager); 42 | 43 | std::vector options = {"Option1", "Option2", "Option3"}; 44 | std::string title = "Vertical Selector Test"; 45 | 46 | // Mock input 47 | mockInput.enqueueKey(KEY_ARROW_LEFT); 48 | 49 | int selectedIndex = verticalSelector.select(title, options); 50 | 51 | TEST_ASSERT_EQUAL(-1, selectedIndex); // Option 3 is selected 52 | } 53 | 54 | void test_vertical_selector_shortcut() { 55 | MockView mockView; 56 | MockInput mockInput; 57 | InactivityManager manager(mockView); 58 | VerticalSelector verticalSelector(mockView, mockInput, manager); 59 | 60 | std::vector options = {"Open Vault", "Create Vault", "Settings"}; 61 | std::vector shortcuts = {"O", "C", "S"}; 62 | std::string title = "Vertical Selector Test"; 63 | 64 | // Mock input for create vault 65 | mockInput.enqueueKey('C'); 66 | 67 | int selectedIndex = verticalSelector.select(title, options, false, false, {}, shortcuts, false, false); 68 | 69 | TEST_ASSERT_EQUAL(1, selectedIndex); // "Create Vault" index 1 70 | } 71 | 72 | #endif // TEST_VERTICAL_SELECTORS_H 73 | -------------------------------------------------------------------------------- /src/Models/VaultFile.h: -------------------------------------------------------------------------------- 1 | #ifndef VAULT_FILE_H 2 | #define VAULT_FILE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class VaultFile { 9 | private: 10 | std::string path; 11 | std::vector data; // raw data (salt + checksum + encryted data) 12 | 13 | GlobalState& globalState = GlobalState::getInstance(); 14 | 15 | public: 16 | // Constructeur 17 | VaultFile(const std::string& filePath, const std::vector& rawData) 18 | : path(filePath), data(rawData) {} 19 | 20 | // Accesseurs 21 | const std::string& getPath() const { return path; } 22 | 23 | std::vector getSalt() const { 24 | size_t saltSize = globalState.getSaltSize(); 25 | if (data.size() >= saltSize) { 26 | return {data.begin(), data.begin() + saltSize}; 27 | } 28 | return {}; 29 | } 30 | 31 | std::vector getChecksum() const { 32 | size_t saltSize = globalState.getSaltSize(); 33 | size_t checksumSize = globalState.getChecksumSize(); 34 | if (data.size() >= saltSize + checksumSize) { 35 | return {data.begin() + saltSize, data.begin() + saltSize + checksumSize}; 36 | } 37 | return {}; 38 | } 39 | 40 | std::vector getData() const { 41 | return data; 42 | } 43 | 44 | std::vector getEncryptedData() const { 45 | size_t saltSize = globalState.getSaltSize(); 46 | size_t checksumSize = globalState.getChecksumSize(); 47 | if (data.size() > saltSize + checksumSize) { 48 | return {data.begin() + saltSize + checksumSize, data.end()}; 49 | } 50 | return {}; 51 | } 52 | 53 | // Mutateurs 54 | void setPath(const std::string& filePath) { path = filePath; } 55 | 56 | void setData(const std::vector& rawData) { data = rawData; } 57 | 58 | void setSalt(const std::vector& salt) { 59 | data.insert(data.begin(), salt.begin(), salt.end()); 60 | } 61 | 62 | void setChecksum(const std::vector& checksum) { 63 | size_t saltSize = globalState.getSaltSize(); 64 | data.insert(data.begin() + saltSize, checksum.begin(), checksum.end()); 65 | } 66 | 67 | void setEncryptedData(const std::vector& encryptedData) { 68 | size_t saltSize = globalState.getSaltSize(); 69 | size_t checksumSize = globalState.getChecksumSize(); 70 | 71 | if (data.size() < saltSize + checksumSize) { 72 | data.resize(saltSize + checksumSize, 0); // Initialize with 0 73 | } 74 | 75 | // Erase old data 76 | data.erase(data.begin() + saltSize + checksumSize, data.end()); 77 | 78 | // Add new data 79 | data.insert(data.end(), encryptedData.begin(), encryptedData.end()); 80 | } 81 | 82 | }; 83 | 84 | #endif // VAULT_FILE_H 85 | -------------------------------------------------------------------------------- /test/Selectors/TestFieldEditorSelector.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_FIELD_EDITOR_SELECTOR_H 2 | #define TEST_FIELD_EDITOR_SELECTOR_H 3 | 4 | #include 5 | #include "../src/Selectors/FieldEditorSelector.h" 6 | #include "../Views/MockView.h" 7 | #include "../Inputs/MockInput.h" 8 | 9 | void test_field_editor_selector_confirm() { 10 | MockView mockView; 11 | MockInput mockInput; 12 | 13 | FieldEditorSelector fieldEditor(mockView, mockInput); 14 | 15 | std::vector fieldNames = {"Name", "Age", "Email"}; 16 | std::vector fieldValues = {"John", "30", "john@example.com"}; 17 | std::string title = "Edit Fields"; 18 | 19 | // Mock input 20 | mockInput.enqueueKey(KEY_ARROW_DOWN); // go to "Age" 21 | mockInput.enqueueKey(KEY_DEL); // Erase 0 to "Age" 22 | mockInput.enqueueKey('3'); // add "3" to "Age" 23 | mockInput.enqueueKey(KEY_ARROW_DOWN); // Go to mail 24 | mockInput.enqueueKey('!'); // Add ! 25 | mockInput.enqueueKey(KEY_ARROW_UP); // Go to "Age" 26 | mockInput.enqueueKey(KEY_DEL); // Erase 3 27 | mockInput.enqueueKey('7'); // Add 7 28 | mockInput.enqueueKey(KEY_OK); // Confirm 29 | 30 | auto modifiedFields = fieldEditor.select(fieldNames, fieldValues, title); 31 | 32 | // Vérifier les résultats 33 | TEST_ASSERT_EQUAL(3, modifiedFields.size()); 34 | TEST_ASSERT_EQUAL_STRING("John", modifiedFields[0].c_str()); 35 | TEST_ASSERT_EQUAL_STRING("37", modifiedFields[1].c_str()); 36 | TEST_ASSERT_EQUAL_STRING("john@example.com!", modifiedFields[2].c_str()); 37 | 38 | TEST_ASSERT_TRUE(mockView.topBarCalled); 39 | TEST_ASSERT_TRUE(mockView.verticalSelectionCalled); 40 | TEST_ASSERT_EQUAL_STRING(title.c_str(), mockView.lastTitle.c_str()); 41 | } 42 | 43 | void test_field_editor_selector_cancel() { 44 | MockView mockView; 45 | MockInput mockInput; 46 | 47 | FieldEditorSelector fieldEditor(mockView, mockInput); 48 | 49 | std::vector fieldNames = {"Name", "Age", "Email"}; 50 | std::vector fieldValues = {"John", "30", "john@example.com"}; 51 | std::string title = "Edit Fields"; 52 | 53 | // Mock input 54 | mockInput.enqueueKey(KEY_RETURN_CUSTOM); 55 | 56 | auto modifiedFields = fieldEditor.select(fieldNames, fieldValues, title); 57 | 58 | // Vérifier que les champs originaux sont renvoyés (aucune modification) 59 | TEST_ASSERT_EQUAL(3, modifiedFields.size()); 60 | TEST_ASSERT_EQUAL_STRING("John", modifiedFields[0].c_str()); 61 | TEST_ASSERT_EQUAL_STRING("30", modifiedFields[1].c_str()); 62 | TEST_ASSERT_EQUAL_STRING("john@example.com", modifiedFields[2].c_str()); 63 | 64 | TEST_ASSERT_TRUE(mockView.topBarCalled); 65 | TEST_ASSERT_TRUE(mockView.verticalSelectionCalled); 66 | TEST_ASSERT_EQUAL_STRING(title.c_str(), mockView.lastTitle.c_str()); 67 | } 68 | 69 | #endif // TEST_FIELD_EDITOR_SELECTOR_H 70 | -------------------------------------------------------------------------------- /src/Managers/InactivityManager.h: -------------------------------------------------------------------------------- 1 | #ifndef INACTIVITY_MANAGER_H 2 | #define INACTIVITY_MANAGER_H 3 | 4 | #include "../Views/IView.h" 5 | #include "../Services/EntryService.h" 6 | #include "../States/GlobalState.h" 7 | #include 8 | #include 9 | 10 | class InactivityManager { 11 | private: 12 | IView& display; 13 | std::chrono::steady_clock::time_point lastInteractionTime; 14 | 15 | bool isDimmed = false; 16 | bool isShutdown = false; 17 | bool isLocked = false; 18 | 19 | GlobalState& globalState = GlobalState::getInstance(); 20 | 21 | public: 22 | InactivityManager(IView& display) : display(display) { 23 | lastInteractionTime = std::chrono::steady_clock::now(); 24 | } 25 | 26 | void reset() { 27 | lastInteractionTime = std::chrono::steady_clock::now(); 28 | globalState.setVaultIsLocked(false); 29 | if (isDimmed || isShutdown) { 30 | restoreScreen(); 31 | } 32 | isLocked = false; 33 | } 34 | 35 | void update() { 36 | auto now = std::chrono::steady_clock::now(); 37 | auto elapsedMs = std::chrono::duration_cast(now - lastInteractionTime).count(); 38 | 39 | // **Réduction de la luminosité** 40 | if (!isDimmed && elapsedMs >= globalState.getInactivityBrightnessTimeout()) { 41 | dimScreen(); 42 | } 43 | 44 | // **Extinction complète de l'écran** 45 | if (!isShutdown && elapsedMs >= globalState.getInactivityScreenTimeout()) { 46 | shutdownScreen(); 47 | } 48 | 49 | // **Verrouillage du coffre** 50 | if (!isLocked && elapsedMs >= globalState.getInactivityLockTimeout()) { 51 | lockVault(); 52 | } 53 | } 54 | 55 | void dimScreen() { 56 | uint16_t currentBrightness = display.getBrightness(); 57 | while (currentBrightness > 20) { 58 | currentBrightness -= 1; // Diminue progressivement 59 | display.setBrightness(currentBrightness); 60 | delay(5); 61 | } 62 | isDimmed = true; 63 | } 64 | 65 | void shutdownScreen() { 66 | uint16_t currentBrightness = display.getBrightness(); 67 | while (currentBrightness > 1) { 68 | currentBrightness -= 1; // Diminue progressivement 69 | display.setBrightness(currentBrightness); 70 | delay(5); 71 | } 72 | isShutdown = true; 73 | } 74 | 75 | void restoreScreen() { 76 | display.setBrightness(globalState.getSelectedScreenBrightness()); 77 | isDimmed = false; 78 | isShutdown = false; 79 | } 80 | 81 | void lockVault() { 82 | shutdownScreen(); 83 | globalState.setVaultIsLocked(true); 84 | isShutdown = true; 85 | isLocked = true; 86 | } 87 | 88 | bool getVaultIsLocked() const { 89 | return isLocked; 90 | } 91 | 92 | void setVaultIsLocked(bool lockState) { 93 | isLocked = lockState; 94 | } 95 | }; 96 | 97 | #endif // INACTIVITY_MANAGER_H 98 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout.h: -------------------------------------------------------------------------------- 1 | /* 2 | KeyboardLayout.h 3 | 4 | This file is not part of the public API. It is meant to be included 5 | only in Keyboard.cpp and the keyboard layout files. Layout files map 6 | ASCII character codes to keyboard scan codes (technically, to USB HID 7 | Usage codes), possibly altered by the SHIFT or ALT_GR modifiers. 8 | Non-ACSII characters (anything outside the 7-bit range NUL..DEL) are 9 | not supported. 10 | 11 | == Creating your own layout == 12 | 13 | In order to create your own layout file, copy an existing layout that 14 | is similar to yours, then modify it to use the correct keys. The 15 | layout is an array in ASCII order. Each entry contains a scan code, 16 | possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from 17 | the Italian layout: 18 | 19 | 0x35, // bslash 20 | 0x30|ALT_GR, // ] 21 | 0x2e|SHIFT, // ^ 22 | 23 | Do not change the control characters (those before scan code 0x2c, 24 | corresponding to space). Do not attempt to grow the table past DEL. Do 25 | not use both SHIFT and ALT_GR on the same character: this is not 26 | supported. Unsupported characters should have 0x00 as scan code. 27 | 28 | For a keyboard with an ISO physical layout, use the scan codes below: 29 | 30 | +---+---+---+---+---+---+---+---+---+---+---+---+---+-------+ 31 | |35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp | 32 | +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+ 33 | | Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret | 34 | +-----++--++--++--++--++--++--++--++--++--++--++--++--++ | 35 | |CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | | 36 | +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+ 37 | |Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift | 38 | +----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+ 39 | |Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl| 40 | +----+----+----+------------------------+----+----+----+----+ 41 | 42 | The ANSI layout is identical except that key 0x31 is above (rather 43 | than next to) Return, and there is not key 0x32. 44 | 45 | Give a unique name to the layout array, then declare it in Keyboard.h 46 | with a line of the form: 47 | 48 | extern const uint8_t KeyboardLayout_xx_YY[]; 49 | 50 | == Encoding details == 51 | 52 | All scan codes are less than 0x80, which makes bit 7 available to 53 | signal that a modifier (Shift or AltGr) is needed to generate the 54 | character. With only one exception, keys that are used with modifiers 55 | have scan codes that are less than 0x40. This makes bit 6 available 56 | to signal whether the modifier is Shift or AltGr. The exception is 57 | 0x64, the key next next to Left Shift on the ISO layout (and absent 58 | from the ANSI layout). We handle it by replacing its value by 0x32 in 59 | the layout arrays. 60 | */ 61 | 62 | #include 63 | 64 | #define SHIFT 0x80 65 | #define ALT_GR 0xc0 66 | #define ISO_KEY 0x64 67 | #define ISO_REPLACEMENT 0x32 68 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/Keyboard_en_UK.h: -------------------------------------------------------------------------------- 1 | /* 2 | KeyboardLayout.h 3 | 4 | This file is not part of the public API. It is meant to be included 5 | only in Keyboard.cpp and the keyboard layout files. Layout files map 6 | ASCII character codes to keyboard scan codes (technically, to USB HID 7 | Usage codes), possibly altered by the SHIFT or ALT_GR modifiers. 8 | Non-ACSII characters (anything outside the 7-bit range NUL..DEL) are 9 | not supported. 10 | 11 | == Creating your own layout == 12 | 13 | In order to create your own layout file, copy an existing layout that 14 | is similar to yours, then modify it to use the correct keys. The 15 | layout is an array in ASCII order. Each entry contains a scan code, 16 | possibly modified by "|SHIFT" or "|ALT_GR", as in this excerpt from 17 | the Italian layout: 18 | 19 | 0x35, // bslash 20 | 0x30|ALT_GR, // ] 21 | 0x2e|SHIFT, // ^ 22 | 23 | Do not change the control characters (those before scan code 0x2c, 24 | corresponding to space). Do not attempt to grow the table past DEL. Do 25 | not use both SHIFT and ALT_GR on the same character: this is not 26 | supported. Unsupported characters should have 0x00 as scan code. 27 | 28 | For a keyboard with an ISO physical layout, use the scan codes below: 29 | 30 | +---+---+---+---+---+---+---+---+---+---+---+---+---+-------+ 31 | |35 |1e |1f |20 |21 |22 |23 |24 |25 |26 |27 |2d |2e |BackSp | 32 | +---+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-----+ 33 | | Tab |14 |1a |08 |15 |17 |1c |18 |0c |12 |13 |2f |30 | Ret | 34 | +-----++--++--++--++--++--++--++--++--++--++--++--++--++ | 35 | |CapsL |04 |16 |07 |09 |0a |0b |0d |0e |0f |33 |34 |31 | | 36 | +----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+---+----+ 37 | |Shi.|32 |1d |1b |06 |19 |05 |11 |10 |36 |37 |38 | Shift | 38 | +----+---++--+-+-+---+---+---+---+---+--++---+---++----+----+ 39 | |Ctrl|Win |Alt | |AlGr|Win |Menu|Ctrl| 40 | +----+----+----+------------------------+----+----+----+----+ 41 | 42 | The ANSI layout is identical except that key 0x31 is above (rather 43 | than next to) Return, and there is not key 0x32. 44 | 45 | Give a unique name to the layout array, then declare it in Keyboard.h 46 | with a line of the form: 47 | 48 | extern const uint8_t KeyboardLayout_xx_YY[]; 49 | 50 | == Encoding details == 51 | 52 | All scan codes are less than 0x80, which makes bit 7 available to 53 | signal that a modifier (Shift or AltGr) is needed to generate the 54 | character. With only one exception, keys that are used with modifiers 55 | have scan codes that are less than 0x40. This makes bit 6 available 56 | to signal whether the modifier is Shift or AltGr. The exception is 57 | 0x64, the key next next to Left Shift on the ISO layout (and absent 58 | from the ANSI layout). We handle it by replacing its value by 0x32 in 59 | the layout arrays. 60 | */ 61 | 62 | #include 63 | 64 | #define SHIFT 0x80 65 | #define ALT_GR 0xc0 66 | #define ISO_KEY 0x64 67 | #define ISO_REPLACEMENT 0x32 68 | -------------------------------------------------------------------------------- /test/Views/MockView.h: -------------------------------------------------------------------------------- 1 | #ifndef MOCK_VIEW_H 2 | #define MOCK_VIEW_H 3 | 4 | #include "../src/Views/IView.h" 5 | #include 6 | #include 7 | 8 | class MockView : public IView { 9 | public: 10 | MockView() {} 11 | 12 | void initialize() override { 13 | initialized = true; 14 | } 15 | 16 | void welcome(uint8_t defaultBrightness) override { 17 | welcomeCalled = true; 18 | } 19 | 20 | void setBrightness(uint16_t brightness) override { 21 | this->brightness = brightness; 22 | } 23 | 24 | uint8_t getBrightness() override { 25 | return this->brightness; 26 | } 27 | 28 | void topBar(const std::string& title, bool submenu, bool searchBar) override { 29 | lastTitle = title; 30 | this->submenu = submenu; 31 | this->searchBar = searchBar; 32 | topBarCalled = true; 33 | } 34 | 35 | void horizontalSelection(const std::vector& options, uint16_t selectedIndex, const std::string& description1 = "", const std::string& description2 = "", const std::vector& icons = {}) override { 36 | displayedOptions = options; 37 | lastSelectedIndex = selectedIndex; 38 | horizontalSelectionCalled = true; 39 | } 40 | 41 | void verticalSelection( 42 | const std::vector& options, 43 | uint16_t selectedIndex, 44 | size_t visibleRows, 45 | const std::vector& optionLabels, 46 | const std::vector& shortcuts, 47 | bool visibleMention) override { 48 | 49 | displayedOptions = options; 50 | lastSelectedIndex = selectedIndex; 51 | this->visibleRows = visibleRows; 52 | verticalSelectionCalled = true; 53 | } 54 | 55 | void value(std::string label, std::string val) { 56 | valueCalled = true; 57 | } 58 | 59 | void subMessage(std::string message, int delayMs) { 60 | message = message; 61 | subMessageCalled = true; 62 | } 63 | 64 | void confirmationPrompt(std::string label) { 65 | confirmationPromptCalled = true; 66 | } 67 | 68 | void stringPrompt(std::string label, std::string value, bool backButton, size_t minLength) { 69 | stringPromptCalled = true; 70 | } 71 | 72 | void debug(const std::string& message) override { 73 | debugMessage = message; 74 | debugCalled = true; 75 | } 76 | 77 | // Public attributes for testing 78 | bool initialized = false; 79 | uint16_t brightness = 0; 80 | std::string lastTitle; 81 | bool submenu = false; 82 | bool searchBar = false; 83 | std::vector displayedOptions; 84 | uint16_t lastSelectedIndex = -1; 85 | size_t visibleRows = 0; 86 | std::string message; 87 | std::string debugMessage; 88 | bool welcomeCalled = false; 89 | bool topBarCalled = false; 90 | bool verticalSelectionCalled = false; 91 | bool horizontalSelectionCalled = false; 92 | bool valueCalled = false; 93 | bool subMessageCalled = false; 94 | bool debugCalled = false; 95 | bool confirmationPromptCalled = false; 96 | bool stringPromptCalled = false; 97 | }; 98 | 99 | #endif // MOCK_VIEW_H 100 | -------------------------------------------------------------------------------- /test/Services/TestCategoryService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_CATEGORY_SERVICE 2 | #define TEST_CATEGORY_SERVICE 3 | 4 | #include 5 | #include "../src/Services/CategoryService.h" 6 | #include "../src/Repositories/CategoryRepository.h" 7 | 8 | void test_validateCategory() { 9 | CategoryRepository repository; 10 | CategoryService service(repository); 11 | 12 | Category validCategory(1, "Work", "#FF0000", "work-icon.png"); 13 | Category invalidCategory(2, "", "#00FF00", "home-icon.png"); 14 | 15 | TEST_ASSERT_TRUE(service.validateCategory(validCategory)); 16 | TEST_ASSERT_FALSE(service.validateCategory(invalidCategory)); 17 | } 18 | 19 | void test_add_and_find_category() { 20 | CategoryRepository repository; 21 | CategoryService service(repository); 22 | 23 | Category category(1, "Work", "#FF0000", "work-icon.png"); 24 | service.addCategory(category); 25 | 26 | Category foundCategory = service.findCategoryByIndex(1); 27 | 28 | TEST_ASSERT_EQUAL_STRING("Work", foundCategory.getName().c_str()); 29 | TEST_ASSERT_EQUAL_STRING("#FF0000", foundCategory.getColorCode().c_str()); 30 | } 31 | 32 | void test_update_category() { 33 | CategoryRepository repository; 34 | CategoryService service(repository); 35 | 36 | Category category(1, "Work", "#FF0000", "work-icon.png"); 37 | service.addCategory(category); 38 | 39 | Category updatedCategory(1, "Home", "#00FF00", "home-icon.png"); 40 | service.updateCategory(1, updatedCategory); 41 | 42 | Category foundCategory = service.findCategoryByIndex(1); 43 | TEST_ASSERT_EQUAL_STRING("Home", foundCategory.getName().c_str()); 44 | TEST_ASSERT_EQUAL_STRING("#00FF00", foundCategory.getColorCode().c_str()); 45 | } 46 | 47 | void test_sort_categories_by_name() { 48 | CategoryRepository repository; 49 | CategoryService service(repository); 50 | 51 | service.addCategory(Category(2, "Work", "#FF0000", "work-icon.png")); 52 | service.addCategory(Category(1, "Home", "#00FF00", "home-icon.png")); 53 | 54 | auto sortedCategories = service.sortCategoriesByName(); 55 | 56 | TEST_ASSERT_EQUAL(2, sortedCategories.size()); 57 | TEST_ASSERT_EQUAL_STRING("Home", sortedCategories[0].getName().c_str()); 58 | TEST_ASSERT_EQUAL_STRING("Work", sortedCategories[1].getName().c_str()); 59 | } 60 | 61 | void test_get_all_categories() { 62 | CategoryRepository repository; 63 | CategoryService service(repository); 64 | 65 | service.addCategory(Category(1, "Work", "#FF0000", "work-icon.png")); 66 | service.addCategory(Category(2, "Home", "#00FF00", "home-icon.png")); 67 | 68 | auto categories = service.getAllCategories(); 69 | 70 | TEST_ASSERT_EQUAL(2, categories.size()); 71 | TEST_ASSERT_EQUAL_STRING("Work", categories[0].getName().c_str()); 72 | TEST_ASSERT_EQUAL_STRING("Home", categories[1].getName().c_str()); 73 | } 74 | 75 | void test_delete_category() { 76 | CategoryRepository repository; 77 | CategoryService service(repository); 78 | 79 | service.addCategory(Category(1, "Work", "#FF0000", "work-icon.png")); 80 | bool result = repository.deleteCategoryByIndex(1); 81 | 82 | TEST_ASSERT_TRUE(result); 83 | 84 | Category foundCategory = service.findCategoryByIndex(1); 85 | TEST_ASSERT_TRUE(foundCategory.getName().empty()); 86 | } 87 | 88 | #endif // TEST_CATEGORY_SERVICE 89 | -------------------------------------------------------------------------------- /test/Transformers/TestJsonTransformer.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_JSON_TRANSFORMER 2 | #define TEST_JSON_TRANSFORMER 3 | #include 4 | #include "../src/Transformers/JsonTransformer.h" 5 | #include 6 | #include "../src/States/GlobalState.h" 7 | 8 | void test_to_json_categories() { 9 | JsonTransformer transformer; 10 | 11 | std::vector categories = { 12 | Category(1, "Personal", "#FF5733", "icon1.png"), 13 | Category(2, "Work", "#33FF57", "icon2.png"), 14 | }; 15 | 16 | std::string json = transformer.toJson(categories); 17 | 18 | TEST_ASSERT_NOT_EQUAL(0, json.size()); 19 | TEST_ASSERT_TRUE(json.find("Personal") != std::string::npos); 20 | TEST_ASSERT_TRUE(json.find("Work") != std::string::npos); 21 | } 22 | 23 | void test_from_json_to_entries() { 24 | JsonTransformer transformer; 25 | std::string jsonContent = R"({ 26 | "categories": [], 27 | "entries": [{ 28 | "id": "1", 29 | "serviceName": "Service1", 30 | "username": "User1", 31 | "password": "Pass1", 32 | "categoryIndex": 0, 33 | "notes": "Note1", 34 | "notes2": "Note2", 35 | "notes3": "Note3", 36 | "link": "http://example.com", 37 | "createdAt": 1672531200, 38 | "updatedAt": 1672531300, 39 | "expiresAt": 1672531400 40 | }] 41 | })"; 42 | 43 | std::vector entries = transformer.fromJsonToEntries(jsonContent); 44 | 45 | TEST_ASSERT_EQUAL(1, entries.size()); 46 | TEST_ASSERT_EQUAL_STRING("Service1", entries[0].getServiceName().c_str()); 47 | TEST_ASSERT_EQUAL(1672531200, entries[0].getCreatedAt()); 48 | } 49 | 50 | void test_from_json_to_categories() { 51 | JsonTransformer transformer; 52 | std::string jsonContent = R"({ 53 | "categories": [{ 54 | "index": 0, 55 | "name": "Social Media", 56 | "colorCode": "#FF5733", 57 | "iconPath": "icons/social.png" 58 | }, { 59 | "index": 1, 60 | "name": "Finance", 61 | "colorCode": "#33FF57", 62 | "iconPath": "icons/finance.png" 63 | }], 64 | "entries": [] 65 | })"; 66 | 67 | std::vector categories = transformer.fromJsonToCategories(jsonContent); 68 | 69 | TEST_ASSERT_EQUAL(2, categories.size()); 70 | TEST_ASSERT_EQUAL_STRING("Social Media", categories[0].getName().c_str()); 71 | TEST_ASSERT_EQUAL_STRING("#FF5733", categories[0].getColorCode().c_str()); 72 | } 73 | 74 | void test_merge_entries_and_categories_to_json() { 75 | JsonTransformer transformer; 76 | 77 | std::vector entries = { 78 | Entry("1", "Facebook", "user1", "encryptedPass1", 0), 79 | Entry("2", "Google", "user2", "encryptedPass2", 1) 80 | }; 81 | std::vector categories = { 82 | Category(0, "Social Media", "#FF5733", "icons/social.png"), 83 | Category(1, "Finance", "#33FF57", "icons/finance.png") 84 | }; 85 | 86 | std::string json = transformer.mergeEntriesAndCategoriesToJson(entries, categories); 87 | 88 | TEST_ASSERT_NOT_EQUAL(0, json.size()); 89 | TEST_ASSERT_TRUE(json.find("Facebook") != std::string::npos); 90 | TEST_ASSERT_TRUE(json.find("Google") != std::string::npos); 91 | TEST_ASSERT_TRUE(json.find("Social Media") != std::string::npos); 92 | TEST_ASSERT_TRUE(json.find("Finance") != std::string::npos); 93 | } 94 | 95 | #endif // TEST_JSON_TRANSFORMER 96 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_en_US.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Standard US keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_en_US[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x34|SHIFT, // " 45 | 0x20|SHIFT, // # 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x24|SHIFT, // & 49 | 0x34, // ' 50 | 0x26|SHIFT, // ( 51 | 0x27|SHIFT, // ) 52 | 0x25|SHIFT, // * 53 | 0x2e|SHIFT, // + 54 | 0x36, // , 55 | 0x2d, // - 56 | 0x37, // . 57 | 0x38, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x33|SHIFT, // : 69 | 0x33, // ; 70 | 0x36|SHIFT, // < 71 | 0x2e, // = 72 | 0x37|SHIFT, // > 73 | 0x38|SHIFT, // ? 74 | 0x1f|SHIFT, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x2f, // [ 102 | 0x31, // bslash 103 | 0x30, // ] 104 | 0x23|SHIFT, // ^ 105 | 0x2d|SHIFT, // _ 106 | 0x35, // ` 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x2f|SHIFT, // { 134 | 0x31|SHIFT, // | 135 | 0x30|SHIFT, // } 136 | 0x35|SHIFT, // ~ 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_fr_FR.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Traditional (not AFNOR) French keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_fr_FR[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x38, // ! 44 | 0x20, // " 45 | 0x20|ALT_GR, // # 46 | 0x30, // $ 47 | 0x34|SHIFT, // % 48 | 0x1E, // & 49 | 0x21, // ' 50 | 0x22, // ( 51 | 0x2d, // ) 52 | 0x31, // * 53 | 0x2e|SHIFT, // + 54 | 0x10, // , 55 | 0x23, // - 56 | 0x36|SHIFT, // . 57 | 0x37|SHIFT, // / 58 | 0x27|SHIFT, // 0 59 | 0x1e|SHIFT, // 1 60 | 0x1f|SHIFT, // 2 61 | 0x20|SHIFT, // 3 62 | 0x21|SHIFT, // 4 63 | 0x22|SHIFT, // 5 64 | 0x23|SHIFT, // 6 65 | 0x24|SHIFT, // 7 66 | 0x25|SHIFT, // 8 67 | 0x26|SHIFT, // 9 68 | 0x37, // : 69 | 0x36, // ; 70 | 0x32, // < 71 | 0x2e, // = 72 | 0x32|SHIFT, // > 73 | 0x10|SHIFT, // ? 74 | 0x27|ALT_GR, // @ 75 | 0x14|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x33|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x04|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1d|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1a|SHIFT, // Z 101 | 0x22|ALT_GR, // [ 102 | 0x25|ALT_GR, // bslash 103 | 0x2d|ALT_GR, // ] 104 | 0x26|ALT_GR, // ^ 105 | 0x25, // _ 106 | 0x24|ALT_GR, // ` 107 | 0x14, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x33, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x04, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1d, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1a, // z 133 | 0x21|ALT_GR, // { 134 | 0x23|ALT_GR, // | 135 | 0x2e|ALT_GR, // } 136 | 0x1f|ALT_GR, // ~ 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_en_UK.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Standard US keyboard layout. 3 | */ 4 | 5 | #include "Keyboard_en_UK.h" 6 | 7 | extern const uint8_t KeyboardLayout_en_UK[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " ok 45 | 0x31, // # ok 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x24|SHIFT, // & 49 | 0x34, // ' ok 50 | 0x26|SHIFT, // ( 51 | 0x27|SHIFT, // ) 52 | 0x25|SHIFT, // * 53 | 0x2e|SHIFT, // + 54 | 0x36, // , 55 | 0x2d, // - 56 | 0x37, // . 57 | 0x38, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x33|SHIFT, // : 69 | 0x33, // ; 70 | 0x36|SHIFT, // < 71 | 0x2e, // = 72 | 0x37|SHIFT, // > 73 | 0x38|SHIFT, // ? 74 | 0x34|SHIFT, // @ ok 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x2f, // [ 102 | 0x64, // bslash ok 103 | 0x30, // ] 104 | 0x23|SHIFT, // ^ 105 | 0x2d|SHIFT, // _ 106 | 0x35, // ` 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x2f|SHIFT, // { 134 | 0x35, // | ok 135 | 0x30|SHIFT, // } 136 | 0x31|SHIFT, // ~ ok 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_hu_HU.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Standard HU keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_hu_HU[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x21|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x1b|ALT_GR, // # 46 | 0x33|ALT_GR, // $ 47 | 0x22|SHIFT, // % 48 | 0x06|ALT_GR, // & 49 | 0x1e|SHIFT, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x38|ALT_GR, // * 53 | 0x20|SHIFT, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x23|SHIFT, // / 58 | 59 | 0x35, // 0 60 | 0x1e, // 1 61 | 0x1f, // 2 62 | 0x20, // 3 63 | 0x21, // 4 64 | 0x22, // 5 65 | 0x23, // 6 66 | 0x24, // 7 67 | 0x25, // 8 68 | 0x26, // 9 69 | 70 | 0x37|SHIFT, // : 71 | 0x36|ALT_GR, // ; 72 | 0x32|ALT_GR, // < 73 | 0x24|SHIFT, // = 74 | 0x1d|ALT_GR, // > 75 | 0x36|SHIFT, // ? 76 | 0x19|ALT_GR, // @ 77 | 78 | 0x04|SHIFT, // A 79 | 0x05|SHIFT, // B 80 | 0x06|SHIFT, // C 81 | 0x07|SHIFT, // D 82 | 0x08|SHIFT, // E 83 | 0x09|SHIFT, // F 84 | 0x0a|SHIFT, // G 85 | 0x0b|SHIFT, // H 86 | 0x0c|SHIFT, // I 87 | 0x0d|SHIFT, // J 88 | 0x0e|SHIFT, // K 89 | 0x0f|SHIFT, // L 90 | 0x10|SHIFT, // M 91 | 0x11|SHIFT, // N 92 | 0x12|SHIFT, // O 93 | 0x13|SHIFT, // P 94 | 0x14|SHIFT, // Q 95 | 0x15|SHIFT, // R 96 | 0x16|SHIFT, // S 97 | 0x17|SHIFT, // T 98 | 0x18|SHIFT, // U 99 | 0x19|SHIFT, // V 100 | 0x1a|SHIFT, // W 101 | 0x1b|SHIFT, // X 102 | 0x1d|SHIFT, // Y 103 | 0x1c|SHIFT, // Z 104 | 105 | 0x09|ALT_GR, // [ 106 | 0x14|ALT_GR, // bslash 107 | 0x0a|ALT_GR, // ] 108 | 0x20|ALT_GR, // ^ 109 | 0x38|SHIFT, // _ 110 | 0x24|ALT_GR, // ` 111 | 112 | 0x04, // a 113 | 0x05, // b 114 | 0x06, // c 115 | 0x07, // d 116 | 0x08, // e 117 | 0x09, // f 118 | 0x0a, // g 119 | 0x0b, // h 120 | 0x0c, // i 121 | 0x0d, // j 122 | 0x0e, // k 123 | 0x0f, // l 124 | 0x10, // m 125 | 0x11, // n 126 | 0x12, // o 127 | 0x13, // p 128 | 0x14, // q 129 | 0x15, // r 130 | 0x16, // s 131 | 0x17, // t 132 | 0x18, // u 133 | 0x19, // v 134 | 0x1a, // w 135 | 0x1b, // x 136 | 0x1d, // y 137 | 0x1c, // z 138 | 139 | 0x05|ALT_GR, // { 140 | 0x1a|ALT_GR, // | 141 | 0x11|ALT_GR, // } 142 | 0x1e|ALT_GR, // ~ 143 | 0x00 // DEL 144 | }; 145 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_de_DE.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * German keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_de_DE[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x31, // # 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x31|SHIFT, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x30|SHIFT, // * 53 | 0x30, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x14|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1d|SHIFT, // Y 100 | 0x1c|SHIFT, // Z 101 | 0x25|ALT_GR, // [ 102 | 0x2d|ALT_GR, // bslash 103 | 0x26|ALT_GR, // ] 104 | 0x00, // ^ not supported (requires dead key + space) 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not supported (requires dead key + space) 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1d, // y 132 | 0x1c, // z 133 | 0x24|ALT_GR, // { 134 | 0x32|ALT_GR, // | 135 | 0x27|ALT_GR, // } 136 | 0x30|ALT_GR, // ~ 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_it_IT.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Italian keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_it_IT[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x34|ALT_GR, // # 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x2d, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x30|SHIFT, // * 53 | 0x30, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x33|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x2f|ALT_GR, // [ 102 | 0x35, // bslash 103 | 0x30|ALT_GR, // ] 104 | 0x2e|SHIFT, // ^ 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not in this layout 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x00, // { not supported (requires AltGr+Shift) 134 | 0x35|SHIFT, // | 135 | 0x00, // } not supported (requires AltGr+Shift) 136 | 0x00, // ~ not in this layout 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_da_DK.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Danish keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_da_DK[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x20|SHIFT, // # 46 | 0x21|ALT_GR, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x31, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x31|SHIFT, // * 53 | 0x2d, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x1f|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x25|ALT_GR, // [ 102 | 0x32|ALT_GR, // bslash 103 | 0x26|ALT_GR, // ] 104 | 0x00, // ^ not supported (requires dead key + space) 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not supported (requires dead key + space) 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x24|ALT_GR, // { 134 | 0x2e|ALT_GR, // | 135 | 0x27|ALT_GR, // } 136 | 0x00, // ~ not supported (requires dead key + space) 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_es_ES.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Spanish keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_es_ES[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x20|ALT_GR, // # 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x2d, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x30|SHIFT, // * 53 | 0x30, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x1f|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x2f|ALT_GR, // [ 102 | 0x35|ALT_GR, // bslash 103 | 0x30|ALT_GR, // ] 104 | 0x00, // ^ not supported (requires dead key + space) 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not supported (requires dead key + space) 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x34|ALT_GR, // { 134 | 0x1e|ALT_GR, // | 135 | 0x31|ALT_GR, // } 136 | 0x00, // ~ not supported (requires dead key + space) 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_sv_SE.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Swedish keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_sv_SE[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x20|SHIFT, // # 46 | 0x21|ALT_GR, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x31, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x31|SHIFT, // * 53 | 0x2d, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x1f|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x25|ALT_GR, // [ 102 | 0x2d|ALT_GR, // bslash 103 | 0x26|ALT_GR, // ] 104 | 0x00, // ^ not supported (requires dead key + space) 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not supported (requires dead key + space) 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x24|ALT_GR, // { 134 | 0x32|ALT_GR, // | 135 | 0x27|ALT_GR, // } 136 | 0x00, // ~ not supported (requires dead key + space) 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_pt_PT.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Portuguese keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_pt_PT[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 0x2a, // BS Backspace 18 | 0x2b, // TAB Tab 19 | 0x28, // LF Enter 20 | 0x00, // VT 21 | 0x00, // FF 22 | 0x00, // CR 23 | 0x00, // SO 24 | 0x00, // SI 25 | 0x00, // DEL 26 | 0x00, // DC1 27 | 0x00, // DC2 28 | 0x00, // DC3 29 | 0x00, // DC4 30 | 0x00, // NAK 31 | 0x00, // SYN 32 | 0x00, // ETB 33 | 0x00, // CAN 34 | 0x00, // EM 35 | 0x00, // SUB 36 | 0x00, // ESC 37 | 0x00, // FS 38 | 0x00, // GS 39 | 0x00, // RS 40 | 0x00, // US 41 | 42 | 0x2c, // ' ' 43 | 0x1e|SHIFT, // ! 44 | 0x1f|SHIFT, // " 45 | 0x20|SHIFT, // # 46 | 0x21|SHIFT, // $ 47 | 0x22|SHIFT, // % 48 | 0x23|SHIFT, // & 49 | 0x2d, // ' 50 | 0x25|SHIFT, // ( 51 | 0x26|SHIFT, // ) 52 | 0x2f|SHIFT, // * 53 | 0x2f, // + 54 | 0x36, // , 55 | 0x38, // - 56 | 0x37, // . 57 | 0x24|SHIFT, // / 58 | 0x27, // 0 59 | 0x1e, // 1 60 | 0x1f, // 2 61 | 0x20, // 3 62 | 0x21, // 4 63 | 0x22, // 5 64 | 0x23, // 6 65 | 0x24, // 7 66 | 0x25, // 8 67 | 0x26, // 9 68 | 0x37|SHIFT, // : 69 | 0x36|SHIFT, // ; 70 | 0x32, // < 71 | 0x27|SHIFT, // = 72 | 0x32|SHIFT, // > 73 | 0x2d|SHIFT, // ? 74 | 0x1f|ALT_GR, // @ 75 | 0x04|SHIFT, // A 76 | 0x05|SHIFT, // B 77 | 0x06|SHIFT, // C 78 | 0x07|SHIFT, // D 79 | 0x08|SHIFT, // E 80 | 0x09|SHIFT, // F 81 | 0x0a|SHIFT, // G 82 | 0x0b|SHIFT, // H 83 | 0x0c|SHIFT, // I 84 | 0x0d|SHIFT, // J 85 | 0x0e|SHIFT, // K 86 | 0x0f|SHIFT, // L 87 | 0x10|SHIFT, // M 88 | 0x11|SHIFT, // N 89 | 0x12|SHIFT, // O 90 | 0x13|SHIFT, // P 91 | 0x14|SHIFT, // Q 92 | 0x15|SHIFT, // R 93 | 0x16|SHIFT, // S 94 | 0x17|SHIFT, // T 95 | 0x18|SHIFT, // U 96 | 0x19|SHIFT, // V 97 | 0x1a|SHIFT, // W 98 | 0x1b|SHIFT, // X 99 | 0x1c|SHIFT, // Y 100 | 0x1d|SHIFT, // Z 101 | 0x25|ALT_GR, // [ 102 | 0x35, // bslash 103 | 0x26|ALT_GR, // ] 104 | 0x00, // ^ not supported (requires dead key + space) 105 | 0x38|SHIFT, // _ 106 | 0x00, // ` not supported (requires dead key + space) 107 | 0x04, // a 108 | 0x05, // b 109 | 0x06, // c 110 | 0x07, // d 111 | 0x08, // e 112 | 0x09, // f 113 | 0x0a, // g 114 | 0x0b, // h 115 | 0x0c, // i 116 | 0x0d, // j 117 | 0x0e, // k 118 | 0x0f, // l 119 | 0x10, // m 120 | 0x11, // n 121 | 0x12, // o 122 | 0x13, // p 123 | 0x14, // q 124 | 0x15, // r 125 | 0x16, // s 126 | 0x17, // t 127 | 0x18, // u 128 | 0x19, // v 129 | 0x1a, // w 130 | 0x1b, // x 131 | 0x1c, // y 132 | 0x1d, // z 133 | 0x24|ALT_GR, // { 134 | 0x35|SHIFT, // | 135 | 0x27|ALT_GR, // } 136 | 0x00, // ~ not supported (requires dead key + space) 137 | 0x00 // DEL 138 | }; 139 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/KeyboardLayout_pt_PT-BR.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Portuguese keyboard layout. 3 | */ 4 | 5 | #include "KeyboardLayout.h" 6 | 7 | extern const uint8_t KeyboardLayout_pt_BR[128] PROGMEM = 8 | { 9 | 0x00, // NUL 10 | 0x00, // SOH 11 | 0x00, // STX 12 | 0x00, // ETX 13 | 0x00, // EOT 14 | 0x00, // ENQ 15 | 0x00, // ACK 16 | 0x00, // BEL 17 | 18 | 0x2a, // BS Backspace 19 | 0x2b, // TAB Tab 20 | 0x28, // LF Enter 21 | 0x00, // VT 22 | 0x00, // FF 23 | 0x00, // CR 24 | 0x00, // SO 25 | 0x00, // SI 26 | 0x00, // DEL 27 | 0x00, // DC1 28 | 0x00, // DC2 29 | 0x00, // DC3 30 | 0x00, // DC4 31 | 0x00, // NAK 32 | 0x00, // SYN 33 | 0x00, // ETB 34 | 0x00, // CAN 35 | 0x00, // EM 36 | 0x00, // SUB 37 | 0x29, // ESC 38 | 0x00, // FS 39 | 0x00, // GS 40 | 0x00, // RS 41 | 0x00, // US 42 | 43 | 0x2c, // ' ' 44 | 0x1e|SHIFT, // ! 45 | 0x35|SHIFT, // " 46 | 0x20|SHIFT, // # 47 | 0x21|SHIFT, // $ 48 | 0x22|SHIFT, // % 49 | 0x23|SHIFT, // & 50 | 0x35, // ' 51 | 0x26|SHIFT, // ( 52 | 0x27|SHIFT, // ) 53 | 0x25|SHIFT, // * 54 | 0x2E|SHIFT, // + 55 | 0x36, // , 56 | 0x2D, // - 57 | 0x37, // . 58 | 0x54, // / 59 | 60 | 0x27, // 0 61 | 0x1e, // 1 62 | 0x1f, // 2 63 | 0x20, // 3 64 | 0x21, // 4 65 | 0x22, // 5 66 | 0x23, // 6 67 | 0x24, // 7 68 | 0x25, // 8 69 | 0x26, // 9 70 | 0x38|SHIFT, // : 71 | 0x38, // ; 72 | 0x36|SHIFT, // < 73 | 0x2e, // = 74 | 0x37|SHIFT, // > 75 | 0x54|SHIFT, // ? ??? 76 | 0x1f|SHIFT, // @ 77 | 78 | 0x04|SHIFT, // A 79 | 0x05|SHIFT, // B 80 | 0x06|SHIFT, // C 81 | 0x07|SHIFT, // D 82 | 0x08|SHIFT, // E 83 | 0x09|SHIFT, // F 84 | 0x0a|SHIFT, // G 85 | 0x0b|SHIFT, // H 86 | 0x0c|SHIFT, // I 87 | 0x0d|SHIFT, // J 88 | 0x0e|SHIFT, // K 89 | 0x0f|SHIFT, // L 90 | 0x10|SHIFT, // M 91 | 0x11|SHIFT, // N 92 | 0x12|SHIFT, // O 93 | 0x13|SHIFT, // P 94 | 0x14|SHIFT, // Q 95 | 0x15|SHIFT, // R 96 | 0x16|SHIFT, // S 97 | 0x17|SHIFT, // T 98 | 0x18|SHIFT, // U 99 | 0x19|SHIFT, // V 100 | 0x1a|SHIFT, // W 101 | 0x1b|SHIFT, // X 102 | 0x1c|SHIFT, // Y 103 | 0x1d|SHIFT, // Z 104 | 105 | 0x30, // [ 106 | 0x64, // bslash 107 | 0x31, // ] 108 | 0x34|SHIFT, // ^ not supported (requires dead key + space) 109 | 0x2d|SHIFT, // _ 110 | 0x2f|SHIFT, // ` not supported (requires dead key + space) 111 | 112 | 0x04, // a 113 | 0x05, // b 114 | 0x06, // c 115 | 0x07, // d 116 | 0x08, // e 117 | 0x09, // f 118 | 0x0a, // g 119 | 0x0b, // h 120 | 0x0c, // i 121 | 0x0d, // j 122 | 0x0e, // k 123 | 0x0f, // l 124 | 0x10, // m 125 | 0x11, // n 126 | 0x12, // o 127 | 0x13, // p 128 | 0x14, // q 129 | 0x15, // r 130 | 0x16, // s 131 | 0x17, // t 132 | 0x18, // u 133 | 0x19, // v 134 | 0x1a, // w 135 | 0x1b, // x 136 | 0x1c, // y 137 | 0x1d, // z 138 | 139 | 0x30|SHIFT, // { 140 | 0x64|SHIFT, // | 141 | 0x31|SHIFT, // } 142 | 0x34, // ~ not supported (requires dead key + space) 143 | 0x00 // DEL 144 | }; 145 | -------------------------------------------------------------------------------- /src/Providers/DependencyProvider.h: -------------------------------------------------------------------------------- 1 | #ifndef DEPENDENCY_PROVIDER_H 2 | #define DEPENDENCY_PROVIDER_H 3 | 4 | #include "Views/IView.h" 5 | #include "Inputs/IInput.h" 6 | #include "Services/CryptoService.h" 7 | #include "Services/EntryService.h" 8 | #include "Services/CategoryService.h" 9 | #include "Services/SdService.h" 10 | #include "Services/NvsService.h" 11 | #include "Services/UsbService.h" 12 | #include "Services/LedService.h" 13 | #include "Transformers/JsonTransformer.h" 14 | #include "Transformers/ModelTransformer.h" 15 | #include "Transformers/TimeTransformer.h" 16 | #include "Selectors/VerticalSelector.h" 17 | #include "Selectors/HorizontalSelector.h" 18 | #include "Selectors/FieldEditorSelector.h" 19 | #include "Selectors/StringPromptSelector.h" 20 | #include "Selectors/ConfirmationSelector.h" 21 | #include "Selectors/FieldActionSelector.h" 22 | #include "Repositories/EntryRepository.h" 23 | #include "Repositories/CategoryRepository.h" 24 | #include "Controllers/VaultController.h" 25 | #include "Controllers/EntryController.h" 26 | #include "Controllers/UtilityController.h" 27 | #include "Managers/InactivityManager.h" 28 | 29 | class DependencyProvider { 30 | public: 31 | DependencyProvider(IView& view, IInput& input); 32 | void setup(); 33 | 34 | // Accessors for core components 35 | IView& getView(); 36 | IInput& getInput(); 37 | 38 | // Repositories 39 | EntryRepository& getEntryRepository(); 40 | CategoryRepository& getCategoryRepository(); 41 | 42 | // Services 43 | CryptoService& getCryptoService(); 44 | EntryService& getEntryService(); 45 | CategoryService& getCategoryService(); 46 | SdService& getSdService(); 47 | NvsService& getNvsService(); 48 | UsbService& getUsbService(); 49 | LedService& getLedService(); 50 | 51 | // Transformers 52 | JsonTransformer& getJsonTransformer(); 53 | ModelTransformer& getModelTransformer(); 54 | TimeTransformer& getTimeTransformer(); 55 | 56 | // Selectors 57 | VerticalSelector& getVerticalSelector(); 58 | HorizontalSelector& getHorizontalSelector(); 59 | FieldEditorSelector& getFieldEditorSelector(); 60 | FieldActionSelector& getFieldActionSelector(); 61 | StringPromptSelector& getStringPromptSelector(); 62 | ConfirmationSelector& getConfirmationSelector(); 63 | 64 | // Controllers 65 | VaultController& getVaultController(); 66 | EntryController& getEntryController(); 67 | UtilityController& getUtilityController(); 68 | 69 | // Managers 70 | InactivityManager& getInactivityManager(); 71 | 72 | private: 73 | IView& view; 74 | IInput& input; 75 | 76 | // Repositories 77 | EntryRepository entryRepository; 78 | CategoryRepository categoryRepository; 79 | 80 | // Services 81 | CryptoService cryptoService; 82 | EntryService entryService; 83 | CategoryService categoryService; 84 | SdService sdService; 85 | NvsService nvsService; 86 | UsbService usbService; 87 | LedService ledService; 88 | 89 | // Transformers 90 | JsonTransformer jsonTransformer; 91 | ModelTransformer modelTransformer; 92 | TimeTransformer timeTransformer; 93 | 94 | // Selectors 95 | VerticalSelector verticalSelector; 96 | HorizontalSelector horizontalSelector; 97 | FieldEditorSelector fieldEditorSelector; 98 | FieldActionSelector fieldActionSelector; 99 | StringPromptSelector stringPromptSelector; 100 | ConfirmationSelector confirmationSelector; 101 | 102 | // Controllers 103 | VaultController vaultController; 104 | EntryController entryController; 105 | UtilityController utilityController; 106 | 107 | // Managers 108 | InactivityManager inactivityManager; 109 | 110 | }; 111 | 112 | #endif // DEPENDENCY_PROVIDER_H 113 | -------------------------------------------------------------------------------- /test/Services/TestEntryService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ENTRY_SERVICE 2 | #define TEST_ENTRY_SERVICE 3 | 4 | #include 5 | #include "../src/Services/EntryService.h" 6 | #include "../src/Repositories/EntryRepository.h" 7 | 8 | void test_isEntryExpired() { 9 | EntryRepository repository; 10 | EntryService service(repository); 11 | 12 | Entry expiredEntry("1", "Service1", "User1", "Pass1", 0); 13 | expiredEntry.setExpiresAt(std::time(nullptr) - 10); // Expried 14 | 15 | Entry validEntry("2", "Service2", "User2", "Pass2", 0); 16 | validEntry.setExpiresAt(std::time(nullptr) + 10); // Not expired 17 | 18 | TEST_ASSERT_TRUE(service.isEntryExpired(expiredEntry)); 19 | TEST_ASSERT_FALSE(service.isEntryExpired(validEntry)); 20 | } 21 | 22 | void test_add_and_find_entry() { 23 | EntryRepository repository; 24 | EntryService service(repository); 25 | 26 | Entry entry("1", "Service1", "User1", "Pass1", 0); 27 | service.addEntry(entry); 28 | 29 | Entry foundEntry = service.findEntryById("1"); 30 | 31 | TEST_ASSERT_EQUAL_STRING("Service1", foundEntry.getServiceName().c_str()); 32 | TEST_ASSERT_EQUAL_STRING("User1", foundEntry.getUsername().c_str()); 33 | } 34 | 35 | void test_update_entry() { 36 | EntryRepository repository; 37 | EntryService service(repository); 38 | 39 | Entry entry("1", "Service1", "User1", "Pass1", 0); 40 | service.addEntry(entry); 41 | 42 | Entry updatedEntry("1", "UpdatedService", "UpdatedUser", "UpdatedPass", 1); 43 | bool result = service.updateEntry(entry, updatedEntry); 44 | 45 | TEST_ASSERT_TRUE(result); 46 | 47 | Entry foundEntry = service.findEntryById("1"); 48 | TEST_ASSERT_EQUAL_STRING("UpdatedService", foundEntry.getServiceName().c_str()); 49 | TEST_ASSERT_EQUAL_STRING("UpdatedUser", foundEntry.getUsername().c_str()); 50 | } 51 | 52 | void test_get_all_entries() { 53 | EntryRepository repository; 54 | EntryService service(repository); 55 | 56 | service.addEntry(Entry("1", "Service1", "User1", "Pass1", 0)); 57 | service.addEntry(Entry("2", "Service2", "User2", "Pass2", 0)); 58 | 59 | std::vector entries = service.getAllEntries(); 60 | 61 | TEST_ASSERT_EQUAL(2, entries.size()); 62 | TEST_ASSERT_EQUAL_STRING("Service1", entries[0].getServiceName().c_str()); 63 | TEST_ASSERT_EQUAL_STRING("Service2", entries[1].getServiceName().c_str()); 64 | } 65 | 66 | void test_updateField() { 67 | EntryRepository repository; 68 | EntryService service(repository); 69 | 70 | // Add entry 71 | Entry entry("1", "Service1", "User1", "Pass1", 0); 72 | service.addEntry(entry); 73 | 74 | // Update user 75 | Field usernameField("User", "UpdatedUser"); 76 | bool usernameResult = service.updateField(entry, usernameField); 77 | 78 | TEST_ASSERT_TRUE(usernameResult); 79 | Entry updatedEntry = service.findEntryById("1"); 80 | TEST_ASSERT_EQUAL_STRING("UpdatedUser", updatedEntry.getUsername().c_str()); 81 | 82 | // Update password 83 | Field passwordField("Pass", "UpdatedPass"); 84 | bool passwordResult = service.updateField(entry, passwordField); 85 | 86 | TEST_ASSERT_TRUE(passwordResult); 87 | updatedEntry = service.findEntryById("1"); 88 | TEST_ASSERT_EQUAL_STRING("UpdatedPass", updatedEntry.getPassword().c_str()); 89 | 90 | // Update notes 91 | Field notesField("Note", "UpdatedNote"); 92 | bool notesResult = service.updateField(entry, notesField); 93 | 94 | TEST_ASSERT_TRUE(notesResult); 95 | updatedEntry = service.findEntryById("1"); 96 | TEST_ASSERT_EQUAL_STRING("UpdatedNote", updatedEntry.getNotes().c_str()); 97 | 98 | // Invalid field 99 | Field invalidField("invalidField", "SomeValue"); 100 | bool invalidResult = service.updateField(entry, invalidField); 101 | 102 | TEST_ASSERT_FALSE(invalidResult); 103 | } 104 | 105 | 106 | #endif // TEST_ENTRY_SERVICE 107 | -------------------------------------------------------------------------------- /test/Services/TestCryptoService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_CRYPTO_SERVICE 2 | #define TEST_CRYPTO_SERVICE 3 | 4 | #include 5 | #include "../src/Services/CryptoService.h" 6 | 7 | void test_generateHardwareRandom() { 8 | CryptoService service; 9 | size_t size = 16; 10 | 11 | auto randomData = service.generateHardwareRandom(size); 12 | 13 | TEST_ASSERT_EQUAL(size, randomData.size()); 14 | 15 | // Verify randomness 16 | bool hasVariety = false; 17 | for (size_t i = 1; i < randomData.size(); ++i) { 18 | if (randomData[i] != randomData[0]) { 19 | hasVariety = true; 20 | break; 21 | } 22 | } 23 | 24 | TEST_ASSERT_TRUE_MESSAGE(hasVariety, "Hardware random data lacks variety."); 25 | } 26 | 27 | void test_generateRandomString() { 28 | CryptoService service; 29 | size_t length = 18; 30 | const std::string PRINTABLE_CHARACTERS = 31 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 32 | "abcdefghijklmnopqrstuvwxyz" 33 | "0123456789" 34 | "!@#$&*-_=+"; 35 | 36 | auto randomString = service.generateRandomString(length); 37 | 38 | TEST_ASSERT_EQUAL(length, randomString.size()); 39 | 40 | // Verify each chars members of PRINTABLE_CHARACTERS 41 | for (char c : randomString) { 42 | TEST_ASSERT_NOT_EQUAL(std::string::npos, PRINTABLE_CHARACTERS.find(c)); 43 | } 44 | } 45 | 46 | void test_deriveKeyFromPassphrase() { 47 | CryptoService service; 48 | std::string passphrase = "strongpassword"; 49 | std::string salt = "randomsalt"; 50 | size_t keySize = 16; 51 | 52 | auto key = service.deriveKeyFromPassphrase(passphrase, salt, keySize); 53 | 54 | TEST_ASSERT_EQUAL(keySize, key.size()); 55 | } 56 | 57 | void test_encrypt_decrypt_AES() { 58 | CryptoService service; 59 | std::vector key(16, 0x01); // Key with 16 bytes of 0x01 60 | std::vector data = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 61 | 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 62 | 63 | auto encrypted = service.encryptAES(data, key); 64 | auto decrypted = service.decryptAES(encrypted, key); 65 | 66 | TEST_ASSERT_EQUAL_MEMORY(data.data(), decrypted.data(), data.size()); 67 | } 68 | 69 | void test_generateSalt() { 70 | CryptoService service; 71 | size_t saltSize = 16; 72 | 73 | auto salt = service.generateSalt(saltSize); 74 | 75 | TEST_ASSERT_EQUAL(saltSize, salt.size()); 76 | 77 | // Vérifie que tous les octets ne sont pas identiques (ex: 0x00 ou 0xFF partout) 78 | bool hasVariety = false; 79 | for (size_t i = 1; i < salt.size(); ++i) { 80 | if (salt[i] != salt[0]) { 81 | hasVariety = true; 82 | break; 83 | } 84 | } 85 | 86 | TEST_ASSERT_TRUE_MESSAGE(hasVariety, "Salt does not contain a variety of values."); 87 | } 88 | 89 | void test_generateChecksum() { 90 | CryptoService service; 91 | std::string data = "RandomData"; 92 | size_t checksumSize = 16; 93 | 94 | auto checksum = service.generateChecksum(data, checksumSize); 95 | 96 | TEST_ASSERT_EQUAL(checksumSize, checksum.size()); 97 | TEST_ASSERT_NOT_EQUAL(0, checksum[0]); // Vérifie que le checksum n'est pas vide 98 | } 99 | 100 | void test_encrypt_decrypt_with_passphrase() { 101 | CryptoService service; 102 | std::string passphrase = "strongpassword"; 103 | std::string data = "random"; 104 | const std::vector salt = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 105 | 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; 106 | 107 | auto encrypted = service.encryptWithPassphrase(data, passphrase, salt); 108 | auto decrypted = service.decryptWithPassphrase(encrypted, passphrase, salt); 109 | 110 | TEST_ASSERT_EQUAL_MEMORY(data.data(), decrypted.data(), data.size()); 111 | } 112 | 113 | #endif // TEST_CRYPTO_SERVICE 114 | -------------------------------------------------------------------------------- /src/Views/CardputerView.h: -------------------------------------------------------------------------------- 1 | #ifndef CARDPUTER_VIEW_H 2 | #define CARDPUTER_VIEW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "IView.h" 9 | 10 | // SIZING 11 | #define DEFAULT_MARGIN 5 12 | #define DEFAULT_ROUND_RECT 5 13 | #define TOP_BAR_HEIGHT 30 14 | 15 | // PALETTE 16 | #define BACKGROUND_COLOR TFT_BLACK 17 | #define PRIMARY_COLOR 0xfc20 18 | #define RECT_COLOR_DARK 0x0841 19 | #define RECT_COLOR_LIGHT 0xd69a 20 | #define TEXT_COLOR 0xef7d 21 | 22 | // TEXT SIZE 23 | #define TEXT_BIG 2 24 | #define TEXT_LARGE 1.9 25 | #define TEXT_WIDE 1.4 26 | #define TEXT_MEDIUM_LARGE 1.2 27 | #define TEXT_MEDIUM 1.1 28 | #define TEXT_SMALL 1.0 29 | #define TEXT_TINY 0.9 30 | 31 | namespace views { 32 | 33 | class CardputerView : public IView { 34 | public: 35 | void initialize() override; 36 | void setBrightness(uint16_t brightness) override; 37 | uint8_t getBrightness() override; 38 | void welcome(uint8_t defaultBrightness=140); 39 | void topBar(const std::string& title, bool submenu, bool searchBar) override; 40 | void horizontalSelection(const std::vector& options, uint16_t selectedIndex, const std::string& description1="", const std::string& description2="", const std::vector& icons={}); 41 | void verticalSelection( 42 | const std::vector& options, 43 | uint16_t selectedIndex, 44 | size_t visibleRows = 4, 45 | const std::vector& optionLabels = {}, 46 | const std::vector& shortcuts = {}, 47 | bool visibleMention=false 48 | ); 49 | void value(std::string label, std::string val); 50 | void subMessage(std::string message, int delayMs); 51 | void stringPrompt(std::string label, std::string value, bool backButton, size_t minLength); 52 | void confirmationPrompt(std::string label); 53 | void debug(const std::string& message) override; 54 | void drawVaultIcon(int x = 86, int y = 10, uint16_t color = PRIMARY_COLOR, size_t w=70, size_t h=50); 55 | void drawFileIcon(int x = 92, int y = 10); 56 | void drawSettingsIcon(int x = 80, int y = 5); 57 | void drawSdCardIcon(int x=90, int y=10); 58 | void drawPlusIcon(int x=120, int y=47, uint16_t color = PRIMARY_COLOR); 59 | void drawMinusIcon(int x=120, int y=47, uint16_t color = PRIMARY_COLOR); 60 | void drawLockIcon(int x=120, int y=78, uint16_t color = PRIMARY_COLOR, size_t w=60, size_t h=45); 61 | private: 62 | static M5GFX* Display; // Variable statique pour l'affichage 63 | void drawRect(bool selected, uint8_t margin, uint16_t startY, uint16_t sizeX, uint16_t sizeY, uint16_t stepY); 64 | void drawSubMenuReturn(uint8_t x, uint8_t y); 65 | void drawSearchIcon(int x, int y, int size, uint16_t color); 66 | void clearMainView(uint8_t offsetY = 0); 67 | void clearTopBar(); 68 | int getCenterOffset(const std::string& text, int screenWidth=240); 69 | std::string truncateString(const std::string& input, size_t maxLength); 70 | void adjustTextSizeToFit(const std::string& text, uint16_t maxWidth, float textSize); 71 | void horizontalSelectionWithIcons( 72 | const std::vector& options, 73 | uint16_t selectedIndex, 74 | const std::vector& icons); 75 | void horizontalSelectionWithoutIcons( 76 | const std::vector& options, 77 | uint16_t selectedIndex, 78 | const std::string& description1, 79 | const std::string& description2); 80 | void verticalSelectionSimple( 81 | const std::vector& options, 82 | uint16_t selectedIndex, 83 | size_t visibleRows = 4 84 | ); 85 | void verticalSelectionWithLabelsAndShortcuts( 86 | const std::vector& options, 87 | uint16_t selectedIndex, 88 | size_t visibleRows = 4, 89 | const std::vector& optionLabels = {}, 90 | const std::vector& shortcuts = {}, 91 | bool visibleMention=false 92 | ); 93 | }; 94 | 95 | } 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/Models/Entry.h: -------------------------------------------------------------------------------- 1 | #ifndef ENTRY_H 2 | #define ENTRY_H 3 | 4 | #include 5 | #include 6 | 7 | class Entry { 8 | private: 9 | std::string id; 10 | std::string serviceName; 11 | std::string username; 12 | std::string password; 13 | size_t categoryIndex; 14 | std::string notes; 15 | std::string notes2; 16 | std::string notes3; 17 | std::string link; 18 | time_t createdAt; 19 | time_t updatedAt; 20 | time_t expiresAt; 21 | 22 | public: 23 | // Constructeurs 24 | Entry() 25 | : id(""), serviceName(""), username(""), password(""), 26 | categoryIndex(0), notes(""), notes2(""), notes3(""), link(""), 27 | createdAt(0), updatedAt(0), expiresAt(0) {} 28 | 29 | Entry(const std::string& serviceName, const std::string& username, const std::string& password, const std::string& notes) 30 | : id(""), serviceName(serviceName), username(username), password(password), 31 | categoryIndex(0), notes(notes), notes2(""), notes3(""), link(""), 32 | createdAt(0), updatedAt(0), expiresAt(0) {} 33 | 34 | Entry(const std::string& id, const std::string& serviceName, const std::string& username, 35 | const std::string& password, size_t categoryIndex) 36 | : id(id), serviceName(serviceName), username(username), password(password), 37 | categoryIndex(categoryIndex), notes(""), notes2(""), notes3(""), link(""), 38 | createdAt(0), updatedAt(0), expiresAt(0) {} 39 | 40 | Entry(const std::string& id, const std::string& serviceName, const std::string& username, 41 | const std::string& password, size_t categoryIndex, const std::string& link) 42 | : id(id), serviceName(serviceName), username(username), password(password), 43 | categoryIndex(categoryIndex), notes(""), notes2(""), notes3(""), link(link), 44 | createdAt(0), updatedAt(0), expiresAt(0) {} 45 | 46 | // Accesseurs 47 | const std::string& getId() const { return id; } 48 | const std::string& getServiceName() const { return serviceName; } 49 | const std::string& getUsername() const { return username; } 50 | const std::string& getPassword() const { return password; } 51 | size_t getCategoryIndex() const { return categoryIndex; } 52 | const std::string& getNotes() const { return notes; } 53 | const std::string& getNotes2() const { return notes2; } 54 | const std::string& getNotes3() const { return notes3; } 55 | const std::string& getLink() const { return link; } 56 | time_t getCreatedAt() const { return createdAt; } 57 | time_t getUpdatedAt() const { return updatedAt; } 58 | time_t getExpiresAt() const { return expiresAt; } 59 | 60 | // Mutateurs 61 | void setId(const std::string& newId) { id = newId; updatedAt = time(nullptr); } 62 | void setServiceName(const std::string& name) { serviceName = name; updatedAt = time(nullptr); } 63 | void setUsername(const std::string& user) { username = user; updatedAt = time(nullptr); } 64 | void setPassword(const std::string& newPassword) { password = newPassword; updatedAt = time(nullptr); } 65 | void setCategoryIndex(size_t index) { categoryIndex = index; updatedAt = time(nullptr); } 66 | void setNotes(const std::string& newNotes) { notes = newNotes; updatedAt = time(nullptr); } 67 | void setNotes2(const std::string& newNotes2) { notes2 = newNotes2; updatedAt = time(nullptr); } 68 | void setNotes3(const std::string& newNotes3) { notes3 = newNotes3; updatedAt = time(nullptr); } 69 | void setLink(const std::string& newLink) { link = newLink; updatedAt = time(nullptr); } 70 | void setExpiresAt(time_t expiry) { expiresAt = expiry; updatedAt = time(nullptr); } 71 | void setCreatedAt(time_t created) { createdAt = created; } 72 | void setUpdatedAt(time_t updated) { updatedAt = updated; } 73 | 74 | // Methodes utils 75 | bool empty() const { 76 | return serviceName.empty() && username.empty() && password.empty() && 77 | notes.empty() && notes2.empty() && notes3.empty() && link.empty(); 78 | } 79 | }; 80 | 81 | #endif // ENTRY_H 82 | -------------------------------------------------------------------------------- /src/Providers/DependencyProvider.cpp: -------------------------------------------------------------------------------- 1 | #include "DependencyProvider.h" 2 | 3 | DependencyProvider::DependencyProvider(IView& view, IInput& input) 4 | : view(view), 5 | input(input), 6 | entryService(entryRepository), 7 | categoryService(categoryRepository), 8 | cryptoService(), 9 | sdService(), 10 | nvsService(), 11 | usbService(), 12 | ledService(), 13 | inactivityManager(view), 14 | verticalSelector(view, input, inactivityManager), 15 | horizontalSelector(view, input, inactivityManager), 16 | fieldEditorSelector(view, input), 17 | fieldActionSelector(view, input, inactivityManager), 18 | stringPromptSelector(view, input), 19 | confirmationSelector(view, input), 20 | jsonTransformer(), 21 | modelTransformer(), 22 | timeTransformer(), 23 | vaultController(view, input, horizontalSelector, verticalSelector, 24 | confirmationSelector, stringPromptSelector, sdService, 25 | nvsService, categoryService, entryService, cryptoService, 26 | jsonTransformer, modelTransformer), 27 | entryController(view, input, horizontalSelector, verticalSelector, fieldActionSelector, 28 | confirmationSelector, stringPromptSelector, entryService, cryptoService, 29 | usbService, ledService, nvsService, modelTransformer), 30 | utilityController(view, input, horizontalSelector, verticalSelector, fieldEditorSelector, 31 | stringPromptSelector, confirmationSelector, usbService, ledService, nvsService, 32 | sdService, timeTransformer) 33 | {} 34 | 35 | void DependencyProvider::setup() { 36 | view.initialize(); 37 | } 38 | 39 | // Accessors for core components 40 | IView& DependencyProvider::getView() { return view; } 41 | IInput& DependencyProvider::getInput() { return input; } 42 | 43 | // Accessors for repositories 44 | EntryRepository& DependencyProvider::getEntryRepository() { return entryRepository; } 45 | CategoryRepository& DependencyProvider::getCategoryRepository() { return categoryRepository; } 46 | 47 | // Accessors for services 48 | CryptoService& DependencyProvider::getCryptoService() { return cryptoService; } 49 | EntryService& DependencyProvider::getEntryService() { return entryService; } 50 | CategoryService& DependencyProvider::getCategoryService() { return categoryService; } 51 | SdService& DependencyProvider::getSdService() { return sdService; } 52 | NvsService& DependencyProvider::getNvsService() { return nvsService; } 53 | UsbService& DependencyProvider::getUsbService() { return usbService; } 54 | LedService& DependencyProvider::getLedService() { return ledService; } 55 | 56 | // Accessors for transformers 57 | JsonTransformer& DependencyProvider::getJsonTransformer() { return jsonTransformer; } 58 | ModelTransformer& DependencyProvider::getModelTransformer() { return modelTransformer; } 59 | TimeTransformer& DependencyProvider::getTimeTransformer() { return timeTransformer; } 60 | 61 | 62 | // Accessors for selectors 63 | VerticalSelector& DependencyProvider::getVerticalSelector() { return verticalSelector; } 64 | HorizontalSelector& DependencyProvider::getHorizontalSelector() { return horizontalSelector; } 65 | FieldEditorSelector& DependencyProvider::getFieldEditorSelector() { return fieldEditorSelector; } 66 | StringPromptSelector& DependencyProvider::getStringPromptSelector() { return stringPromptSelector; } 67 | ConfirmationSelector& DependencyProvider::getConfirmationSelector() { return confirmationSelector; } 68 | FieldActionSelector& DependencyProvider::getFieldActionSelector() { return fieldActionSelector; } 69 | 70 | // Accessors for controllers 71 | VaultController& DependencyProvider::getVaultController() { return vaultController; } 72 | EntryController& DependencyProvider::getEntryController() { return entryController; } 73 | UtilityController& DependencyProvider::getUtilityController() { return utilityController; } 74 | 75 | // Accessors for managers 76 | InactivityManager& DependencyProvider::getInactivityManager() { return inactivityManager; }; -------------------------------------------------------------------------------- /src/Dispatchers/ActionDispatcher.cpp: -------------------------------------------------------------------------------- 1 | #include "ActionDispatcher.h" 2 | 3 | ActionDispatcher::ActionDispatcher(DependencyProvider& provider) 4 | : provider(provider), 5 | context(ContextEnum::NoVault), 6 | selectedEntry(), 7 | selectedField() {} 8 | 9 | void ActionDispatcher::setup() { 10 | provider.getUtilityController().handleLoadNvs(); 11 | provider.getUtilityController().handleWelcome(); 12 | } 13 | 14 | void ActionDispatcher::run() { 15 | while (true) { 16 | auto action = determineActionByContext(); 17 | executeAction(action); 18 | } 19 | } 20 | 21 | ActionEnum ActionDispatcher::determineActionByContext() { 22 | auto action = ActionEnum::None; 23 | 24 | // Vault lock state check 25 | if(globalState.getVaultIsLocked()) { 26 | context = ContextEnum::NoVault; 27 | provider.getUtilityController().handleInactivity(); 28 | } 29 | 30 | switch (context) { 31 | case ContextEnum::NoVault: 32 | action = provider.getVaultController().actionNoVault(); 33 | break; 34 | 35 | case ContextEnum::VaultSelected: 36 | action = provider.getVaultController().actionVaultSelected(); 37 | if (action == ActionEnum::None) { context = ContextEnum::NoVault;} 38 | break; 39 | 40 | case ContextEnum::VaultLoaded: 41 | action = ActionEnum::SelectEntry; 42 | break; 43 | 44 | case ContextEnum::EntrySelected: 45 | action = ActionEnum::SelectField; 46 | break; 47 | 48 | case ContextEnum::FieldSelected: 49 | action = provider.getEntryController().actionFieldSelected(selectedField); 50 | if (action == ActionEnum::None) {context = ContextEnum::EntrySelected;} 51 | break; 52 | } 53 | 54 | return action; 55 | } 56 | 57 | void ActionDispatcher::executeAction(ActionEnum action) { 58 | bool confirmation; 59 | switch (action) { 60 | case ActionEnum::CreateVault: 61 | confirmation = provider.getVaultController().handleVaultCreation(); 62 | if (confirmation) { 63 | context = ContextEnum::VaultSelected; 64 | } 65 | break; 66 | 67 | case ActionEnum::OpenVault: 68 | confirmation = provider.getVaultController().handleVaultLoading(); 69 | if (confirmation) { 70 | context = ContextEnum::VaultSelected; 71 | } 72 | break; 73 | 74 | case ActionEnum::SelectEntry: 75 | selectedEntry = provider.getEntryController().handleEntrySelection(); 76 | 77 | if (selectedEntry.empty()) { 78 | context = ContextEnum::VaultSelected; 79 | } else { 80 | context = ContextEnum::EntrySelected; 81 | } 82 | break; 83 | 84 | case ActionEnum::CreateEntry: 85 | confirmation = provider.getEntryController().handleEntryCreation(); 86 | if (confirmation) { 87 | provider.getVaultController().handleVaultSave(); 88 | } 89 | break; 90 | 91 | case ActionEnum::DeleteEntry: 92 | confirmation = provider.getEntryController().handleEntryDeletion(); 93 | if (confirmation) { 94 | provider.getVaultController().handleVaultSave(); 95 | } 96 | break; 97 | 98 | case ActionEnum::SelectField: 99 | provider.getUtilityController().handleKeyboardInitialization(); 100 | selectedField = provider.getEntryController().handleFieldSelection(selectedEntry); 101 | 102 | if (selectedField.empty()) { 103 | context = ContextEnum::VaultLoaded; 104 | } else { 105 | context = ContextEnum::FieldSelected; 106 | } 107 | break; 108 | 109 | case ActionEnum::UpdateField: 110 | confirmation = provider.getEntryController().handleEntryUpdate(selectedEntry, selectedField); 111 | if (confirmation) { 112 | provider.getVaultController().handleVaultSave(); 113 | } 114 | break; 115 | 116 | case ActionEnum::SendToUsb: 117 | provider.getUtilityController().handleUsbTyping(selectedField.getValue()); 118 | break; 119 | 120 | case ActionEnum::UpdateSettings: 121 | provider.getUtilityController().handleGeneralSettings(); 122 | break; 123 | } 124 | } -------------------------------------------------------------------------------- /src/Selectors/VerticalSelector.cpp: -------------------------------------------------------------------------------- 1 | #include "VerticalSelector.h" 2 | #include 3 | #include 4 | 5 | VerticalSelector::VerticalSelector(IView& display, IInput& input, InactivityManager& inactivityManager) 6 | : display(display), input(input), inactivityManager(inactivityManager) {} 7 | 8 | 9 | int VerticalSelector::select( 10 | const std::string& title, 11 | const std::vector& options, 12 | bool subMenu, 13 | bool searchBar, 14 | const std::vector& options2, 15 | const std::vector& shortcuts, 16 | bool visibleMention, 17 | bool handleInactivity) 18 | { 19 | int currentIndex = 0; 20 | int lastIndex = -1; 21 | int lastQuerySize = 0; 22 | char key = KEY_NONE; 23 | std::string searchQuery; 24 | std::vector filteredOptions = options; 25 | inactivityManager.reset(); 26 | 27 | while (true) { 28 | // Inactivity 29 | if (handleInactivity) { 30 | inactivityManager.update(); 31 | if (inactivityManager.getVaultIsLocked()) {return -1;} 32 | } 33 | 34 | // Display the current options and selection 35 | if (lastIndex != currentIndex || lastQuerySize != searchQuery.size()) { 36 | display.topBar(searchQuery.empty() ? title : searchQuery, subMenu, searchBar); 37 | display.verticalSelection(filteredOptions, currentIndex, 4, options2, shortcuts, visibleMention); 38 | lastIndex = currentIndex; 39 | lastQuerySize = searchQuery.size(); 40 | } 41 | 42 | // Capture user input 43 | key = input.handler(); 44 | 45 | if (handleInactivity && key != KEY_NONE) { 46 | inactivityManager.reset(); 47 | } 48 | 49 | // Verify shortcuts 50 | if (!shortcuts.empty()) { 51 | int shortcutIndex = checkShortcut(shortcuts, key); 52 | if (shortcutIndex != -1) { 53 | return shortcutIndex; 54 | } 55 | } 56 | 57 | switch (key) { 58 | case KEY_ARROW_UP: 59 | currentIndex = (currentIndex > 0) ? currentIndex - 1 : filteredOptions.size() - 1; 60 | break; 61 | case KEY_ARROW_DOWN: 62 | currentIndex = (currentIndex < filteredOptions.size() - 1) ? currentIndex + 1 : 0; 63 | break; 64 | case KEY_OK: 65 | for (size_t i = 0; i < options.size(); ++i) { 66 | if (options[i] == filteredOptions[currentIndex]) { 67 | return i; 68 | } 69 | } 70 | break; 71 | case KEY_ESC_CUSTOM: 72 | case KEY_ARROW_LEFT: // Back 73 | return -1; 74 | case KEY_DEL: // Backspace for text search 75 | if (searchBar && !searchQuery.empty()) { 76 | searchQuery.pop_back(); 77 | filteredOptions = filterOptions(options, searchQuery); 78 | currentIndex = 0; 79 | } else { 80 | filteredOptions = options; 81 | } 82 | break; 83 | default: 84 | if (searchBar && std::isalnum(key)) { 85 | searchQuery += key; 86 | filteredOptions = filterOptions(options, searchQuery); 87 | currentIndex = 0; 88 | } 89 | 90 | break; 91 | } 92 | } 93 | } 94 | 95 | std::string VerticalSelector::toLowerCase(const std::string& input) { 96 | std::string result = input; 97 | std::transform(result.begin(), result.end(), result.begin(), ::tolower); 98 | return result; 99 | } 100 | 101 | std::vector VerticalSelector::filterOptions(const std::vector& options, const std::string& query) { 102 | std::vector filtered; 103 | std::string lowerQuery = toLowerCase(query); 104 | for (const auto& option : options) { 105 | if (toLowerCase(option).find(lowerQuery) != std::string::npos) { 106 | filtered.push_back(option); 107 | } 108 | } 109 | return filtered; 110 | } 111 | 112 | int VerticalSelector::checkShortcut(const std::vector& shortcuts, char key) { 113 | for (size_t i = 0; i < shortcuts.size(); ++i) { 114 | if (!shortcuts[i].empty() && std::tolower(key) == std::tolower(shortcuts[i][0])) { 115 | return i; // Retourne l'index du raccourci correspondant 116 | } 117 | } 118 | return -1; // Aucun raccourci correspondant trouvé 119 | } 120 | 121 | -------------------------------------------------------------------------------- /test/Services/TestSdService.cpp: -------------------------------------------------------------------------------- 1 | #ifndef TEST_SD_SERVICE 2 | #define TEST_SD_SERVICE 3 | 4 | #include 5 | #include "../src/Services/SdService.h" 6 | 7 | void test_sd_begin() { 8 | SdService sdService; 9 | TEST_ASSERT_FALSE(sdService.getSdState()); 10 | bool result = sdService.begin(); 11 | TEST_ASSERT_EQUAL(result, sdService.getSdState()); 12 | } 13 | 14 | void test_sd_close() { 15 | SdService sdService; 16 | sdService.close(); 17 | TEST_ASSERT_FALSE(sdService.getSdState()); 18 | } 19 | 20 | void test_isFile() { 21 | SdService sdService; 22 | sdService.begin(); 23 | TEST_ASSERT_FALSE(sdService.isFile("/non_existent.txt")); 24 | sdService.writeFile("/unitTestFile.txt", "Hello"); 25 | TEST_ASSERT_TRUE(sdService.isFile("/unitTestFile.txt")); 26 | sdService.deleteFile("/unitTestFile.txt"); 27 | sdService.close(); 28 | } 29 | 30 | void test_isDirectory() { 31 | SdService sdService; 32 | sdService.begin(); 33 | TEST_ASSERT_FALSE(sdService.isDirectory("/non_existent_dir")); 34 | sdService.ensureDirectory("/unitTestDir"); 35 | TEST_ASSERT_TRUE(sdService.isDirectory("/unitTestDir")); 36 | sdService.deleteFile("/unitTestDir"); 37 | sdService.close(); 38 | } 39 | 40 | void test_read_write_file() { 41 | SdService sdService; 42 | sdService.begin(); 43 | std::string content = "Test content"; 44 | TEST_ASSERT_TRUE(sdService.writeFile("/unitTest.txt", content)); 45 | std::string readContent = sdService.readFile("/unitTest.txt"); 46 | TEST_ASSERT_EQUAL_STRING(content.c_str(), readContent.c_str()); 47 | sdService.deleteFile("/unitTest.txt"); 48 | sdService.close(); 49 | } 50 | 51 | void test_append_to_file() { 52 | SdService sdService; 53 | sdService.begin(); 54 | sdService.writeFile("/unitTestAppend.txt", "Hello"); 55 | sdService.appendToFile("/unitTestAppend.txt", " World"); 56 | std::string content = sdService.readFile("/unitTestAppend.txt"); 57 | TEST_ASSERT_EQUAL_STRING("Hello World", content.c_str()); 58 | sdService.deleteFile("/unitTestAppend.txt"); 59 | sdService.close(); 60 | } 61 | 62 | void test_list_elements() { 63 | SdService sdService; 64 | sdService.begin(); 65 | sdService.ensureDirectory("/unitTestDir"); 66 | sdService.writeFile("/unitTestDir/file1.txt", "content1"); 67 | sdService.writeFile("/unitTestDir/file2.txt", "content2"); 68 | std::vector elements = sdService.listElements("/unitTestDir"); 69 | TEST_ASSERT_EQUAL(2, elements.size()); 70 | sdService.deleteFile("/unitTestDir/file1.txt"); 71 | sdService.deleteFile("/unitTestDir/file2.txt"); 72 | sdService.deleteFile("/unitTestDir"); 73 | sdService.close(); 74 | } 75 | 76 | void test_getFileName() { 77 | SdService service; 78 | 79 | std::string path1 = "/folder/subfolder/file.txt"; 80 | std::string path2 = "/folder/file"; 81 | std::string path3 = "file"; 82 | 83 | TEST_ASSERT_EQUAL_STRING("file", service.getFileName(path1).c_str()); 84 | TEST_ASSERT_EQUAL_STRING("file", service.getFileName(path2).c_str()); 85 | TEST_ASSERT_EQUAL_STRING("file", service.getFileName(path3).c_str()); 86 | } 87 | 88 | void test_getFileExt() { 89 | SdService service; 90 | 91 | std::string path1 = "/folder/subfolder/file.txt"; 92 | std::string path2 = "/folder/file.tar.gz"; 93 | std::string path3 = "/folder/file"; 94 | 95 | TEST_ASSERT_EQUAL_STRING("txt", service.getFileExt(path1).c_str()); 96 | TEST_ASSERT_EQUAL_STRING("gz", service.getFileExt(path2).c_str()); 97 | TEST_ASSERT_EQUAL_STRING("", service.getFileExt(path3).c_str()); 98 | } 99 | 100 | void test_getParentDirectory() { 101 | SdService service; 102 | 103 | std::string path1 = "/folder/subfolder/file.txt"; 104 | std::string path2 = "/folder/file"; 105 | std::string path3 = "file"; 106 | std::string path4 = "/"; 107 | 108 | TEST_ASSERT_EQUAL_STRING("/folder/subfolder", service.getParentDirectory(path1).c_str()); 109 | TEST_ASSERT_EQUAL_STRING("/folder", service.getParentDirectory(path2).c_str()); 110 | TEST_ASSERT_EQUAL_STRING("/", service.getParentDirectory(path3).c_str()); 111 | TEST_ASSERT_EQUAL_STRING("/", service.getParentDirectory(path4).c_str()); 112 | } 113 | 114 | void test_validateVaultFile() { 115 | SdService service; 116 | 117 | std::string validVaultPath = "/vaults/myVault.vault"; 118 | std::string invalidVaultPath1 = "/vaults/myVault.txt"; 119 | std::string invalidVaultPath2 = "/vaults/myVault."; 120 | 121 | TEST_ASSERT_TRUE(service.validateVaultFile(validVaultPath)); 122 | TEST_ASSERT_FALSE(service.validateVaultFile(invalidVaultPath1)); 123 | TEST_ASSERT_FALSE(service.validateVaultFile(invalidVaultPath2)); 124 | } 125 | 126 | #endif // TEST_SD_SERVICE 127 | -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Services/TestCryptoService.cpp" 4 | #include "Services/TestEntryService.cpp" 5 | #include "Services/TestCategoryService.cpp" 6 | #include "Services/TestSdService.cpp" 7 | #include "Services/TestNvsService.cpp" 8 | #include "Transformers/TestJsonTransformer.cpp" 9 | #include "Transformers/TestModelTransformer.cpp" 10 | #include "Transformers/TestTimeTransformer.cpp" 11 | #include "Selectors/TestVerticalSelector.cpp" 12 | #include "Selectors/TestHorizontalSelector.cpp" 13 | #include "Selectors/TestFieldEditorSelector.cpp" 14 | #include "Selectors/TestFieldActionSelector.cpp" 15 | #include "Selectors/TestConfirmationSelector.cpp" 16 | #include "Selectors/TestStringPromptSelector.cpp" 17 | #include "Enums/TestActionEnumMapper.cpp" 18 | #include "Enums/TestBaseColorEnumMapper.cpp" 19 | #include "Enums/TestIconEnumMapper.cpp" 20 | #include "Enums/TestKeyboardLayoutEnumMapper.cpp" 21 | #include "Controllers/TestVaultController.cpp" 22 | #include "Controllers/TestEntryController.cpp" 23 | #include "Controllers/TestUtilityController.cpp" 24 | 25 | void setup() { 26 | UNITY_BEGIN(); 27 | 28 | // CryptoService 29 | RUN_TEST(test_generateRandomString); 30 | RUN_TEST(test_generateHardwareRandom); 31 | RUN_TEST(test_deriveKeyFromPassphrase); 32 | RUN_TEST(test_encrypt_decrypt_AES); 33 | RUN_TEST(test_encrypt_decrypt_with_passphrase); 34 | RUN_TEST(test_generateChecksum); 35 | RUN_TEST(test_generateSalt); 36 | 37 | // EntryService 38 | RUN_TEST(test_isEntryExpired); 39 | RUN_TEST(test_add_and_find_entry); 40 | RUN_TEST(test_update_entry); 41 | RUN_TEST(test_get_all_entries); 42 | RUN_TEST(test_updateField); 43 | RUN_TEST(test_maxSavedPasswords); 44 | 45 | // CategoryService 46 | RUN_TEST(test_validateCategory); 47 | RUN_TEST(test_add_and_find_category); 48 | RUN_TEST(test_update_category); 49 | RUN_TEST(test_sort_categories_by_name); 50 | RUN_TEST(test_get_all_categories); 51 | RUN_TEST(test_delete_category); 52 | 53 | // SdService 54 | RUN_TEST(test_sd_begin); 55 | RUN_TEST(test_sd_close); 56 | RUN_TEST(test_read_write_file); 57 | RUN_TEST(test_append_to_file); 58 | RUN_TEST(test_list_elements); 59 | RUN_TEST(test_isFile); 60 | RUN_TEST(test_isDirectory); 61 | RUN_TEST(test_getFileName); 62 | RUN_TEST(test_getFileExt); 63 | RUN_TEST(test_getParentDirectory); 64 | RUN_TEST(test_validateVaultFile); 65 | 66 | // NvsService 67 | RUN_TEST(test_save_and_get_string); 68 | RUN_TEST(test_save_and_get_int); 69 | RUN_TEST(test_remove_key); 70 | 71 | // JsonTransformer 72 | RUN_TEST(test_to_json_categories); 73 | RUN_TEST(test_from_json_to_entries); 74 | RUN_TEST(test_from_json_to_categories); 75 | RUN_TEST(test_merge_entries_and_categories_to_json); 76 | 77 | // ModelTransformer 78 | RUN_TEST(test_transform_entries_to_strings); 79 | RUN_TEST(test_transform_single_entry_to_strings); 80 | RUN_TEST(test_transform_categories_to_strings); 81 | 82 | // TimeTransformer 83 | RUN_TEST(test_to_label); 84 | RUN_TEST(test_to_milliseconds); 85 | RUN_TEST(test_get_all_time_labels); 86 | RUN_TEST(test_get_all_time_values); 87 | 88 | // VerticalSelector 89 | RUN_TEST(test_vertical_selector_confirm); 90 | RUN_TEST(test_vertical_selector_cancel); 91 | RUN_TEST(test_vertical_selector_shortcut); 92 | 93 | // HorizontalSelector 94 | RUN_TEST(test_horizontal_selector_confirm); 95 | RUN_TEST(test_horizontal_selector_cancel); 96 | 97 | // FieldEditorSelector 98 | RUN_TEST(test_field_editor_selector_confirm); 99 | RUN_TEST(test_field_editor_selector_cancel); 100 | 101 | // FieldActionSelector 102 | RUN_TEST(test_field_action_selector_send_to_usb); 103 | RUN_TEST(test_field_action_selector_update_field); 104 | RUN_TEST(test_field_action_selector_cancel); 105 | 106 | // ConfirmationSelector 107 | RUN_TEST(test_confirmation_selector_confirm); 108 | RUN_TEST(test_confirmation_selector_cancel); 109 | 110 | // StringPromptSelector 111 | RUN_TEST(test_string_selector_confirm); 112 | RUN_TEST(test_string_selector_cancel); 113 | 114 | // ActionEnumMapper 115 | RUN_TEST(test_action_enum_to_string); 116 | RUN_TEST(test_action_enum_get_action_names); 117 | 118 | // BaseColorEnumMapper 119 | RUN_TEST(test_base_color_enum_to_string); 120 | RUN_TEST(test_base_color_enum_to_color_value); 121 | RUN_TEST(test_base_color_enum_get_all_color_names); 122 | 123 | // IconEnumMapper 124 | RUN_TEST(test_icon_enum_to_string); 125 | RUN_TEST(test_icon_enum_get_icon_names); 126 | 127 | // KeyboardLayoutMapper 128 | RUN_TEST(test_to_layout_valid_name); 129 | RUN_TEST(test_to_layout_invalid_name); 130 | RUN_TEST(test_get_all_layout_names); 131 | 132 | // VaultController 133 | RUN_TEST(test_actionNoVault); 134 | RUN_TEST(test_actionVaultSelected); 135 | RUN_TEST(test_handleVaultCreation); 136 | RUN_TEST(test_handleVaultSave); 137 | RUN_TEST(test_handleVaultSave_maxEntries); 138 | RUN_TEST(test_handleVaultLoading); 139 | 140 | // EntryController 141 | RUN_TEST(test_handleEntryCreation); 142 | RUN_TEST(test_handleEntryUpdate); 143 | RUN_TEST(test_handleEntryDeletion); 144 | 145 | // UtilityController 146 | RUN_TEST(test_handleGeneralSettings); 147 | 148 | UNITY_END(); 149 | } 150 | 151 | void loop() { 152 | // Required by PlatformIO 153 | } 154 | -------------------------------------------------------------------------------- /lib/USBHIDKeyboard/USBHIDKeyboard.h: -------------------------------------------------------------------------------- 1 | /* 2 | Keyboard.h 3 | 4 | Copyright (c) 2015, Arduino LLC 5 | Original code (pre-library): Copyright (c) 2011, Peter Barrett 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #pragma once 23 | #include "Print.h" 24 | #include "USBHID.h" 25 | #if CONFIG_TINYUSB_HID_ENABLED 26 | 27 | #include "esp_event.h" 28 | 29 | ESP_EVENT_DECLARE_BASE(ARDUINO_USB_HID_KEYBOARD_EVENTS); 30 | 31 | typedef enum { 32 | ARDUINO_USB_HID_KEYBOARD_ANY_EVENT = ESP_EVENT_ANY_ID, 33 | ARDUINO_USB_HID_KEYBOARD_LED_EVENT = 0, 34 | ARDUINO_USB_HID_KEYBOARD_MAX_EVENT, 35 | } arduino_usb_hid_keyboard_event_t; 36 | 37 | typedef union { 38 | struct { 39 | uint8_t numlock:1; 40 | uint8_t capslock:1; 41 | uint8_t scrolllock:1; 42 | uint8_t compose:1; 43 | uint8_t kana:1; 44 | uint8_t reserved:3; 45 | }; 46 | uint8_t leds; 47 | } arduino_usb_hid_keyboard_event_data_t; 48 | 49 | #define KEY_LEFT_CTRL 0x80 50 | #define KEY_LEFT_SHIFT 0x81 51 | #define KEY_LEFT_ALT 0x82 52 | #define KEY_LEFT_GUI 0x83 53 | #define KEY_RIGHT_CTRL 0x84 54 | #define KEY_RIGHT_SHIFT 0x85 55 | #define KEY_RIGHT_ALT 0x86 56 | #define KEY_RIGHT_GUI 0x87 57 | 58 | #define KEY_UP_ARROW 0xDA 59 | #define KEY_DOWN_ARROW 0xD9 60 | #define KEY_LEFT_ARROW 0xD8 61 | #define KEY_RIGHT_ARROW 0xD7 62 | #define KEYBACKSPACE 0xB2 //changed from KEY_BACKSPACE due to compatibility to cardputer keyboard 63 | #define KEYTAB 0xB3 64 | #define KEY_RETURN 0xB0 65 | #define KEY_ESC 0xB1 66 | #define KEY_PRINT_SCREEN 0xCE 67 | #define KEY_SCROLL_LOCK 0xCF 68 | #define KEY_PAUSE 0xD0 69 | #define KEY_INSERT 0xD1 70 | #define KEY_DELETE 0xD4 71 | #define KEY_PAGE_UP 0xD3 72 | #define KEY_PAGE_DOWN 0xD6 73 | #define KEY_HOME 0xD2 74 | #define KEY_END 0xD5 75 | #define KEY_MENU 0xED 76 | #define KEY_CAPS_LOCK 0xC1 77 | #define KEY_F1 0xC2 78 | #define KEY_F2 0xC3 79 | #define KEY_F3 0xC4 80 | #define KEY_F4 0xC5 81 | #define KEY_F5 0xC6 82 | #define KEY_F6 0xC7 83 | #define KEY_F7 0xC8 84 | #define KEY_F8 0xC9 85 | #define KEY_F9 0xCA 86 | #define KEY_F10 0xCB 87 | #define KEY_F11 0xCC 88 | #define KEY_F12 0xCD 89 | #define KEY_F13 0xF0 90 | #define KEY_F14 0xF1 91 | #define KEY_F15 0xF2 92 | #define KEY_F16 0xF3 93 | #define KEY_F17 0xF4 94 | #define KEY_F18 0xF5 95 | #define KEY_F19 0xF6 96 | #define KEY_F20 0xF7 97 | #define KEY_F21 0xF8 98 | #define KEY_F22 0xF9 99 | #define KEY_F23 0xFA 100 | #define KEY_F24 0xFB 101 | 102 | #define LED_NUMLOCK 0x01 103 | #define LED_CAPSLOCK 0x02 104 | #define LED_SCROLLLOCK 0x04 105 | #define LED_COMPOSE 0x08 106 | #define LED_KANA 0x10 107 | #define KEY_SPACE 0x2c 108 | 109 | 110 | 111 | 112 | 113 | // Supported keyboard layouts 114 | extern const uint8_t KeyboardLayout_de_DE[]; 115 | extern const uint8_t KeyboardLayout_en_US[]; 116 | extern const uint8_t KeyboardLayout_en_UK[]; 117 | extern const uint8_t KeyboardLayout_es_ES[]; 118 | extern const uint8_t KeyboardLayout_fr_FR[]; 119 | extern const uint8_t KeyboardLayout_it_IT[]; 120 | extern const uint8_t KeyboardLayout_pt_PT[]; 121 | extern const uint8_t KeyboardLayout_pt_BR[]; 122 | extern const uint8_t KeyboardLayout_sv_SE[]; 123 | extern const uint8_t KeyboardLayout_da_DK[]; 124 | extern const uint8_t KeyboardLayout_hu_HU[]; 125 | 126 | // Low level key report: up to 6 keys and shift, ctrl etc at once 127 | typedef struct 128 | { 129 | uint8_t modifiers; 130 | uint8_t reserved; 131 | uint8_t keys[6]; 132 | } KeyReport; 133 | 134 | class USBHIDKeyboard: public USBHIDDevice, public Print 135 | { 136 | private: 137 | USBHID hid; 138 | KeyReport _keyReport; 139 | const uint8_t *_asciimap; 140 | public: 141 | USBHIDKeyboard(void); 142 | void begin(const uint8_t *layout = KeyboardLayout_en_US); //void begin(void); 143 | void end(void); 144 | size_t write(uint8_t k); 145 | size_t write(const uint8_t *buffer, size_t size); 146 | size_t press(uint8_t k); 147 | size_t release(uint8_t k); 148 | void releaseAll(void); 149 | void sendReport(KeyReport* keys); 150 | 151 | //raw functions work with TinyUSB's HID_KEY_* macros 152 | size_t pressRaw(uint8_t k); 153 | size_t releaseRaw(uint8_t k); 154 | 155 | void onEvent(esp_event_handler_t callback); 156 | void onEvent(arduino_usb_hid_keyboard_event_t event, esp_event_handler_t callback); 157 | 158 | // internal use 159 | uint16_t _onGetDescriptor(uint8_t* buffer); 160 | void _onOutput(uint8_t report_id, const uint8_t* buffer, uint16_t len); 161 | }; 162 | 163 | #endif 164 | --------------------------------------------------------------------------------