140 lines
5.2 KiB
C
140 lines
5.2 KiB
C
#include "rolling_flaws_subghz_receive.h"
|
|
|
|
static SubGhzEnvironment* load_environment() {
|
|
SubGhzEnvironment* environment = subghz_environment_alloc();
|
|
subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME);
|
|
subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME);
|
|
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
|
environment, SUBGHZ_CAME_ATOMO_DIR_NAME);
|
|
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
|
environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
|
|
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
|
environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
|
|
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
|
|
return environment;
|
|
}
|
|
|
|
RollingFlawsSubGhz* rolling_flaws_subghz_alloc() {
|
|
RollingFlawsSubGhz* subghz = malloc(sizeof(RollingFlawsSubGhz));
|
|
subghz->status = SUBGHZ_RECEIVER_UNINITIALIZED;
|
|
subghz->environment = load_environment();
|
|
subghz->stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
|
furi_check(subghz->stream);
|
|
subghz->overrun = false;
|
|
return subghz;
|
|
}
|
|
|
|
void rolling_flaws_subghz_free(RollingFlawsSubGhz* subghz) {
|
|
subghz_environment_free(subghz->environment);
|
|
furi_stream_buffer_free(subghz->stream);
|
|
free(subghz);
|
|
}
|
|
|
|
static void
|
|
rx_callback(SubGhzReceiver* receiver, SubGhzProtocolDecoderBase* decoder_base, void* cxt) {
|
|
RollingFlawsSubGhz* context = (RollingFlawsSubGhz*)cxt;
|
|
FuriString* buffer = furi_string_alloc();
|
|
subghz_protocol_decoder_base_get_string(decoder_base, buffer);
|
|
subghz_receiver_reset(receiver);
|
|
FURI_LOG_I(TAG, "PACKET:\r\n%s", furi_string_get_cstr(buffer));
|
|
if(context->callback) {
|
|
if(!context->callback(buffer, context->callback_context)) {
|
|
context->status = SUBGHZ_RECEIVER_SYNCHRONIZED;
|
|
}
|
|
}
|
|
furi_string_free(buffer);
|
|
}
|
|
|
|
static void rx_capture_callback(bool level, uint32_t duration, void* context) {
|
|
RollingFlawsSubGhz* instance = context;
|
|
|
|
LevelDuration level_duration = level_duration_make(level, duration);
|
|
if(instance->overrun) {
|
|
instance->overrun = false;
|
|
level_duration = level_duration_reset();
|
|
}
|
|
size_t ret =
|
|
furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0);
|
|
if(sizeof(LevelDuration) != ret) {
|
|
instance->overrun = true;
|
|
}
|
|
}
|
|
|
|
static int32_t listen_rx(void* ctx) {
|
|
RollingFlawsSubGhz* context = (RollingFlawsSubGhz*)ctx;
|
|
context->status = SUBGHZ_RECEIVER_LISTENING;
|
|
LevelDuration level_duration;
|
|
FURI_LOG_I(TAG, "listen_rx started...");
|
|
while(context->status == SUBGHZ_RECEIVER_LISTENING) {
|
|
int ret = furi_stream_buffer_receive(
|
|
context->stream, &level_duration, sizeof(LevelDuration), 10);
|
|
|
|
if(ret == sizeof(LevelDuration)) {
|
|
if(level_duration_is_reset(level_duration)) {
|
|
subghz_receiver_reset(context->receiver);
|
|
} else {
|
|
bool level = level_duration_get_level(level_duration);
|
|
uint32_t duration = level_duration_get_duration(level_duration);
|
|
subghz_receiver_decode(context->receiver, level, duration);
|
|
}
|
|
}
|
|
}
|
|
FURI_LOG_I(TAG, "listen_rx exiting...");
|
|
context->status = SUBGHZ_RECEIVER_NOTLISTENING;
|
|
return 0;
|
|
}
|
|
|
|
void start_listening(
|
|
RollingFlawsSubGhz* context,
|
|
uint32_t frequency,
|
|
SubghzPacketCallback callback,
|
|
void* callback_context) {
|
|
context->status = SUBGHZ_RECEIVER_INITIALIZING;
|
|
|
|
context->callback = callback;
|
|
context->callback_context = callback_context;
|
|
subghz_devices_init();
|
|
const SubGhzDevice* device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
|
if(!subghz_devices_is_frequency_valid(device, frequency)) {
|
|
FURI_LOG_E(TAG, "Frequency not in range. %lu\r\n", frequency);
|
|
subghz_devices_deinit();
|
|
return;
|
|
}
|
|
|
|
context->receiver = subghz_receiver_alloc_init(context->environment);
|
|
subghz_receiver_set_filter(context->receiver, SubGhzProtocolFlag_Decodable);
|
|
subghz_receiver_set_rx_callback(context->receiver, rx_callback, context);
|
|
|
|
subghz_devices_begin(device);
|
|
subghz_devices_reset(device);
|
|
subghz_devices_load_preset(device, FuriHalSubGhzPresetOok650Async, NULL);
|
|
frequency = subghz_devices_set_frequency(device, frequency);
|
|
|
|
furi_hal_power_suppress_charge_enter();
|
|
|
|
subghz_devices_start_async_rx(device, rx_capture_callback, context);
|
|
|
|
FURI_LOG_I(TAG, "Listening at frequency: %lu\r\n", frequency);
|
|
|
|
context->thread = furi_thread_alloc_ex("RX", 1024, listen_rx, context);
|
|
furi_thread_start(context->thread);
|
|
}
|
|
|
|
void stop_listening(RollingFlawsSubGhz* context) {
|
|
if(context->status == SUBGHZ_RECEIVER_UNINITIALIZED) {
|
|
return;
|
|
}
|
|
|
|
context->status = SUBGHZ_RECEIVER_UNINITIALING;
|
|
FURI_LOG_D(TAG, "Stopping listening...");
|
|
furi_thread_join(context->thread);
|
|
furi_thread_free(context->thread);
|
|
furi_hal_power_suppress_charge_exit();
|
|
|
|
const SubGhzDevice* device = subghz_devices_get_by_name(SUBGHZ_DEVICE_CC1101_INT_NAME);
|
|
subghz_devices_stop_async_rx(device);
|
|
|
|
subghz_receiver_free(context->receiver);
|
|
subghz_devices_deinit();
|
|
context->status = SUBGHZ_RECEIVER_UNINITIALIZED;
|
|
} |