[FL-3769] Check universal remote files before loading (#3438)

* Improve code readability
* Check universal remote files before loading

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
Georgii Surkov
2024-02-12 05:30:10 +03:00
committed by GitHub
parent b0df852944
commit 6d09bebf14
4 changed files with 98 additions and 44 deletions

View File

@@ -121,7 +121,7 @@ struct InfraredApp {
InfraredProgressView* progress; /**< Custom view for showing brute force progress. */ InfraredProgressView* progress; /**< Custom view for showing brute force progress. */
FuriString* file_path; /**< Full path to the currently loaded file. */ 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. */ /** Arbitrary text storage for various inputs. */
char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1]; char text_store[INFRARED_TEXT_STORE_NUM][INFRARED_TEXT_STORE_SIZE + 1];
InfraredAppState app_state; /**< Application state. */ InfraredAppState app_state; /**< Application state. */

View File

@@ -57,20 +57,31 @@ bool infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
Storage* storage = furi_record_open(RECORD_STORAGE); Storage* storage = furi_record_open(RECORD_STORAGE);
FlipperFormat* ff = flipper_format_buffered_file_alloc(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 = InfraredBruteForceRecord* record =
InfraredBruteForceRecordDict_get(brute_force->records, signal_name); InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
if(record) { //-V547 if(record) { //-V547
++(record->count); ++(record->count);
} }
} }
if(!signals_valid) break;
success = true;
} while(false);
infrared_signal_free(signal);
furi_string_free(signal_name); furi_string_free(signal_name);
}
flipper_format_free(ff); flipper_format_free(ff);
furi_record_close(RECORD_STORAGE); furi_record_close(RECORD_STORAGE);

View File

@@ -8,7 +8,23 @@
#define TAG "InfraredSignal" #define TAG "InfraredSignal"
// Common keys
#define INFRARED_SIGNAL_NAME_KEY "name" #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 { struct InfraredSignal {
bool is_raw; bool is_raw;
@@ -88,18 +104,23 @@ static bool infrared_signal_is_raw_valid(const InfraredRawSignal* raw) {
static inline bool static inline bool
infrared_signal_save_message(const InfraredMessage* message, FlipperFormat* ff) { infrared_signal_save_message(const InfraredMessage* message, FlipperFormat* ff) {
const char* protocol_name = infrared_get_protocol_name(message->protocol); const char* protocol_name = infrared_get_protocol_name(message->protocol);
return flipper_format_write_string_cstr(ff, "type", "parsed") && return flipper_format_write_string_cstr(
flipper_format_write_string_cstr(ff, "protocol", protocol_name) && ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_PARSED) &&
flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) && flipper_format_write_string_cstr(ff, INFRARED_SIGNAL_PROTOCOL_KEY, protocol_name) &&
flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4); 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) { static inline bool infrared_signal_save_raw(const InfraredRawSignal* raw, FlipperFormat* ff) {
furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT); furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT);
return flipper_format_write_string_cstr(ff, "type", "raw") && return flipper_format_write_string_cstr(
flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) && ff, INFRARED_SIGNAL_TYPE_KEY, INFRARED_SIGNAL_TYPE_RAW) &&
flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) && flipper_format_write_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &raw->frequency, 1) &&
flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size); 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) { 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; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "protocol", buf)) break; if(!flipper_format_read_string(ff, INFRARED_SIGNAL_PROTOCOL_KEY, buf)) break;
InfraredMessage message; InfraredMessage message;
message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf)); message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) && if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_ADDRESS_KEY, (uint8_t*)&message.address, 4))
flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) && break;
infrared_signal_is_message_valid(&message); if(!flipper_format_read_hex(ff, INFRARED_SIGNAL_COMMAND_KEY, (uint8_t*)&message.command, 4))
break;
if(!success) break; if(!infrared_signal_is_message_valid(&message)) break;
infrared_signal_set_message(signal, &message); infrared_signal_set_message(signal, &message);
} while(0); success = true;
} while(false);
furi_string_free(buf); furi_string_free(buf);
return success; return success;
} }
static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) { static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
uint32_t timings_size, frequency; bool success = false;
do {
uint32_t frequency;
if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_FREQUENCY_KEY, &frequency, 1)) break;
float duty_cycle; float duty_cycle;
if(!flipper_format_read_float(ff, INFRARED_SIGNAL_DUTY_CYCLE_KEY, &duty_cycle, 1)) break;
bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) && uint32_t timings_size;
flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) && if(!flipper_format_get_value_count(ff, INFRARED_SIGNAL_DATA_KEY, &timings_size)) break;
flipper_format_get_value_count(ff, "data", &timings_size);
if(!success || timings_size > MAX_TIMINGS_AMOUNT) { if(timings_size > MAX_TIMINGS_AMOUNT) break;
return false;
}
uint32_t* timings = malloc(sizeof(uint32_t) * timings_size); uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
success = flipper_format_read_uint32(ff, "data", timings, timings_size); if(!flipper_format_read_uint32(ff, INFRARED_SIGNAL_DATA_KEY, timings, timings_size)) {
if(success) {
infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
}
free(timings); free(timings);
break;
}
infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
free(timings);
success = true;
} while(false);
return success; 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(); FuriString* tmp = furi_string_alloc();
bool success = false; bool success = false;
do { do {
if(!flipper_format_read_string(ff, "type", tmp)) break; if(!flipper_format_read_string(ff, INFRARED_SIGNAL_TYPE_KEY, tmp)) break;
if(furi_string_equal(tmp, "raw")) {
success = infrared_signal_read_raw(signal, ff); if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_RAW)) {
} else if(furi_string_equal(tmp, "parsed")) { if(!infrared_signal_read_raw(signal, ff)) break;
success = infrared_signal_read_message(signal, ff); } else if(furi_string_equal(tmp, INFRARED_SIGNAL_TYPE_PARSED)) {
if(!infrared_signal_read_message(signal, ff)) break;
} else { } 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); } while(false);
furi_string_free(tmp); furi_string_free(tmp);

View File

@@ -127,7 +127,7 @@ void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage*
const InfraredMessage* infrared_signal_get_message(const InfraredSignal* signal); 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 * 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 * 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); 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. * @brief Read a signal with a particular name from a FlipperFormat file into an InfraredSignal instance.
* *