[FL-1419] new iButton cli (#521)
* iButton, helpers: add destructor * iButton app: new approach to cli commands, cli read * iButton app: cli write * iButton app: cli emulate * iButton app: remove old cli commands * iButton app: use unique_ptr for worker * iButton app: remove obsolete cli help * iButton app: fix help and key type parsing
This commit is contained in:
		
							parent
							
								
									9943c93189
								
							
						
					
					
						commit
						89dd1ff925
					
				| @ -47,6 +47,7 @@ void nfc_cli_init(); | ||||
| void subghz_cli_init(); | ||||
| void bt_cli_init(); | ||||
| void lfrfid_cli_init(); | ||||
| void ibutton_cli_init(); | ||||
| 
 | ||||
| const FlipperApplication FLIPPER_SERVICES[] = { | ||||
| #ifdef SRV_CLI | ||||
| @ -216,6 +217,9 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { | ||||
| #ifdef APP_LF_RFID | ||||
|     lfrfid_cli_init, | ||||
| #endif | ||||
| #ifdef APP_IBUTTON | ||||
|     ibutton_cli_init, | ||||
| #endif | ||||
| #ifdef SRV_BT | ||||
|     bt_cli_init, | ||||
| #endif | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| KeyEmulator::~KeyEmulator() { | ||||
|     onewire_slave->stop(); | ||||
|     stop(); | ||||
| } | ||||
| 
 | ||||
| KeyEmulator::KeyEmulator(OneWireSlave* _onewire_slave) | ||||
|  | ||||
| @ -49,3 +49,6 @@ KeyWorker::KeyWorker(const GpioPin* one_wire_gpio) | ||||
|     , key_emulator{&onewire_slave} | ||||
|     , key_writer{&onewire_master} { | ||||
| } | ||||
| 
 | ||||
| KeyWorker::~KeyWorker() { | ||||
| } | ||||
| @ -23,6 +23,7 @@ public: | ||||
|     void stop_write(); | ||||
| 
 | ||||
|     KeyWorker(const GpioPin* one_wire_gpio); | ||||
|     ~KeyWorker(); | ||||
| 
 | ||||
| private: | ||||
|     // one wire
 | ||||
|  | ||||
| @ -5,6 +5,10 @@ KeyWriter::KeyWriter(OneWireMaster* _onewire_master) { | ||||
|     onewire_master = _onewire_master; | ||||
| } | ||||
| 
 | ||||
| KeyWriter::~KeyWriter() { | ||||
|     stop(); | ||||
| } | ||||
| 
 | ||||
| KeyWriter::Error KeyWriter::write(iButtonKey* key) { | ||||
|     return write_internal(key); | ||||
| } | ||||
|  | ||||
| @ -28,171 +28,14 @@ void iButtonApp::run(void) { | ||||
|     scenes[current_scene]->on_exit(this); | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::print_key_data(void) { | ||||
|     uint8_t* key_data = key.get_data(); | ||||
|     switch(key.get_key_type()) { | ||||
|     case iButtonKeyType::KeyDallas: | ||||
|         printf( | ||||
|             "Dallas %02X %02X %02X %02X %02X %02X %02X %02X\r\n", | ||||
|             key_data[0], | ||||
|             key_data[1], | ||||
|             key_data[2], | ||||
|             key_data[3], | ||||
|             key_data[4], | ||||
|             key_data[5], | ||||
|             key_data[6], | ||||
|             key_data[7]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyCyfral: | ||||
|         printf("Cyfral %02X %02X\r\n", key_data[0], key_data[1]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyMetakom: | ||||
|         printf( | ||||
|             "Metakom %02X %02X %02X %02X\r\n", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool iButtonApp::read_hex_byte(string_t args, uint8_t* byte) { | ||||
|     char* endptr; | ||||
|     *byte = strtoul(string_get_cstr(args), &endptr, 16); | ||||
|     if(*endptr == '\0') { | ||||
|         return false; | ||||
|     } | ||||
|     size_t ws = string_search_char(args, ' '); | ||||
|     if(ws != 2) { | ||||
|         return false; | ||||
|     } | ||||
|     string_right(args, ws); | ||||
|     string_strim(args); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::cli_cmd_callback(Cli* cli, string_t args, void* context) { | ||||
|     iButtonApp::Scene scene; | ||||
|     string_t cmd; | ||||
|     string_init(cmd); | ||||
|     if(!string_cmp_str(args, "read")) { | ||||
|         scene = iButtonApp::Scene::SceneCliRead; | ||||
|         printf("Reading key ...\r\n"); | ||||
|     } else { | ||||
|         // Parse write / emulate commands
 | ||||
|         size_t ws = string_search_char(args, ' '); | ||||
|         if(ws == STRING_FAILURE) { | ||||
|             printf("Incorrect input. Try tm <read | write | emulate> [key_type] [key_data]"); | ||||
|             string_clear(cmd); | ||||
|             return; | ||||
|         } else { | ||||
|             string_set_n(cmd, args, 0, ws); | ||||
|             string_right(args, ws); | ||||
|             string_strim(args); | ||||
|         } | ||||
|         if(!string_cmp_str(cmd, "write")) { | ||||
|             scene = iButtonApp::Scene::SceneCliWrite; | ||||
|         } else if(!string_cmp_str(cmd, "emulate")) { | ||||
|             scene = iButtonApp::Scene::SceneCliEmulate; | ||||
|         } else { | ||||
|             printf("Incorrect input. Try tm <write | emulate> <key_type> <key_data>"); | ||||
|             string_clear(cmd); | ||||
|             return; | ||||
|         } | ||||
|         string_clear(cmd); | ||||
|         // Parse key type
 | ||||
|         string_t key_type; | ||||
|         string_init(key_type); | ||||
|         ws = string_search_char(args, ' '); | ||||
|         string_set_n(key_type, args, 0, ws); | ||||
|         uint8_t bytes_to_read = 0; | ||||
|         if(!string_cmp_str(key_type, "0")) { | ||||
|             key.set_type(iButtonKeyType::KeyDallas); | ||||
|             bytes_to_read = 8; | ||||
|         } else if(!string_cmp_str(key_type, "1")) { | ||||
|             key.set_type(iButtonKeyType::KeyCyfral); | ||||
|             bytes_to_read = 2; | ||||
|         } else if(!string_cmp_str(key_type, "2")) { | ||||
|             key.set_type(iButtonKeyType::KeyMetakom); | ||||
|             bytes_to_read = 4; | ||||
|         } else { | ||||
|             printf("Incorrect key type. Try 0 - KeyDallas, 1 - KeyCyfral, 2 - KeyMetakom"); | ||||
|             string_clear(key_type); | ||||
|             return; | ||||
|         } | ||||
|         string_clear(key_type); | ||||
|         // Read key data
 | ||||
|         string_right(args, 1); | ||||
|         string_strim(args); | ||||
|         uint8_t key_data[8] = {}; | ||||
|         uint8_t i = 0; | ||||
|         bool ret = true; | ||||
|         while((i < bytes_to_read) && ret) { | ||||
|             ret = read_hex_byte(args, &key_data[i++]); | ||||
|         } | ||||
|         if(i != bytes_to_read) { | ||||
|             printf("Incorrect key data. Type %d key data hex digits", bytes_to_read); | ||||
|             return; | ||||
|         } | ||||
|         key.set_data(key_data, bytes_to_read); | ||||
|         if(scene == iButtonApp::Scene::SceneCliWrite) { | ||||
|             printf("Writing key "); | ||||
|         } else { | ||||
|             printf("Emulating key "); | ||||
|         } | ||||
|         print_key_data(); | ||||
|     } | ||||
|     switch_to_next_scene(scene); | ||||
|     // Wait return event
 | ||||
|     iButtonApp::CliEvent result; | ||||
|     if(osMessageQueueGet(cli_event_result, &result, NULL, osWaitForever) != osOK) { | ||||
|         printf("Command execution error"); | ||||
|         return; | ||||
|     } | ||||
|     // Process return event
 | ||||
|     switch(result) { | ||||
|     case iButtonApp::CliEvent::CliReadSuccess: | ||||
|     case iButtonApp::CliEvent::CliReadCRCError: | ||||
|         print_key_data(); | ||||
|         if(result == iButtonApp::CliEvent::CliReadCRCError) { | ||||
|             printf("Warning: invalid CRC"); | ||||
|         } | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliReadNotKeyError: | ||||
|         printf("Read error: not a key"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliTimeout: | ||||
|         printf("Timeout error"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliInterrupt: | ||||
|         printf("Command interrupted"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliWriteSuccess: | ||||
|         printf("Write success"); | ||||
|         break; | ||||
|     case iButtonApp::CliEvent::CliWriteFail: | ||||
|         printf("Write fail"); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     return; | ||||
| } | ||||
| 
 | ||||
| void iButtonApp::cli_send_event(iButtonApp::CliEvent scene) { | ||||
|     osMessageQueuePut(cli_event_result, &scene, 0, osWaitForever); | ||||
| } | ||||
| 
 | ||||
| iButtonApp::iButtonApp() { | ||||
|     api_hal_power_insomnia_enter(); | ||||
| 
 | ||||
|     cli_event_result = osMessageQueueNew(1, sizeof(iButtonApp::Scene), NULL); | ||||
|     key_worker = new KeyWorker(&ibutton_gpio); | ||||
|     sd_ex_api = static_cast<SdCard_Api*>(furi_record_open("sdcard-ex")); | ||||
|     fs_api = static_cast<FS_Api*>(furi_record_open("sdcard")); | ||||
|     cli = static_cast<Cli*>(furi_record_open("cli")); | ||||
|     notification = static_cast<NotificationApp*>(furi_record_open("notification")); | ||||
| 
 | ||||
|     auto callback = cbc::obtain_connector(this, &iButtonApp::cli_cmd_callback); | ||||
|     cli_add_command(cli, "tm", callback, cli); | ||||
| 
 | ||||
|     // we need random
 | ||||
|     srand(DWT->CYCCNT); | ||||
| } | ||||
| @ -202,11 +45,8 @@ iButtonApp::~iButtonApp() { | ||||
| 
 | ||||
|     furi_record_close("sdcard-ex"); | ||||
|     furi_record_close("sdcard"); | ||||
|     furi_record_close("cli"); | ||||
|     furi_record_close("notification"); | ||||
| 
 | ||||
|     osMessageQueueDelete(cli_event_result); | ||||
| 
 | ||||
|     for(std::map<Scene, iButtonScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) { | ||||
|         delete it->second; | ||||
|         scenes.erase(it); | ||||
|  | ||||
| @ -6,19 +6,16 @@ | ||||
| #include "scene/ibutton-scene-generic.h" | ||||
| #include "scene/ibutton-scene-start.h" | ||||
| #include "scene/ibutton-scene-read.h" | ||||
| #include "scene/ibutton-scene-cli-read.h" | ||||
| #include "scene/ibutton-scene-read-crc-error.h" | ||||
| #include "scene/ibutton-scene-read-not-key-error.h" | ||||
| #include "scene/ibutton-scene-read-success.h" | ||||
| #include "scene/ibutton-scene-readed-key-menu.h" | ||||
| #include "scene/ibutton-scene-write.h" | ||||
| #include "scene/ibutton-scene-cli-write.h" | ||||
| #include "scene/ibutton-scene-write-success.h" | ||||
| #include "scene/ibutton-scene-saved-key-menu.h" | ||||
| #include "scene/ibutton-scene-delete-confirm.h" | ||||
| #include "scene/ibutton-scene-delete-success.h" | ||||
| #include "scene/ibutton-scene-emulate.h" | ||||
| #include "scene/ibutton-scene-cli-emulate.h" | ||||
| #include "scene/ibutton-scene-save-name.h" | ||||
| #include "scene/ibutton-scene-save-success.h" | ||||
| #include "scene/ibutton-scene-info.h" | ||||
| @ -49,16 +46,13 @@ public: | ||||
|         SceneExit, | ||||
|         SceneStart, | ||||
|         SceneRead, | ||||
|         SceneCliRead, | ||||
|         SceneReadNotKeyError, | ||||
|         SceneReadCRCError, | ||||
|         SceneReadSuccess, | ||||
|         SceneReadedKeyMenu, | ||||
|         SceneWrite, | ||||
|         SceneCliWrite, | ||||
|         SceneWriteSuccess, | ||||
|         SceneEmulate, | ||||
|         SceneCliEmulate, | ||||
|         SceneSavedKeyMenu, | ||||
|         SceneDeleteConfirm, | ||||
|         SceneDeleteSuccess, | ||||
| @ -70,16 +64,6 @@ public: | ||||
|         SceneAddValue, | ||||
|     }; | ||||
| 
 | ||||
|     enum class CliEvent : uint8_t { | ||||
|         CliReadSuccess, | ||||
|         CliReadCRCError, | ||||
|         CliReadNotKeyError, | ||||
|         CliWriteSuccess, | ||||
|         CliWriteFail, | ||||
|         CliTimeout, | ||||
|         CliInterrupt, | ||||
|     }; | ||||
| 
 | ||||
|     iButtonAppViewManager* get_view_manager(); | ||||
|     void switch_to_next_scene(Scene index); | ||||
|     void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list); | ||||
| @ -110,9 +94,6 @@ public: | ||||
|     char* get_file_name(); | ||||
|     uint8_t get_file_name_size(); | ||||
| 
 | ||||
|     void cli_cmd_callback(Cli* cli, string_t args, void* context); | ||||
|     void cli_send_event(CliEvent scene); | ||||
| 
 | ||||
|     void generate_random_name(char* name, uint8_t max_name_size); | ||||
| 
 | ||||
|     bool save_key(const char* key_name); | ||||
| @ -123,21 +104,17 @@ private: | ||||
|     std::list<Scene> previous_scenes_list = {Scene::SceneExit}; | ||||
|     Scene current_scene = Scene::SceneStart; | ||||
|     iButtonAppViewManager view; | ||||
|     osMessageQueueId_t cli_event_result; | ||||
| 
 | ||||
|     std::map<Scene, iButtonScene*> scenes = { | ||||
|         {Scene::SceneStart, new iButtonSceneStart()}, | ||||
|         {Scene::SceneRead, new iButtonSceneRead()}, | ||||
|         {Scene::SceneCliRead, new iButtonSceneCliRead()}, | ||||
|         {Scene::SceneReadCRCError, new iButtonSceneReadCRCError()}, | ||||
|         {Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()}, | ||||
|         {Scene::SceneReadSuccess, new iButtonSceneReadSuccess()}, | ||||
|         {Scene::SceneReadedKeyMenu, new iButtonSceneReadedKeyMenu()}, | ||||
|         {Scene::SceneWrite, new iButtonSceneWrite()}, | ||||
|         {Scene::SceneCliWrite, new iButtonSceneCliWrite()}, | ||||
|         {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, | ||||
|         {Scene::SceneEmulate, new iButtonSceneEmulate()}, | ||||
|         {Scene::SceneCliEmulate, new iButtonSceneCliEmulate()}, | ||||
|         {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, | ||||
|         {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, | ||||
|         {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, | ||||
| @ -164,9 +141,6 @@ private: | ||||
| 
 | ||||
|     NotificationApp* notification; | ||||
| 
 | ||||
|     bool read_hex_byte(string_t arg, uint8_t* byte); | ||||
|     void print_key_data(void); | ||||
| 
 | ||||
|     static const char* app_folder; | ||||
|     static const char* app_extension; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										234
									
								
								applications/ibutton/ibutton-cli.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								applications/ibutton/ibutton-cli.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,234 @@ | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <stdarg.h> | ||||
| #include <cli/cli.h> | ||||
| #include <args.h> | ||||
| 
 | ||||
| #include "helpers/key-info.h" | ||||
| #include "helpers/key-worker.h" | ||||
| 
 | ||||
| #include <memory> | ||||
| 
 | ||||
| void ibutton_cli(Cli* cli, string_t args, void* context); | ||||
| 
 | ||||
| // app cli function
 | ||||
| extern "C" void ibutton_cli_init() { | ||||
|     Cli* cli = static_cast<Cli*>(furi_record_open("cli")); | ||||
|     cli_add_command(cli, "tm", ibutton_cli, cli); | ||||
|     furi_record_close("cli"); | ||||
| } | ||||
| 
 | ||||
| void ibutton_cli_print_usage() { | ||||
|     printf("Usage:\r\n"); | ||||
|     printf("tm read\r\n"); | ||||
|     printf("tm <write | emulate> <key_type> <key_data>\r\n"); | ||||
|     printf("\t<key_type> choose from:\r\n"); | ||||
|     printf("\tDallas (8 bytes key_data)\r\n"); | ||||
|     printf("\tCyfral (2 bytes key_data)\r\n"); | ||||
|     printf("\tMetakom (4 bytes key_data)\r\n"); | ||||
|     printf("\t<key_data> are hex-formatted\r\n"); | ||||
| }; | ||||
| 
 | ||||
| bool ibutton_cli_get_key_type(string_t data, iButtonKeyType* type) { | ||||
|     bool result = false; | ||||
| 
 | ||||
|     if(string_cmp_str(data, "Dallas") == 0 || string_cmp_str(data, "dallas") == 0) { | ||||
|         result = true; | ||||
|         *type = iButtonKeyType::KeyDallas; | ||||
|     } else if(string_cmp_str(data, "Cyfral") == 0 || string_cmp_str(data, "cyfral") == 0) { | ||||
|         result = true; | ||||
|         *type = iButtonKeyType::KeyCyfral; | ||||
|     } else if(string_cmp_str(data, "Metakom") == 0 || string_cmp_str(data, "metakom") == 0) { | ||||
|         result = true; | ||||
|         *type = iButtonKeyType::KeyMetakom; | ||||
|     } | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| void ibutton_cli_print_key_data(iButtonKey* key) { | ||||
|     uint8_t* key_data = key->get_data(); | ||||
|     switch(key->get_key_type()) { | ||||
|     case iButtonKeyType::KeyDallas: | ||||
|         printf( | ||||
|             "Dallas %02X%02X%02X%02X%02X%02X%02X%02X\r\n", | ||||
|             key_data[0], | ||||
|             key_data[1], | ||||
|             key_data[2], | ||||
|             key_data[3], | ||||
|             key_data[4], | ||||
|             key_data[5], | ||||
|             key_data[6], | ||||
|             key_data[7]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyCyfral: | ||||
|         printf("Cyfral %02X%02X\r\n", key_data[0], key_data[1]); | ||||
|         break; | ||||
|     case iButtonKeyType::KeyMetakom: | ||||
|         printf("Metakom %02X%02X%02X%02X\r\n", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ibutton_cli_read(Cli* cli) { | ||||
|     iButtonKey key; | ||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); | ||||
| 
 | ||||
|     bool exit = false; | ||||
| 
 | ||||
|     worker->start_read(); | ||||
|     printf("Reading iButton...\r\nPress Ctrl+C to abort\r\n"); | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         exit = cli_cmd_interrupt_received(cli); | ||||
| 
 | ||||
|         switch(worker->read(&key)) { | ||||
|         case KeyReader::Error::EMPTY: | ||||
|             break; | ||||
|         case KeyReader::Error::CRC_ERROR: | ||||
|             ibutton_cli_print_key_data(&key); | ||||
|             printf("Warning: invalid CRC\r\n"); | ||||
|             exit = true; | ||||
|             break; | ||||
|         case KeyReader::Error::OK: | ||||
|             ibutton_cli_print_key_data(&key); | ||||
|             exit = true; | ||||
|             break; | ||||
|         case KeyReader::Error::NOT_ARE_KEY: | ||||
|             ibutton_cli_print_key_data(&key); | ||||
|             printf("Warning: not a key\r\n"); | ||||
|             exit = true; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         delay(100); | ||||
|     } | ||||
| 
 | ||||
|     worker->stop_read(); | ||||
| }; | ||||
| 
 | ||||
| void ibutton_cli_write(Cli* cli, string_t args) { | ||||
|     iButtonKey key; | ||||
|     iButtonKeyType type; | ||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); | ||||
| 
 | ||||
|     bool exit = false; | ||||
|     string_t data; | ||||
|     string_init(data); | ||||
| 
 | ||||
|     if(!args_read_string_and_trim(args, data)) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(!ibutton_cli_get_key_type(data, &type)) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     key.set_type(type); | ||||
| 
 | ||||
|     if(!args_read_hex_bytes(args, key.get_data(), key.get_type_data_size())) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     printf("Writing key "); | ||||
|     ibutton_cli_print_key_data(&key); | ||||
|     printf("Press Ctrl+C to abort\r\n"); | ||||
| 
 | ||||
|     worker->start_write(); | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         exit = cli_cmd_interrupt_received(cli); | ||||
| 
 | ||||
|         KeyWriter::Error result = worker->write(&key); | ||||
| 
 | ||||
|         switch(result) { | ||||
|         case KeyWriter::Error::SAME_KEY: | ||||
|         case KeyWriter::Error::OK: | ||||
|             printf("Write success\r\n"); | ||||
|             exit = true; | ||||
|             break; | ||||
|         case KeyWriter::Error::NO_DETECT: | ||||
|             break; | ||||
|         case KeyWriter::Error::CANNOT_WRITE: | ||||
|             printf("Write fail\r\n"); | ||||
|             exit = true; | ||||
|             break; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     worker->stop_write(); | ||||
| 
 | ||||
|     string_clear(data); | ||||
| }; | ||||
| 
 | ||||
| void ibutton_cli_emulate(Cli* cli, string_t args) { | ||||
|     iButtonKey key; | ||||
|     iButtonKeyType type; | ||||
|     std::unique_ptr<KeyWorker> worker(new KeyWorker(&ibutton_gpio)); | ||||
|     bool exit = false; | ||||
|     string_t data; | ||||
|     string_init(data); | ||||
| 
 | ||||
|     if(!args_read_string_and_trim(args, data)) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(!ibutton_cli_get_key_type(data, &type)) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     key.set_type(type); | ||||
| 
 | ||||
|     if(!args_read_hex_bytes(args, key.get_data(), key.get_type_data_size())) { | ||||
|         ibutton_cli_print_usage(); | ||||
|         string_clear(data); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     printf("Emulating key "); | ||||
|     ibutton_cli_print_key_data(&key); | ||||
|     printf("Press Ctrl+C to abort\r\n"); | ||||
| 
 | ||||
|     worker->start_emulate(&key); | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         exit = cli_cmd_interrupt_received(cli); | ||||
|     }; | ||||
| 
 | ||||
|     worker->stop_emulate(); | ||||
| 
 | ||||
|     string_clear(data); | ||||
| }; | ||||
| 
 | ||||
| void ibutton_cli(Cli* cli, string_t args, void* context) { | ||||
|     string_t cmd; | ||||
|     string_init(cmd); | ||||
| 
 | ||||
|     if(!args_read_string_and_trim(args, cmd)) { | ||||
|         string_clear(cmd); | ||||
|         ibutton_cli_print_usage(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if(string_cmp_str(cmd, "read") == 0) { | ||||
|         ibutton_cli_read(cli); | ||||
|     } else if(string_cmp_str(cmd, "write") == 0) { | ||||
|         ibutton_cli_write(cli, args); | ||||
|     } else if(string_cmp_str(cmd, "emulate") == 0) { | ||||
|         ibutton_cli_emulate(cli, args); | ||||
|     } else { | ||||
|         ibutton_cli_print_usage(); | ||||
|     } | ||||
| 
 | ||||
|     string_clear(cmd); | ||||
| } | ||||
| @ -1,102 +0,0 @@ | ||||
| #include "ibutton-scene-cli-emulate.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| #include "../ibutton-key.h" | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| void iButtonSceneCliEmulate::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     iButtonKey* key = app->get_key(); | ||||
|     uint8_t* key_data = key->get_data(); | ||||
|     const char* key_name = key->get_name(); | ||||
|     uint8_t line_count = 2; | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     // check that stored key has name
 | ||||
|     if(strcmp(key_name, "") != 0) { | ||||
|         app->set_text_store("emulating\n%s", key_name); | ||||
|         line_count = 2; | ||||
|     } else { | ||||
|         // if not, show key data
 | ||||
|         switch(key->get_key_type()) { | ||||
|         case iButtonKeyType::KeyDallas: | ||||
|             app->set_text_store( | ||||
|                 "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3], | ||||
|                 key_data[4], | ||||
|                 key_data[5], | ||||
|                 key_data[6], | ||||
|                 key_data[7]); | ||||
|             line_count = 3; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyCyfral: | ||||
|             app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyMetakom: | ||||
|             app->set_text_store( | ||||
|                 "emulating\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     switch(line_count) { | ||||
|     case 3: | ||||
|         popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
|     app->get_key_worker()->start_emulate(app->get_key()); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliEmulate::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|         } else { | ||||
|             if(app->get_key_worker()->emulated()) { | ||||
|                 app->notify_yellow_blink(); | ||||
|             } else { | ||||
|                 app->notify_red_blink(); | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliEmulate::on_exit(iButtonApp* app) { | ||||
|     app->get_key_worker()->stop_emulate(); | ||||
| 
 | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| #include "../helpers/key-emulator.h" | ||||
| 
 | ||||
| class iButtonSceneCliEmulate : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
| @ -1,65 +0,0 @@ | ||||
| #include "ibutton-scene-cli-read.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| 
 | ||||
| void iButtonSceneCliRead::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, 0, 5, I_DolphinWait_61x59); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
|     app->get_key()->set_name(""); | ||||
| 
 | ||||
|     app->get_key_worker()->start_read(); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliRead::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         app->notify_red_blink(); | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|             return consumed; | ||||
|         } else { | ||||
|             switch(app->get_key_worker()->read(app->get_key())) { | ||||
|             case KeyReader::Error::EMPTY: | ||||
|                 break; | ||||
|             case KeyReader::Error::OK: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadSuccess); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyReader::Error::CRC_ERROR: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadCRCError); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyReader::Error::NOT_ARE_KEY: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliReadNotKeyError); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliRead::on_exit(iButtonApp* app) { | ||||
|     app->get_key_worker()->stop_read(); | ||||
| 
 | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| } | ||||
| @ -1,12 +0,0 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| 
 | ||||
| class iButtonSceneCliRead : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
| @ -1,109 +0,0 @@ | ||||
| #include "ibutton-scene-cli-write.h" | ||||
| #include "../ibutton-app.h" | ||||
| #include "../ibutton-view-manager.h" | ||||
| #include "../ibutton-event.h" | ||||
| #include "../ibutton-key.h" | ||||
| 
 | ||||
| void iButtonSceneCliWrite::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     iButtonKey* key = app->get_key(); | ||||
|     uint8_t* key_data = key->get_data(); | ||||
|     const char* key_name = key->get_name(); | ||||
|     uint8_t line_count = 2; | ||||
|     timeout = 50; // 5s timeout
 | ||||
| 
 | ||||
|     // check that stored key has name
 | ||||
|     if(strcmp(key_name, "") != 0) { | ||||
|         app->set_text_store("writing\n%s", key_name); | ||||
|         line_count = 2; | ||||
|     } else { | ||||
|         // if not, show key data
 | ||||
|         switch(key->get_key_type()) { | ||||
|         case iButtonKeyType::KeyDallas: | ||||
|             app->set_text_store( | ||||
|                 "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", | ||||
|                 key_data[0], | ||||
|                 key_data[1], | ||||
|                 key_data[2], | ||||
|                 key_data[3], | ||||
|                 key_data[4], | ||||
|                 key_data[5], | ||||
|                 key_data[6], | ||||
|                 key_data[7]); | ||||
|             line_count = 3; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyCyfral: | ||||
|             app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         case iButtonKeyType::KeyMetakom: | ||||
|             app->set_text_store( | ||||
|                 "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); | ||||
|             line_count = 2; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     switch(line_count) { | ||||
|     case 3: | ||||
|         popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); | ||||
|         popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); | ||||
| 
 | ||||
|     view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); | ||||
| 
 | ||||
|     app->get_key_worker()->start_write(); | ||||
| } | ||||
| 
 | ||||
| bool iButtonSceneCliWrite::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTick) { | ||||
|         consumed = true; | ||||
|         if(!timeout--) { | ||||
|             app->cli_send_event(iButtonApp::CliEvent::CliTimeout); | ||||
|             app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|         } else { | ||||
|             KeyWriter::Error result = app->get_key_worker()->write(app->get_key()); | ||||
| 
 | ||||
|             switch(result) { | ||||
|             case KeyWriter::Error::SAME_KEY: | ||||
|             case KeyWriter::Error::OK: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliWriteSuccess); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             case KeyWriter::Error::NO_DETECT: | ||||
|                 app->notify_red_blink(); | ||||
|                 break; | ||||
|             case KeyWriter::Error::CANNOT_WRITE: | ||||
|                 app->cli_send_event(iButtonApp::CliEvent::CliWriteFail); | ||||
|                 app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } else if(event->type == iButtonEvent::Type::EventTypeBack) { | ||||
|         consumed = false; | ||||
|         app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void iButtonSceneCliWrite::on_exit(iButtonApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
| 
 | ||||
|     app->get_key_worker()->stop_write(); | ||||
| } | ||||
| @ -1,12 +0,0 @@ | ||||
| #pragma once | ||||
| #include "ibutton-scene-generic.h" | ||||
| 
 | ||||
| class iButtonSceneCliWrite : public iButtonScene { | ||||
| public: | ||||
|     void on_enter(iButtonApp* app) final; | ||||
|     bool on_event(iButtonApp* app, iButtonEvent* event) final; | ||||
|     void on_exit(iButtonApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint16_t timeout; | ||||
| }; | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG