Skip to content

Commit 9e19498

Browse files
feat: universal ir signal selection
1 parent 7291e6b commit 9e19498

File tree

12 files changed

+370
-105
lines changed

12 files changed

+370
-105
lines changed

applications/main/infrared/infrared_brute_force.c

Lines changed: 71 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,61 @@
22

33
#include <stdlib.h>
44
#include <m-dict.h>
5+
#include <m-array.h>
56
#include <flipper_format/flipper_format.h>
67

78
#include "infrared_signal.h"
89

10+
ARRAY_DEF(SignalPositionArray, size_t, M_DEFAULT_OPLIST);
11+
912
typedef struct {
10-
uint32_t index;
11-
uint32_t count;
13+
size_t index;
14+
SignalPositionArray_t signals;
1215
} InfraredBruteForceRecord;
1316

17+
static inline void ir_bf_record_init(InfraredBruteForceRecord* record) {
18+
record->index = 0;
19+
SignalPositionArray_init(record->signals);
20+
}
21+
#define IR_BF_RECORD_INIT(r) (ir_bf_record_init(&(r)))
22+
23+
static inline void
24+
ir_bf_record_init_set(InfraredBruteForceRecord* dest, const InfraredBruteForceRecord* src) {
25+
dest->index = src->index;
26+
SignalPositionArray_init_set(dest->signals, src->signals);
27+
}
28+
#define IR_BF_RECORD_INIT_SET(d, s) (ir_bf_record_init_set(&(d), &(s)))
29+
30+
static inline void
31+
ir_bf_record_set(InfraredBruteForceRecord* dest, const InfraredBruteForceRecord* src) {
32+
dest->index = src->index;
33+
SignalPositionArray_set(dest->signals, src->signals);
34+
}
35+
#define IR_BF_RECORD_SET(d, s) (ir_bf_record_set(&(d), &(s)))
36+
37+
static inline void ir_bf_record_clear(InfraredBruteForceRecord* record) {
38+
SignalPositionArray_clear(record->signals);
39+
}
40+
#define IR_BF_RECORD_CLEAR(r) (ir_bf_record_clear(&(r)))
41+
42+
#define IR_BF_RECORD_OPLIST \
43+
(INIT(IR_BF_RECORD_INIT), \
44+
INIT_SET(IR_BF_RECORD_INIT_SET), \
45+
SET(IR_BF_RECORD_SET), \
46+
CLEAR(IR_BF_RECORD_CLEAR))
47+
1448
DICT_DEF2(
1549
InfraredBruteForceRecordDict,
1650
FuriString*,
1751
FURI_STRING_OPLIST,
1852
InfraredBruteForceRecord,
19-
M_POD_OPLIST);
53+
IR_BF_RECORD_OPLIST);
2054

2155
struct InfraredBruteForce {
2256
FlipperFormat* ff;
2357
const char* db_filename;
2458
FuriString* current_record_name;
59+
InfraredBruteForceRecord current_record;
2560
InfraredSignal* current_signal;
2661
InfraredBruteForceRecordDict_t records;
2762
bool is_started;
@@ -39,18 +74,21 @@ InfraredBruteForce* infrared_brute_force_alloc(void) {
3974
}
4075

4176
void infrared_brute_force_free(InfraredBruteForce* brute_force) {
77+
furi_check(brute_force);
4278
furi_assert(!brute_force->is_started);
4379
InfraredBruteForceRecordDict_clear(brute_force->records);
4480
furi_string_free(brute_force->current_record_name);
4581
free(brute_force);
4682
}
4783

4884
void infrared_brute_force_set_db_filename(InfraredBruteForce* brute_force, const char* db_filename) {
85+
furi_check(brute_force);
4986
furi_assert(!brute_force->is_started);
5087
brute_force->db_filename = db_filename;
5188
}
5289

5390
InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* brute_force) {
91+
furi_check(brute_force);
5492
furi_assert(!brute_force->is_started);
5593
furi_assert(brute_force->db_filename);
5694
InfraredErrorCode error = InfraredErrorCodeNone;
@@ -66,19 +104,19 @@ InfraredErrorCode infrared_brute_force_calculate_messages(InfraredBruteForce* br
66104
break;
67105
}
68106

69-
bool signals_valid = false;
107+
size_t signal_start = flipper_format_tell(ff);
108+
bool signal_valid = false;
70109
while(infrared_signal_read_name(ff, signal_name) == InfraredErrorCodeNone) {
71110
error = infrared_signal_read_body(signal, ff);
72-
signals_valid = (!INFRARED_ERROR_PRESENT(error)) && infrared_signal_is_valid(signal);
73-
if(!signals_valid) break;
111+
signal_valid = (!INFRARED_ERROR_PRESENT(error)) && infrared_signal_is_valid(signal);
112+
if(!signal_valid) break;
74113

75114
InfraredBruteForceRecord* record =
76115
InfraredBruteForceRecordDict_get(brute_force->records, signal_name);
77-
if(record) { //-V547
78-
++(record->count);
79-
}
116+
furi_assert(record);
117+
SignalPositionArray_push_back(record->signals, signal_start);
80118
}
81-
if(!signals_valid) break;
119+
if(!signal_valid) break;
82120
} while(false);
83121

