diff --git a/applications/main/infrared/infrared_app_i.h b/applications/main/infrared/infrared_app_i.h index c35d3fa41..7a9202b28 100644 --- a/applications/main/infrared/infrared_app_i.h +++ b/applications/main/infrared/infrared_app_i.h @@ -121,7 +121,7 @@ struct InfraredApp { InfraredProgressView* progress; /**< Custom view for showing brute force progress. */ FuriString* file_path; /**< Full path to the currently loaded file. */ - FuriString* button_name; /** Name of the button requested in RPC mode. */ + FuriString* button_name; /**< Name of the button requested in RPC mode. */ /** Arbitrary text storage for various inputs. */ char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; InfraredAppState app_state; /**< Application state. */ diff --git a/applications/main/infrared/infrared_brute_force.c b/applications/main/infrared/infrared_brute_force.c index 373c7270f..b941a4760 100644 --- a/applications/main/infrared/infrared_brute_force.c +++ b/applications/main/infrared/infrared_brute_force.c @@ -57,20 +57,31 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) { Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); + FuriString* signal_name = furi_string_alloc(); + InfraredSignal* signal = infrared_signal_alloc(); + + do { + if(!flipper_format_buffered_file_open_existing(ff, brute_force->db_filename)) break; + + bool signals_valid = false; + while(infrared_signal_read_name(ff, signal_name)) { + signals_valid = infrared_signal_read_body(signal, ff) && + infrared_signal_is_valid(signal); + if(!signals_valid) break; - success = flipper_format_buffered_file_open_existing(ff, brute_force->db_filename); - if(success) { - FuriString* signal_name; - signal_name = furi_string_alloc(); - while(flipper_format_read_string(ff, "name", signal_name)) { InfraredBruteForceRecord* record = InfraredBruteForceRecordDict_get(brute_force->records, signal_name); if(record) { //-V547 ++(record->count); } } - furi_string_free(signal_name); - } + + if(!signals_valid) break; + success = true; + } while(false); + + infrared_signal_free(signal); + furi_string_free(signal_name); flipper_format_free(ff); furi_record_close(RECORD_STORAGE); diff --git a/applications/main/infrared/infrared_signal.c b/applications/main/infrared/infrared_signal.c index 2b0d34791..eec8c19cb 100644 --- a/applications/main/infrared/infrared_signal.c +++ b/applications/main/infrared/infrared_signal.c @@ -8,7 +8,23 @@ #define TAG "InfraredSignal" +// Common keys #define INFRARED_SIGNAL_NAME_KEY "name" +#define INFRARED_SIGNAL_TYPE_KEY "type" + +// Type key values +#define INFRARED_SIGNAL_TYPE_RAW "raw" +#define INFRARED_SIGNAL_TYPE_PARSED "parsed" + +// Raw signal keys +#define INFRARED_SIGNAL_DATA_KEY "data" +#define INFRARED_SIGNAL_FREQUENCY_KEY "frequency" +#define INFRARED_SIGNAL_DUTY_CYCLE_KEY "duty_cycle" + +// Parsed signal keys +#define INFRARED_SIGNAL_PROTOCOL_KEY "protocol" +#define INFRARED_SIGNAL_ADDRESS_KEY "address" +#define INFRARED_SIGNAL_COMMAND_KEY "command" struct InfraredSignal { bool is_raw; @@ -88,18 +104,23 @@ static bool infrared_signal_is_raw_valid(const InfraredRawSignal* raw) { static inline bool infrared_signal_save_message(const InfraredMessage* message, FlipperFormat* ff) { const char* protocol_name = infrared_get_protocol_name(message->protocol); - return flipper_format_write_string_cstr(ff, "type", "parsed") && - flipper_format_write_string_cstr(ff, "protocol", protocol_name) && - flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) && - flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4); + return flipper_format_write_string_cstr( + ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_PARSED) && + flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_PROTOCOL_KEY, protocol_name) && + flipper_format_write_hex( + ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message->address, 4) && + flipper_format_write_hex( + ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message->command, 4); } static inline bool infrared_signal_save_raw(const InfraredRawSignal* raw, FlipperFormat* ff) { furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT); - return flipper_format_write_string_cstr(ff, "type", "raw") && - flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) && - flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) && - flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size); + return flipper_format_write_string_cstr( + ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_RAW) && + flipper_format_write_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &raw->frequency, 1) && + flipper_format_write_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &raw->duty_cycle, 1) && + flipper_format_write_uint32( + ff, INFRARED_SIGNAL_DATA_KEY, raw->timings, raw->timings_size); } static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) { @@ -108,61 +129,72 @@ static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperF bool success = false; do { - if(!flipper_format_read_string(ff, "protocol", buf)) break; + if(!flipper_format_read_string(ff, INFRARED_SIGNAL_PROTOCOL_KEY, buf)) break; InfraredMessage message; message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf)); - success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) && - flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) && - infrared_signal_is_message_valid(&message); - - if(!success) break; + if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message.address, 4)) + break; + if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message.command, 4)) + break; + if(!infrared_signal_is_message_valid(&message)) break; infrared_signal_set_message(signal, &message); - } while(0); + success = true; + } while(false); furi_string_free(buf); return success; } static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) { - uint32_t timings_size, frequency; - float duty_cycle; + bool success = false; - bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) && - flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) && - flipper_format_get_value_count(ff, "data", &timings_size); + do { + uint32_t frequency; + if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &frequency, 1)) break; - if(!success || timings_size > MAX_TIMINGS_AMOUNT) { - return false; - } + float duty_cycle; + if(!flipper_format_read_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &duty_cycle, 1)) break; - uint32_t* timings = malloc(sizeof(uint32_t) * timings_size); - success = flipper_format_read_uint32(ff, "data", timings, timings_size); + uint32_t timings_size; + if(!flipper_format_get_value_count(ff, INFRARED_SIGNAL_DATA_KEY, &timings_size)) break; - if(success) { + if(timings_size > MAX_TIMINGS_AMOUNT) break; + + uint32_t* timings = malloc(sizeof(uint32_t) * timings_size); + if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_DATA_KEY, timings, timings_size)) { + free(timings); + break; + } infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle); - } + free(timings); + + success = true; + } while(false); - free(timings); return success; } -static bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) { +bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) { FuriString* tmp = furi_string_alloc(); bool success = false; do { - if(!flipper_format_read_string(ff, "type", tmp)) break; - if(furi_string_equal(tmp, "raw")) { - success = infrared_signal_read_raw(signal, ff); - } else if(furi_string_equal(tmp, "parsed")) { - success = infrared_signal_read_message(signal, ff); + if(!flipper_format_read_string(ff, INFRARED_SIGNAL_TYPE_KEY, tmp)) break; + + if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_RAW)) { + if(!infrared_signal_read_raw(signal, ff)) break; + } else if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_PARSED)) { + if(!infrared_signal_read_message(signal, ff)) break; } else { - FURI_LOG_E(TAG, "Unknown signal type"); + FURI_LOG_E(TAG, "Unknown signal type: %s", furi_string_get_cstr(tmp)); + break; } + + success = true; } while(false); furi_string_free(tmp); diff --git a/applications/main/infrared/infrared_signal.h b/applications/main/infrared/infrared_signal.h index cfa4cfa94..69b677f23 100644 --- a/applications/main/infrared/infrared_signal.h +++ b/applications/main/infrared/infrared_signal.h @@ -127,7 +127,7 @@ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal); /** - * @brief Read a signal from a FlipperFormat file into an InfraredSignal instance. + * @brief Read a signal and its name from a FlipperFormat file into an InfraredSignal instance. * * The file must be allocated and open prior to this call. The seek position determines * which signal will be read (if there is more than one in the file). Calling this function @@ -151,6 +151,17 @@ bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* */ bool infrared_signal_read_name(FlipperFormat* ff, FuriString* name); +/** + * @brief Read a signal from a FlipperFormat file. + * + * Same behaviour as infrared_signal_read(), but only the body is read. + * + * @param[in,out] ff pointer to the FlipperFormat file instance to read from. + * @param[out] body pointer to the InfraredSignal instance to hold the signal body. Must be properly allocated. + * @returns true if a signal body was successfully read, false otherwise (e.g. syntax error). + */ +bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff); + /** * @brief Read a signal with a particular name from a FlipperFormat file into an InfraredSignal instance. *