|
@@ -1,4 +1,5 @@
|
|
|
#include "fake_worker.h"
|
|
#include "fake_worker.h"
|
|
|
|
|
+#include "helpers/hardware_worker.h"
|
|
|
#include "protocol_i.h"
|
|
#include "protocol_i.h"
|
|
|
|
|
|
|
|
#include <timer.h>
|
|
#include <timer.h>
|
|
@@ -8,37 +9,16 @@
|
|
|
#include <toolbox/stream/buffered_file_stream.h>
|
|
#include <toolbox/stream/buffered_file_stream.h>
|
|
|
|
|
|
|
|
#define TAG "Fuzzer worker"
|
|
#define TAG "Fuzzer worker"
|
|
|
-
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
-
|
|
|
|
|
-#include <lib/lfrfid/lfrfid_dict_file.h>
|
|
|
|
|
-#include <lib/lfrfid/lfrfid_worker.h>
|
|
|
|
|
-#include <lfrfid/protocols/lfrfid_protocols.h>
|
|
|
|
|
-
|
|
|
|
|
-#else
|
|
|
|
|
-
|
|
|
|
|
-#include <lib/ibutton/ibutton_worker.h>
|
|
|
|
|
-#include <lib/ibutton/ibutton_key.h>
|
|
|
|
|
-
|
|
|
|
|
-#endif
|
|
|
|
|
-
|
|
|
|
|
-#include <toolbox/stream/stream.h>
|
|
|
|
|
|
|
+#define TOTAL_PROTOCOL_COUNT COUNT_OF(&fuzzer_proto_items)
|
|
|
|
|
|
|
|
typedef uint8_t FuzzerWorkerPayload[MAX_PAYLOAD_SIZE];
|
|
typedef uint8_t FuzzerWorkerPayload[MAX_PAYLOAD_SIZE];
|
|
|
|
|
|
|
|
struct FuzzerWorker {
|
|
struct FuzzerWorker {
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- LFRFIDWorker* proto_worker;
|
|
|
|
|
- ProtocolId protocol_id;
|
|
|
|
|
- ProtocolDict* protocols_items;
|
|
|
|
|
-#else
|
|
|
|
|
- iButtonWorker* proto_worker;
|
|
|
|
|
- iButtonProtocolId protocol_id; // TODO
|
|
|
|
|
- iButtonProtocols* protocols_items;
|
|
|
|
|
- iButtonKey* key;
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+ HardwareWorker* hw_worker;
|
|
|
|
|
|
|
|
const FuzzerProtocol* protocol;
|
|
const FuzzerProtocol* protocol;
|
|
|
|
|
+ HwProtocolID* suported_proto;
|
|
|
|
|
+
|
|
|
FuzzerWorkerPayload payload;
|
|
FuzzerWorkerPayload payload;
|
|
|
|
|
|
|
|
FuzzerWorkerAttackType attack_type;
|
|
FuzzerWorkerAttackType attack_type;
|
|
@@ -59,95 +39,12 @@ struct FuzzerWorker {
|
|
|
void* end_context;
|
|
void* end_context;
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-static void hardware_worker_alloc_init(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- instance->protocols_items = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
|
|
|
|
-
|
|
|
|
|
- instance->proto_worker = lfrfid_worker_alloc(instance->protocols_items);
|
|
|
|
|
-#else
|
|
|
|
|
- instance->protocols_items = ibutton_protocols_alloc();
|
|
|
|
|
- instance->key =
|
|
|
|
|
- ibutton_key_alloc(ibutton_protocols_get_max_data_size(instance->protocols_items));
|
|
|
|
|
-
|
|
|
|
|
- instance->proto_worker = ibutton_worker_alloc(instance->protocols_items);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void hardware_worker_free(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- lfrfid_worker_free(instance->proto_worker);
|
|
|
|
|
|
|
+static bool fuzzer_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
|
|
|
|
|
+ furi_assert(protocol_index < TOTAL_PROTOCOL_COUNT);
|
|
|
|
|
|
|
|
- protocol_dict_free(instance->protocols_items);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_worker_free(instance->proto_worker);
|
|
|
|
|
-
|
|
|
|
|
- ibutton_key_free(instance->key);
|
|
|
|
|
- ibutton_protocols_free(instance->protocols_items);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void hardware_worker_start_thread(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- lfrfid_worker_start_thread(instance->proto_worker);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_worker_start_thread(instance->proto_worker);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void hardware_worker_stop_thread(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- lfrfid_worker_stop(instance->proto_worker);
|
|
|
|
|
- lfrfid_worker_stop_thread(instance->proto_worker);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_worker_stop(instance->proto_worker);
|
|
|
|
|
- ibutton_worker_stop_thread(instance->proto_worker);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void hardware_worker_emulate_start(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- lfrfid_worker_emulate_start(instance->proto_worker, instance->protocol_id);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_worker_emulate_start(instance->proto_worker, instance->key);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void hardware_worker_stop(FuzzerWorker* instance) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- lfrfid_worker_stop(instance->proto_worker);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_worker_stop(instance->proto_worker);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void
|
|
|
|
|
- hardware_worker_set_protocol_data(FuzzerWorker* instance, FuzzerWorkerPayload payload) {
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- protocol_dict_set_data(
|
|
|
|
|
- instance->protocols_items, instance->protocol_id, payload, MAX_PAYLOAD_SIZE);
|
|
|
|
|
-#else
|
|
|
|
|
- ibutton_key_set_protocol_id(instance->key, instance->protocol_id);
|
|
|
|
|
- iButtonEditableData data;
|
|
|
|
|
- ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data);
|
|
|
|
|
-
|
|
|
|
|
- // TODO check data.size logic
|
|
|
|
|
- data.size = MAX_PAYLOAD_SIZE;
|
|
|
|
|
- memcpy(data.ptr, payload, MAX_PAYLOAD_SIZE); // data.size);
|
|
|
|
|
-#endif
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-static void
|
|
|
|
|
- hardware_worker_set_protocol(FuzzerWorker* instance, FuzzerProtocolsID protocol_index) {
|
|
|
|
|
instance->protocol = &fuzzer_proto_items[protocol_index];
|
|
instance->protocol = &fuzzer_proto_items[protocol_index];
|
|
|
-
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- instance->protocol_id =
|
|
|
|
|
- protocol_dict_get_protocol_by_name(instance->protocols_items, instance->protocol->name);
|
|
|
|
|
-#else
|
|
|
|
|
- // TODO iButtonProtocolIdInvalid check
|
|
|
|
|
- instance->protocol_id =
|
|
|
|
|
- ibutton_protocols_get_id_by_name(instance->protocols_items, instance->protocol->name);
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
+ return hardware_worker_set_protocol_id_by_name(
|
|
|
|
|
+ instance->hw_worker, fuzzer_proto_items[protocol_index].name);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TODO make it protocol independent
|
|
// TODO make it protocol independent
|
|
@@ -158,47 +55,13 @@ bool fuzzer_worker_load_key_from_file(
|
|
|
furi_assert(instance);
|
|
furi_assert(instance);
|
|
|
|
|
|
|
|
bool res = false;
|
|
bool res = false;
|
|
|
- hardware_worker_set_protocol(instance, protocol_index);
|
|
|
|
|
-
|
|
|
|
|
-#if defined(RFID_125_PROTOCOL)
|
|
|
|
|
- ProtocolId loaded_proto_id = lfrfid_dict_file_load(instance->protocols_items, filename);
|
|
|
|
|
- if(loaded_proto_id == PROTOCOL_NO) {
|
|
|
|
|
- // Err Cant load file
|
|
|
|
|
- FURI_LOG_W(TAG, "Cant load file");
|
|
|
|
|
- } else if(instance->protocol_id != loaded_proto_id) { // Err wrong protocol
|
|
|
|
|
- FURI_LOG_W(TAG, "Wrong protocol");
|
|
|
|
|
- FURI_LOG_W(
|
|
|
|
|
- TAG,
|
|
|
|
|
- "Selected: %s Loaded: %s",
|
|
|
|
|
- instance->protocol->name,
|
|
|
|
|
- protocol_dict_get_name(instance->protocols_items, loaded_proto_id));
|
|
|
|
|
|
|
+ fuzzer_worker_set_protocol(instance, protocol_index); // TODO add Check
|
|
|
|
|
+ if(!hardware_worker_load_key_from_file(instance->hw_worker, protocol_index, filename)) {
|
|
|
} else {
|
|
} else {
|
|
|
- protocol_dict_get_data(
|
|
|
|
|
- instance->protocols_items, instance->protocol_id, instance->payload, MAX_PAYLOAD_SIZE);
|
|
|
|
|
|
|
+ hardware_worker_get_protocol_data(
|
|
|
|
|
+ instance->hw_worker, &instance->payload[0], MAX_PAYLOAD_SIZE);
|
|
|
res = true;
|
|
res = true;
|
|
|
}
|
|
}
|
|
|
-#else
|
|
|
|
|
- if(!ibutton_protocols_load(instance->protocols_items, instance->key, filename)) {
|
|
|
|
|
- // Err Cant load file
|
|
|
|
|
- FURI_LOG_W(TAG, "Cant load file");
|
|
|
|
|
- } else {
|
|
|
|
|
- if(instance->protocol_id != ibutton_key_get_protocol_id(instance->key)) {
|
|
|
|
|
- // Err wrong protocol
|
|
|
|
|
- FURI_LOG_W(TAG, "Wrong protocol");
|
|
|
|
|
- FURI_LOG_W(
|
|
|
|
|
- TAG,
|
|
|
|
|
- "Selected: %s Loaded: %s",
|
|
|
|
|
- instance->protocol->name,
|
|
|
|
|
- ibutton_protocols_get_name(
|
|
|
|
|
- instance->protocols_items, ibutton_key_get_protocol_id(instance->key)));
|
|
|
|
|
- } else {
|
|
|
|
|
- iButtonEditableData data;
|
|
|
|
|
- ibutton_protocols_get_editable_data(instance->protocols_items, instance->key, &data);
|
|
|
|
|
- memcpy(instance->payload, data.ptr, data.size);
|
|
|
|
|
- res = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
|
|
return res;
|
|
return res;
|
|
|
}
|
|
}
|
|
@@ -280,7 +143,8 @@ static bool fuzzer_worker_load_key(FuzzerWorker* instance, bool next) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(res) {
|
|
if(res) {
|
|
|
- hardware_worker_set_protocol_data(instance, instance->payload);
|
|
|
|
|
|
|
+ hardware_worker_set_protocol_data(
|
|
|
|
|
+ instance->hw_worker, &instance->payload[0], protocol->data_size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
return res;
|
|
@@ -318,7 +182,8 @@ static bool fuzzer_worker_load_previous_key(FuzzerWorker* instance) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(res) {
|
|
if(res) {
|
|
|
- hardware_worker_set_protocol_data(instance, instance->payload);
|
|
|
|
|
|
|
+ hardware_worker_set_protocol_data(
|
|
|
|
|
+ instance->hw_worker, &instance->payload[0], protocol->data_size);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
return res;
|
|
@@ -331,7 +196,7 @@ static void fuzzer_worker_on_tick_callback(void* context) {
|
|
|
|
|
|
|
|
if(instance->in_emu_phase) {
|
|
if(instance->in_emu_phase) {
|
|
|
if(instance->treead_running) {
|
|
if(instance->treead_running) {
|
|
|
- hardware_worker_stop(instance);
|
|
|
|
|
|
|
+ hardware_worker_stop(instance->hw_worker);
|
|
|
}
|
|
}
|
|
|
instance->in_emu_phase = false;
|
|
instance->in_emu_phase = false;
|
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_idle_time_ms));
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_idle_time_ms));
|
|
@@ -343,7 +208,7 @@ static void fuzzer_worker_on_tick_callback(void* context) {
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
if(instance->treead_running) {
|
|
if(instance->treead_running) {
|
|
|
- hardware_worker_emulate_start(instance);
|
|
|
|
|
|
|
+ hardware_worker_emulate_start(instance->hw_worker);
|
|
|
}
|
|
}
|
|
|
instance->in_emu_phase = true;
|
|
instance->in_emu_phase = true;
|
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
|
@@ -381,7 +246,11 @@ bool fuzzer_worker_init_attack_dict(FuzzerWorker* instance, FuzzerProtocolsID pr
|
|
|
furi_assert(instance);
|
|
furi_assert(instance);
|
|
|
|
|
|
|
|
bool res = false;
|
|
bool res = false;
|
|
|
- hardware_worker_set_protocol(instance, protocol_index);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
|
|
|
|
|
+ instance->attack_type = FuzzerWorkerAttackTypeMax;
|
|
|
|
|
+ return res;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
instance->attack_type = FuzzerWorkerAttackTypeDefaultDict;
|
|
instance->attack_type = FuzzerWorkerAttackTypeDefaultDict;
|
|
|
instance->index = 0;
|
|
instance->index = 0;
|
|
@@ -403,7 +272,11 @@ bool fuzzer_worker_init_attack_file_dict(
|
|
|
furi_assert(file_path);
|
|
furi_assert(file_path);
|
|
|
|
|
|
|
|
bool res = false;
|
|
bool res = false;
|
|
|
- hardware_worker_set_protocol(instance, protocol_index);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
|
|
|
|
|
+ instance->attack_type = FuzzerWorkerAttackTypeMax;
|
|
|
|
|
+ return res;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
|
|
instance->uids_stream = buffered_file_stream_alloc(storage);
|
|
instance->uids_stream = buffered_file_stream_alloc(storage);
|
|
@@ -436,7 +309,10 @@ bool fuzzer_worker_init_attack_bf_byte(
|
|
|
furi_assert(instance);
|
|
furi_assert(instance);
|
|
|
|
|
|
|
|
bool res = false;
|
|
bool res = false;
|
|
|
- hardware_worker_set_protocol(instance, protocol_index);
|
|
|
|
|
|
|
+ if(!fuzzer_worker_set_protocol(instance, protocol_index)) {
|
|
|
|
|
+ instance->attack_type = FuzzerWorkerAttackTypeMax;
|
|
|
|
|
+ return res;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
instance->attack_type = FuzzerWorkerAttackTypeLoadFile;
|
|
instance->attack_type = FuzzerWorkerAttackTypeLoadFile;
|
|
|
instance->index = chusen;
|
|
instance->index = chusen;
|
|
@@ -451,7 +327,18 @@ bool fuzzer_worker_init_attack_bf_byte(
|
|
|
FuzzerWorker* fuzzer_worker_alloc() {
|
|
FuzzerWorker* fuzzer_worker_alloc() {
|
|
|
FuzzerWorker* instance = malloc(sizeof(FuzzerWorker));
|
|
FuzzerWorker* instance = malloc(sizeof(FuzzerWorker));
|
|
|
|
|
|
|
|
- hardware_worker_alloc_init(instance);
|
|
|
|
|
|
|
+ instance->hw_worker = hardware_worker_alloc();
|
|
|
|
|
+ instance->suported_proto = malloc(sizeof(HwProtocolID) * TOTAL_PROTOCOL_COUNT);
|
|
|
|
|
+
|
|
|
|
|
+ for(uint8_t i = 0; i < TOTAL_PROTOCOL_COUNT; i++) {
|
|
|
|
|
+ if(!hardware_worker_set_protocol_id_by_name(
|
|
|
|
|
+ instance->hw_worker, fuzzer_proto_items[i].name)) {
|
|
|
|
|
+ // Check protocol support
|
|
|
|
|
+ furi_crash("Not supported protocol name");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ instance->suported_proto[i] = hardware_worker_get_protocol_id(instance->hw_worker);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
|
instance->attack_type = FuzzerWorkerAttackTypeMax;
|
|
|
instance->index = 0;
|
|
instance->index = 0;
|
|
@@ -476,7 +363,8 @@ void fuzzer_worker_free(FuzzerWorker* instance) {
|
|
|
|
|
|
|
|
furi_timer_free(instance->timer);
|
|
furi_timer_free(instance->timer);
|
|
|
|
|
|
|
|
- hardware_worker_free(instance);
|
|
|
|
|
|
|
+ free(instance->suported_proto);
|
|
|
|
|
+ hardware_worker_free(instance->hw_worker);
|
|
|
|
|
|
|
|
free(instance);
|
|
free(instance);
|
|
|
}
|
|
}
|
|
@@ -503,7 +391,7 @@ bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_
|
|
|
instance->timer_idle_time_ms);
|
|
instance->timer_idle_time_ms);
|
|
|
|
|
|
|
|
if(!instance->treead_running) {
|
|
if(!instance->treead_running) {
|
|
|
- hardware_worker_start_thread(instance);
|
|
|
|
|
|
|
+ hardware_worker_start_thread(instance->hw_worker);
|
|
|
|
|
|
|
|
FURI_LOG_D(TAG, "Worker Starting");
|
|
FURI_LOG_D(TAG, "Worker Starting");
|
|
|
instance->treead_running = true;
|
|
instance->treead_running = true;
|
|
@@ -511,7 +399,7 @@ bool fuzzer_worker_start(FuzzerWorker* instance, uint8_t idle_time, uint8_t emu_
|
|
|
FURI_LOG_D(TAG, "Worker UnPaused");
|
|
FURI_LOG_D(TAG, "Worker UnPaused");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- hardware_worker_emulate_start(instance);
|
|
|
|
|
|
|
+ hardware_worker_emulate_start(instance->hw_worker);
|
|
|
|
|
|
|
|
instance->in_emu_phase = true;
|
|
instance->in_emu_phase = true;
|
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
|
furi_timer_start(instance->timer, furi_ms_to_ticks(instance->timer_emu_time_ms));
|
|
@@ -524,7 +412,7 @@ void fuzzer_worker_start_emulate(FuzzerWorker* instance) {
|
|
|
furi_assert(instance);
|
|
furi_assert(instance);
|
|
|
|
|
|
|
|
if(!instance->treead_running) {
|
|
if(!instance->treead_running) {
|
|
|
- hardware_worker_start_thread(instance);
|
|
|
|
|
|
|
+ hardware_worker_start_thread(instance->hw_worker);
|
|
|
|
|
|
|
|
FURI_LOG_D(TAG, "Worker Starting");
|
|
FURI_LOG_D(TAG, "Worker Starting");
|
|
|
instance->treead_running = true;
|
|
instance->treead_running = true;
|
|
@@ -532,7 +420,7 @@ void fuzzer_worker_start_emulate(FuzzerWorker* instance) {
|
|
|
FURI_LOG_D(TAG, "Worker UnPaused");
|
|
FURI_LOG_D(TAG, "Worker UnPaused");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- hardware_worker_emulate_start(instance);
|
|
|
|
|
|
|
+ hardware_worker_emulate_start(instance->hw_worker);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void fuzzer_worker_pause(FuzzerWorker* instance) {
|
|
void fuzzer_worker_pause(FuzzerWorker* instance) {
|
|
@@ -541,7 +429,7 @@ void fuzzer_worker_pause(FuzzerWorker* instance) {
|
|
|
furi_timer_stop(instance->timer);
|
|
furi_timer_stop(instance->timer);
|
|
|
|
|
|
|
|
if(instance->treead_running) {
|
|
if(instance->treead_running) {
|
|
|
- hardware_worker_stop(instance);
|
|
|
|
|
|
|
+ hardware_worker_stop(instance->hw_worker);
|
|
|
|
|
|
|
|
FURI_LOG_D(TAG, "Worker Paused");
|
|
FURI_LOG_D(TAG, "Worker Paused");
|
|
|
}
|
|
}
|
|
@@ -553,7 +441,7 @@ void fuzzer_worker_stop(FuzzerWorker* instance) {
|
|
|
furi_timer_stop(instance->timer);
|
|
furi_timer_stop(instance->timer);
|
|
|
|
|
|
|
|
if(instance->treead_running) {
|
|
if(instance->treead_running) {
|
|
|
- hardware_worker_stop_thread(instance);
|
|
|
|
|
|
|
+ hardware_worker_stop_thread(instance->hw_worker);
|
|
|
|
|
|
|
|
FURI_LOG_D(TAG, "Worker Stopping");
|
|
FURI_LOG_D(TAG, "Worker Stopping");
|
|
|
instance->treead_running = false;
|
|
instance->treead_running = false;
|