[FL-1472, FL-1596, FL-1673] IRDA: stability improvements (#655)
- Restrict with 31 bytes length for remote and signal name - Don't stuck for 0 PWM cycle timings - Support timings > 65535 PWM cycles - Fix remote file open error - Add IRDA TX debug redirect - Add remote parse error print, improve parsing, support tabs - Fix stucks with uncorrect RAW signal values, long strings in remote file, etc - Fix HAL signals capturing (save previous read value) - Fix leak in case of failed parsing
This commit is contained in:
@@ -44,8 +44,9 @@ struct IrdaWorkerSignal{
|
||||
size_t timings_cnt;
|
||||
union {
|
||||
IrdaMessage message;
|
||||
uint32_t timings[MAX_TIMINGS_AMOUNT];
|
||||
} data;
|
||||
/* +1 is for pause we add at the beginning */
|
||||
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
|
||||
};
|
||||
};
|
||||
|
||||
struct IrdaWorker {
|
||||
@@ -125,7 +126,7 @@ static void irda_worker_process_timeout(IrdaWorker* instance) {
|
||||
static void irda_worker_process_timings(IrdaWorker* instance, uint32_t duration, bool level) {
|
||||
const IrdaMessage* message_decoded = irda_decode(instance->irda_decoder, level, duration);
|
||||
if (message_decoded) {
|
||||
instance->signal.data.message = *message_decoded;
|
||||
instance->signal.message = *message_decoded;
|
||||
instance->signal.timings_cnt = 0;
|
||||
instance->signal.decoded = true;
|
||||
if (instance->rx.received_signal_callback)
|
||||
@@ -137,7 +138,7 @@ static void irda_worker_process_timings(IrdaWorker* instance, uint32_t duration,
|
||||
}
|
||||
|
||||
if (instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) {
|
||||
instance->signal.data.timings[instance->signal.timings_cnt] = duration;
|
||||
instance->signal.timings[instance->signal.timings_cnt] = duration;
|
||||
++instance->signal.timings_cnt;
|
||||
} else {
|
||||
uint32_t flags_set = osEventFlagsSet(instance->events, IRDA_WORKER_OVERRUN);
|
||||
@@ -211,7 +212,7 @@ IrdaWorker* irda_worker_alloc() {
|
||||
furi_thread_set_stack_size(instance->thread, 2048);
|
||||
furi_thread_set_context(instance->thread, instance);
|
||||
|
||||
size_t buffer_size = MAX(sizeof(IrdaWorkerTiming) * MAX_TIMINGS_AMOUNT, sizeof(LevelDuration) * MAX_TIMINGS_AMOUNT);
|
||||
size_t buffer_size = MAX(sizeof(IrdaWorkerTiming) * (MAX_TIMINGS_AMOUNT + 1), sizeof(LevelDuration) * MAX_TIMINGS_AMOUNT);
|
||||
instance->stream = xStreamBufferCreate(buffer_size, sizeof(IrdaWorkerTiming));
|
||||
instance->irda_decoder = irda_alloc_decoder();
|
||||
instance->irda_encoder = irda_alloc_encoder();
|
||||
@@ -283,13 +284,13 @@ void irda_worker_get_raw_signal(const IrdaWorkerSignal* signal, const uint32_t**
|
||||
furi_assert(timings);
|
||||
furi_assert(timings_cnt);
|
||||
|
||||
*timings = signal->data.timings;
|
||||
*timings = signal->timings;
|
||||
*timings_cnt = signal->timings_cnt;
|
||||
}
|
||||
|
||||
const IrdaMessage* irda_worker_get_decoded_signal(const IrdaWorkerSignal* signal) {
|
||||
furi_assert(signal);
|
||||
return &signal->data.message;
|
||||
return &signal->message;
|
||||
}
|
||||
|
||||
void irda_worker_rx_enable_blink_on_receiving(IrdaWorker* instance, bool enable) {
|
||||
@@ -328,21 +329,24 @@ static FuriHalIrdaTxGetDataState irda_worker_furi_hal_data_isr_callback(void* co
|
||||
furi_assert(level);
|
||||
|
||||
IrdaWorker* instance = context;
|
||||
IrdaWorkerTiming timing = {.state = FuriHalIrdaTxGetDataStateError} ;
|
||||
IrdaWorkerTiming timing;
|
||||
FuriHalIrdaTxGetDataState state;
|
||||
|
||||
if (sizeof(IrdaWorkerTiming) == xStreamBufferReceiveFromISR(instance->stream, &timing, sizeof(IrdaWorkerTiming), 0)) {
|
||||
*level = timing.level;
|
||||
*duration = timing.duration;
|
||||
furi_assert(timing.state != FuriHalIrdaTxGetDataStateError);
|
||||
state = timing.state;
|
||||
} else {
|
||||
furi_assert(0);
|
||||
timing.state = FuriHalIrdaTxGetDataStateError;
|
||||
*level = 0;
|
||||
*duration = 100;
|
||||
state = FuriHalIrdaTxGetDataStateDone;
|
||||
}
|
||||
|
||||
uint32_t flags_set = osEventFlagsSet(instance->events, IRDA_WORKER_TX_FILL_BUFFER);
|
||||
furi_check(flags_set & IRDA_WORKER_TX_FILL_BUFFER);
|
||||
|
||||
return timing.state;
|
||||
return state;
|
||||
}
|
||||
|
||||
static bool irda_get_new_signal(IrdaWorker* instance) {
|
||||
@@ -353,8 +357,8 @@ static bool irda_get_new_signal(IrdaWorker* instance) {
|
||||
uint32_t new_tx_frequency = 0;
|
||||
float new_tx_duty_cycle = 0;
|
||||
if (instance->signal.decoded) {
|
||||
new_tx_frequency = irda_get_protocol_frequency(instance->signal.data.message.protocol);
|
||||
new_tx_duty_cycle = irda_get_protocol_duty_cycle(instance->signal.data.message.protocol);
|
||||
new_tx_frequency = irda_get_protocol_frequency(instance->signal.message.protocol);
|
||||
new_tx_duty_cycle = irda_get_protocol_duty_cycle(instance->signal.message.protocol);
|
||||
} else {
|
||||
furi_assert(instance->signal.timings_cnt > 1);
|
||||
new_tx_frequency = IRDA_COMMON_CARRIER_FREQUENCY;
|
||||
@@ -366,7 +370,7 @@ static bool irda_get_new_signal(IrdaWorker* instance) {
|
||||
instance->tx.frequency = new_tx_frequency;
|
||||
instance->tx.duty_cycle = new_tx_duty_cycle;
|
||||
if (instance->signal.decoded) {
|
||||
irda_reset_encoder(instance->irda_encoder, &instance->signal.data.message);
|
||||
irda_reset_encoder(instance->irda_encoder, &instance->signal.message);
|
||||
}
|
||||
new_signal_obtained = true;
|
||||
} else if (response == IrdaWorkerGetSignalResponseSame) {
|
||||
@@ -390,8 +394,8 @@ static bool irda_worker_tx_fill_buffer(IrdaWorker* instance) {
|
||||
if (instance->signal.decoded) {
|
||||
status = irda_encode(instance->irda_encoder, &timing.duration, &timing.level);
|
||||
} else {
|
||||
timing.duration = instance->signal.data.timings[instance->tx.tx_raw_cnt];
|
||||
/* raw always starts from Mark, but we fulfill it with space delay at start */
|
||||
timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt];
|
||||
/* raw always starts from Mark, but we fill it with space delay at start */
|
||||
timing.level = (instance->tx.tx_raw_cnt % 2);
|
||||
++instance->tx.tx_raw_cnt;
|
||||
if (instance->tx.tx_raw_cnt >= instance->signal.timings_cnt) {
|
||||
@@ -532,16 +536,18 @@ void irda_worker_set_decoded_signal(IrdaWorker* instance, const IrdaMessage* mes
|
||||
furi_assert(message);
|
||||
|
||||
instance->signal.decoded = true;
|
||||
instance->signal.data.message = *message;
|
||||
instance->signal.message = *message;
|
||||
}
|
||||
|
||||
void irda_worker_set_raw_signal(IrdaWorker* instance, const uint32_t* timings, size_t timings_cnt) {
|
||||
furi_assert(instance);
|
||||
furi_assert(timings);
|
||||
furi_assert(timings_cnt > 2);
|
||||
furi_assert(timings_cnt > 0);
|
||||
size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1;
|
||||
furi_check(timings_cnt <= max_copy_num);
|
||||
|
||||
instance->signal.data.timings[0] = IRDA_RAW_TX_TIMING_DELAY_US;
|
||||
memcpy(&instance->signal.data.timings[1], timings, timings_cnt * sizeof(uint32_t));
|
||||
instance->signal.timings[0] = IRDA_RAW_TX_TIMING_DELAY_US;
|
||||
memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t));
|
||||
instance->signal.decoded = false;
|
||||
instance->signal.timings_cnt = timings_cnt + 1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user