84122
infrared_signal_free(signal);
@@ -93,6 +131,7 @@ bool infrared_brute_force_start(
93131
InfraredBruteForce* brute_force,
94132
uint32_t index,
95133
uint32_t* record_count) {
134+
furi_check(brute_force);
96135
furi_assert(!brute_force->is_started);
97136
bool success = false;
98137
*record_count = 0;
@@ -103,9 +142,10 @@ bool infrared_brute_force_start(
103142
InfraredBruteForceRecordDict_next(it)) {
104143
const InfraredBruteForceRecordDict_itref_t* record = InfraredBruteForceRecordDict_cref(it);
105144
if(record->value.index == index) {
106-
*record_count = record->value.count;
145+
*record_count = SignalPositionArray_size(record->value.signals);
107146
if(*record_count) {
108147
furi_string_set(brute_force->current_record_name, record->key);
148+
brute_force->current_record = record->value;
109149
}
110150
break;
111151
}
@@ -124,10 +164,12 @@ bool infrared_brute_force_start(
124164
}
125165

126166
bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force) {
167+
furi_check(brute_force);
127168
return brute_force->is_started;
128169
}
129170

130171
void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
172+
furi_check(brute_force);
131173
furi_assert(brute_force->is_started);
132174
furi_string_reset(brute_force->current_record_name);
133175
infrared_signal_free(brute_force->current_signal);
@@ -138,25 +180,32 @@ void infrared_brute_force_stop(InfraredBruteForce* brute_force) {
138180
furi_record_close(RECORD_STORAGE);
139181
}
140182

141-
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force) {
183+
bool infrared_brute_force_send(InfraredBruteForce* brute_force, uint32_t signal_index) {
184+
furi_check(brute_force);
142185
furi_assert(brute_force->is_started);
143186

144-
const bool success = infrared_signal_search_by_name_and_read(
145-
brute_force->current_signal,
146-
brute_force->ff,
147-
furi_string_get_cstr(brute_force->current_record_name)) ==
148-
InfraredErrorCodeNone;
149-
if(success) {
150-
infrared_signal_transmit(brute_force->current_signal);
151-
}
152-
return success;
187+
if(signal_index >= SignalPositionArray_size(brute_force->current_record.signals)) return false;
188+
189+
size_t signal_start =
190+
*SignalPositionArray_cget(brute_force->current_record.signals, signal_index);
191+
if(!flipper_format_seek(brute_force->ff, signal_start, FlipperFormatOffsetFromStart))
192+
return false;
193+
194+
if(INFRARED_ERROR_PRESENT(
195+
infrared_signal_read_body(brute_force->current_signal, brute_force->ff)))
196+
return false;
197+
198+
infrared_signal_transmit(brute_force->current_signal);
199+
return true;
153200
}
154201

155202
void infrared_brute_force_add_record(
156203
InfraredBruteForce* brute_force,
157204
uint32_t index,
158205
const char* name) {
159-
InfraredBruteForceRecord value = {.index = index, .count = 0};
206+
InfraredBruteForceRecord value;
207+
ir_bf_record_init(&value);
208+
value.index = index;
160209
FuriString* key;
161210
key = furi_string_alloc_set(name);
162211
InfraredBruteForceRecordDict_set_at(brute_force->records, key, value);

applications/main/infrared/infrared_brute_force.h

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,18 +78,16 @@ bool infrared_brute_force_is_started(const InfraredBruteForce* brute_force);
7878
void infrared_brute_force_stop(InfraredBruteForce* brute_force);
7979

8080
/**
81-
* @brief Send the next signal from the chosen category.
82-
*
83-
* This function is called repeatedly until no more signals are left
84-
* in the chosen signal category.
85-
*
86-
* @warning Transmission must be started first by calling infrared_brute_force_start()
87-
* before calling this function.
88-
*
89-
* @param[in,out] brute_force pointer to the instance to be used.
90-
* @returns true if the next signal existed and could be transmitted, false otherwise.
81+
* @brief Send an arbitrary signal from the chosen category.
82+
*
83+
* @param[in] brute_force pointer to the instance
84+
* @param signal_index the index of the signal within the category, must be
85+
* between 0 and `record_count` as told by
86+
* `infrared_brute_force_start`
87+
*
88+
* @returns true on success, false otherwise
9189
*/
92-
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force);
90+
bool infrared_brute_force_send(InfraredBruteForce* brute_force, uint32_t signal_index);
9391

9492
/**
9593
* @brief Add a signal category to an InfraredBruteForce instance's dictionary.

applications/main/infrared/infrared_cli.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,25 +475,24 @@ static void
475475
break;
476476
}
477477

478-
uint32_t record_count;
478+
uint32_t signal_count, current_signal = 0;
479479
bool running = infrared_brute_force_start(
480-
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, &record_count);
480+
brute_force, INFRARED_BRUTE_FORCE_DUMMY_INDEX, &signal_count);
481481

482-
if(record_count <= 0) {
482+
if(signal_count <= 0) {
483483
printf("Invalid signal name.\r\n");
484484
break;
485485
}
486486

487-
printf("Sending %lu signal(s)...\r\n", record_count);
487+
printf("Sending %lu signal(s)...\r\n", signal_count);
488488
printf("Press Ctrl-C to stop.\r\n");
489489

490-
int records_sent = 0;
491490
while(running) {
492-
running = infrared_brute_force_send_next(brute_force);
491+
running = infrared_brute_force_send(brute_force, current_signal);
493492

494493
if(cli_cmd_interrupt_received(cli)) break;
495494

496-
printf("\r%d%% complete.", (int)((float)records_sent++ / (float)record_count * 100));
495+
printf("\r%d%% complete.", (int)((float)current_signal++ / (float)signal_count * 100));
497496
fflush(stdout);
498497
}
499498

applications/main/infrared/infrared_custom_event.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#include <stdint.h>
44
#include <stddef.h>
55

6-
enum InfraredCustomEventType {
6+
typedef enum {
77
// Reserve first 100 events for button types and indexes, starting from 0
88
InfraredCustomEventTypeReserved = 100,
99
InfraredCustomEventTypeMenuSelected,
@@ -13,7 +13,7 @@ enum InfraredCustomEventType {
1313
InfraredCustomEventTypeTextEditDone,
1414
InfraredCustomEventTypePopupClosed,
1515
InfraredCustomEventTypeButtonSelected,
16-
InfraredCustomEventTypeBackPressed,
16+
InfraredCustomEventTypePopupInput,
1717
InfraredCustomEventTypeTaskFinished,
1818

1919
InfraredCustomEventTypeRpcLoadFile,
@@ -27,7 +27,7 @@ enum InfraredCustomEventType {
2727

2828
InfraredCustomEventTypeGpioTxPinChanged,
2929
InfraredCustomEventTypeGpioOtgChanged,
30-
};
30+
} InfraredCustomEventType;
3131

3232
#pragma pack(push, 1)
3333
typedef union {

0 commit comments

Comments
 (0)