From 971ef7915d98082dd05b2ee3ac6933defa0aa184 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Tue, 20 Dec 2022 00:55:14 -0500 Subject: [PATCH 1/2] NRF24 Scanner v2.0 --- ReadMe.md | 3 +- applications/plugins/nrf24scan/nrf24scan.c | 334 +++++++++++---------- applications/plugins/nrf24scan/nrf24scan.h | 7 + 3 files changed, 185 insertions(+), 159 deletions(-) diff --git a/ReadMe.md b/ReadMe.md index ec0283e78..289bdc274 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -45,6 +45,7 @@ Thank you to all the supporters! - Fixed: [Music Beeper (By DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/pull/1189) (With Changes By qqMajiKpp/Haseo) with thanks to [xMasterX](https://github.com/xMasterX/unleashed-extra-pack) - Fixed: [Air Mouse (By ginkage)](https://github.com/ginkage/FlippAirMouse/) with thanks to [xMasterX](https://github.com/xMasterX/unleashed-extra-pack) - Fixed: [USB Midi (By DrZlo13)](https://github.com/DrZlo13/flipper-zero-usb-midi) with thanks to [xMasterX](https://github.com/xMasterX/unleashed-extra-pack) +- Updated: [NRF24 Scanner v2.0 (By vad7)](https://github.com/vad7/nrf24scan) ## Install from Release FLASH STOCK FIRST BEFORE UPDATING TO CUSTOM FIRMWARE! @@ -241,7 +242,7 @@ $ ./fbt resources icons dolphin_ext - [Music Player (By DrZlo13)-OFW](https://github.com/flipperdevices/flipperzero-firmware/pull/1189) - [NFC Magic (By gornekich)](https://github.com/flipperdevices/flipperzero-firmware/pull/1966) - [NRF Sniff (By mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/nrfsniff) ([Pin Out](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/tree/420/applications/nrfsniff) from nocomp/Frog/UberGuidoZ) `Req: NRF24` -- [NRF24 Scanner v1.8 (By vad7)](https://github.com/vad7/nrf24scan) +- [NRF24 Scanner v2.0 (By vad7)](https://github.com/vad7/nrf24scan) - [Ocarina (By invalidna-me)](https://github.com/invalidna-me/flipperzero-ocarina) [Here are the LOTZ Songs](https://www.zeldadungeon.net/wiki/Ocarina_of_Time_Songs) - [Orgasmotron (By qqmajikpp)](https://github.com/qqmajikpp/flipperzero-firmware-wPlugins) - [Paint (By n-o-T-I-n-s-a-n-e)](https://github.com/n-o-T-I-n-s-a-n-e) diff --git a/applications/plugins/nrf24scan/nrf24scan.c b/applications/plugins/nrf24scan/nrf24scan.c index f2bdfa096..6e89a243d 100644 --- a/applications/plugins/nrf24scan/nrf24scan.c +++ b/applications/plugins/nrf24scan/nrf24scan.c @@ -14,7 +14,7 @@ #include #define TAG "nrf24scan" -#define VERSION "2.0b" +#define VERSION "2.0" #define MAX_CHANNEL 125 #define MAX_ADDR 6 @@ -85,9 +85,9 @@ struct ADDRS { struct ADDRS addrs; struct ADDRS addrs_sniff; -struct ADDRS addrs_found; -uint16_t found_total[6]; bool sniff_loaded = 0; +int16_t found_total; +int16_t view_found = 0; int8_t log_to_file = 0; // 0 - no, 1 - yes(new), 2 - append, -1 - only clear uint16_t log_arr_idx; @@ -98,7 +98,6 @@ uint16_t last_packet_send = -1; uint8_t last_packet_send_st = 0; int16_t find_channel_period = 0; // sec uint8_t menu_selected = 0; -uint8_t view_details_type = 1; // 0 - sniff addrs, 1 - found addrs uint32_t start_time; uint8_t view_log_decode_PCF = 0; // view log: 1 - decode packet control field (9b) when ESB off. After pipe # (hex): @@ -165,18 +164,8 @@ void clear_log() { log_arr_idx = 0; view_log_arr_idx = 0; last_packet_send = -1; - memset(&addrs_found, 0, sizeof(addrs_found)); - view_details_type = 0; - memset(&found_total, 0, sizeof(found_total)); -} - -void allocate_log_array() { - APP->log_arr = malloc(LOG_REC_SIZE * MAX_LOG_RECORDS); - if(APP->log_arr == NULL) { - FURI_LOG_E(TAG, "Not enouch memory: %d", LOG_REC_SIZE * MAX_LOG_RECORDS); - strcpy(addr_file_name, "MEMORY LOW!"); - } - clear_log(); + found_total = 0; + view_found = 0; } void write_to_log_file(Storage* storage, bool f_settings) { @@ -578,42 +567,25 @@ static void start_scanning() { start_time = furi_get_tick(); } -bool check_addr_found(uint8_t* pkt) { - uint8_t idx = 255; - if(addrs_found.addr_count > 0 && memcmp(addrs_found.addr_P0, pkt, addrs_found.addr_len) == 0) { - idx = 0; - goto x_end; - } - if(addrs_found.addr_count > 1 && - memcmp(addrs_found.addr_P1, pkt, addrs_found.addr_len - 1) == 0) { - if(addrs_found.addr_P1[addrs_found.addr_len - 1] == pkt[addrs_found.addr_len - 1]) { - idx = 1; - goto x_end; - } - if(addrs_found.addr_count > 2 && addrs_found.addr_P2 == pkt[addrs_found.addr_len - 1]) { - idx = 2; - goto x_end; - } - if(addrs_found.addr_count > 3 && addrs_found.addr_P3 == pkt[addrs_found.addr_len - 1]) { - idx = 3; - goto x_end; - } - if(addrs_found.addr_count > 4 && addrs_found.addr_P4 == pkt[addrs_found.addr_len - 1]) { - idx = 4; - goto x_end; - } - if(addrs_found.addr_count > 5 && addrs_found.addr_P5 == pkt[addrs_found.addr_len - 1]) { - idx = 5; - goto x_end; - } - } +/* +bool check_addr_found(uint8_t *pkt) +{ + uint8_t idx = 255; + if(addrs_found.addr_count > 0 && memcmp(addrs_found.addr_P0, pkt, addrs_found.addr_len) == 0) { idx = 0; goto x_end; } + if(addrs_found.addr_count > 1 && memcmp(addrs_found.addr_P1, pkt, addrs_found.addr_len - 1) == 0) { + if(addrs_found.addr_P1[addrs_found.addr_len - 1] == pkt[addrs_found.addr_len - 1]) { idx = 1; goto x_end; } + if(addrs_found.addr_count > 2 && addrs_found.addr_P2 == pkt[addrs_found.addr_len - 1]) { idx = 2; goto x_end; } + if(addrs_found.addr_count > 3 && addrs_found.addr_P3 == pkt[addrs_found.addr_len - 1]) { idx = 3; goto x_end; } + if(addrs_found.addr_count > 4 && addrs_found.addr_P4 == pkt[addrs_found.addr_len - 1]) { idx = 4; goto x_end; } + if(addrs_found.addr_count > 5 && addrs_found.addr_P5 == pkt[addrs_found.addr_len - 1]) { idx = 5; goto x_end; } + } x_end: - if(idx < sizeof(found_total) / sizeof(found_total[0])) { - found_total[idx]++; - return true; - } else - return false; + if(idx < sizeof(found_total) / sizeof(found_total[0])) { + found_total[idx]++; + return true; + } else return false; } +*/ // start bitnum = 7 uint32_t calc_crc(uint32_t crc, uint8_t* ptr, uint8_t bitnum, uint16_t bits) { @@ -652,7 +624,7 @@ bool check_packet(uint8_t* pkt, uint16_t size) { uint8_t b = *pkt; if(b == 0x55 || b == 0xAA || b == 0x00 || b == 0xFF) return false; // skip pkt when address begin with - uint32_t prevcrc; + uint32_t prevcrc = 0xFFFFFFFF; bool found = false; uint8_t addr_size = 3; for(; addr_size <= 5; addr_size++) { @@ -661,16 +633,18 @@ bool check_packet(uint8_t* pkt, uint16_t size) { if((_payload > size - addr_size - 2 - view_log_decode_CRC && _payload != 0x33)) continue; uint8_t* p = pkt + addr_size; - if(addr_size == 3) { + if(prevcrc == 0xFFFFFFFF) { prevcrc = calc_crc( view_log_decode_CRC == 2 ? 0xFFFF : 0xFF, pkt, 7, 3 * 8); // crc for smallest addr - } else { - prevcrc = calc_crc(prevcrc, p - 1, 7, 8); } - uint32_t crc = prevcrc; + uint32_t crc; + if(addr_size > 3) + crc = calc_crc(prevcrc, p - (addr_size - 3), 7, 8 * (addr_size - 3)); + else + crc = prevcrc; if(_payload != 0x33) { // DPL crc = calc_crc(crc, p, 7, 9 + _payload * 8); if(crc == get_shifted_crc(p + _payload + 1)) { @@ -736,61 +710,88 @@ bool check_packet(uint8_t* pkt, uint16_t size) { if(found) break; } } - if(found && furi_log_get_level() == FuriLogLevelDebug) { - char dbuf[65]; - dbuf[0] = 0; - add_to_str_hex_bytes(dbuf, (char*)pkt, size); - FURI_LOG_D(TAG, "PKT%02X: %s (%d)", *(pkt - 1), dbuf, size); - } - if(found && addrs_found.addr_count < 6) { - if(addrs_found.addr_count == 0) { - memcpy(addrs_found.addr_P0, pkt, addr_size); - addrs_found.addr_len = addr_size; - found_total[0]++; - addrs_found.addr_count++; - } else if(addr_size == addrs_found.addr_len) { - if(!check_addr_found(pkt)) { - if(addrs_found.addr_count == 1) { - memcpy(addrs_found.addr_P1, pkt, addr_size); - found_total[1]++; - addrs_found.addr_count++; - } else if(addrs_found.addr_count == 2) { - if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) { - addrs_found.addr_P2 = pkt[addr_size - 1]; - found_total[2]++; - addrs_found.addr_count++; - } else if(memcmp(addrs_found.addr_P0, pkt, addr_size - 1) == 0) { - uint8_t tmp[5]; - memcpy(tmp, addrs_found.addr_P1, addr_size); // swap P0-P1 - memcpy(addrs_found.addr_P1, addrs_found.addr_P0, addr_size); - memcpy(addrs_found.addr_P0, tmp, addr_size); - uint32_t n = found_total[0]; - found_total[0] = found_total[1]; - found_total[1] = n; - addrs_found.addr_P2 = pkt[addr_size - 1]; - found_total[2]++; - addrs_found.addr_count++; - } - } else if(addrs_found.addr_count >= 3) { - if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) { - if(addrs_found.addr_count == 3) { - addrs_found.addr_P3 = pkt[addr_size - 1]; - found_total[3]++; - addrs_found.addr_count++; - } else if(addrs_found.addr_count == 4) { - addrs_found.addr_P4 = pkt[addr_size - 1]; - found_total[4]++; - addrs_found.addr_count++; - } else if(addrs_found.addr_count == 5) { - addrs_found.addr_P5 = pkt[addr_size - 1]; - found_total[5]++; - addrs_found.addr_count++; - } - } + if(found) { + if(furi_log_get_level() == FuriLogLevelDebug) { + char dbuf[65]; + dbuf[0] = 0; + add_to_str_hex_bytes(dbuf, (char*)pkt, size); + FURI_LOG_D(TAG, "PKT%02X: %s (%d)", *(pkt - 1), dbuf, size); + } + int16_t i = 0; + for(; i < found_total; i++) { + if(APP->found[i].addr_size != addr_size) continue; + if(memcmp(APP->found[i].addr, pkt, addr_size) == 0) break; + } + if(i != found_total) { // found + APP->found[i].total++; + } else { + pkt--; + uint8_t* p = APP->log_arr; + for(i = 0; i < log_arr_idx; i++, p += LOG_REC_SIZE) { + if(*p & 0x80 && (*(p + 1) & 0b11) + 2 == addr_size && pkt != p) { + if(memcmp(p, pkt, addr_size) == 0) break; } } + if(i != log_arr_idx && found_total < MAX_LOG_RECORDS) { // found -> 2 + memset(&APP->found[found_total], 0, sizeof(struct FOUND)); + memcpy(APP->found[found_total].addr, pkt, addr_size); + APP->found[found_total].addr_size = addr_size; + APP->found[found_total].total = 2; + if(found_total == 0) view_found = 0; + found_total++; + } } + /* + if(addrs_found.addr_count == 0) { + memcpy(addrs_found.addr_P0, pkt, addr_size); + addrs_found.addr_len = addr_size; + found_total[0]++; + addrs_found.addr_count++; + } else if(addr_size == addrs_found.addr_len) { + if(!check_addr_found(pkt)) { + if(addrs_found.addr_count == 1) { + memcpy(addrs_found.addr_P1, pkt, addr_size); + found_total[1]++; + addrs_found.addr_count++; + } else if(addrs_found.addr_count == 2) { + if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) { + addrs_found.addr_P2 = pkt[addr_size - 1]; + found_total[2]++; + addrs_found.addr_count++; + } else if(memcmp(addrs_found.addr_P0, pkt, addr_size - 1) == 0) { + uint8_t tmp[5]; + memcpy(tmp, addrs_found.addr_P1, addr_size); // swap P0-P1 + memcpy(addrs_found.addr_P1, addrs_found.addr_P0, addr_size); + memcpy(addrs_found.addr_P0, tmp, addr_size); + uint32_t n = found_total[0]; + found_total[0] = found_total[1]; + found_total[1] = n; + addrs_found.addr_P2 = pkt[addr_size - 1]; + found_total[2]++; + addrs_found.addr_count++; + } + } else if(addrs_found.addr_count >= 3) { + if(memcmp(addrs_found.addr_P1, pkt, addr_size - 1) == 0) { + if(addrs_found.addr_count == 3) { + addrs_found.addr_P3 = pkt[addr_size - 1]; + found_total[3]++; + addrs_found.addr_count++; + } else if(addrs_found.addr_count == 4) { + addrs_found.addr_P4 = pkt[addr_size - 1]; + found_total[4]++; + addrs_found.addr_count++; + } else if(addrs_found.addr_count == 5) { + addrs_found.addr_P5 = pkt[addr_size - 1]; + found_total[5]++; + addrs_found.addr_count++; + } + } + } + } + } +*/ } + return found; } @@ -802,7 +803,7 @@ bool nrf24_read_newpacket() { uint8_t st; /* test pkts static int iii = 0; - char ppp[][65] = { "42E4A65544CC4AD9B25655A93E25669895572162DDA295524660D2", + char ppp[][65] = { "54A545109411544BAAE50110A3282512A9A1152A565B22AAA48AB751A5", "C8C8C0CE7A81018007202FFFFC", "EAEC8C8C2CE3C0101006FB737A", "BEBFFFEC8C8C1CC00542AF7CFF7DBEAFE3397FEAFEF1DDFA4AEF7FDBB7CDEABC", @@ -1211,54 +1212,61 @@ static void render_callback(Canvas* const canvas, void* ctx) { } } else { canvas_set_font(canvas, FontBatteryPercent); // 5x7 font, 9 lines - struct ADDRS* a; - if(what_to_do == 1) { - if(view_details_type && addrs_found.addr_count) { - a = &addrs_found; - canvas_draw_str(canvas, 0, 1 * 7, "Found addr:"); - } else { - a = &addrs_sniff; - canvas_draw_str(canvas, 0, 1 * 7, "Sniff prefix:"); + if(view_found >= 0) { + snprintf(screen_buf, 50, "Found > 1: %d", found_total); + canvas_draw_str(canvas, 0, 1 * 7, screen_buf); + int16_t idx = view_found * 7; + for(uint8_t i = 0; i < 7; i++) { + if(idx++ >= found_total) break; + snprintf(screen_buf, 16, "%d. ", idx); + add_to_str_hex_bytes( + screen_buf, (char*)APP->found[idx].addr, APP->found[idx].addr_size); + if(APP->found[idx].addr_size == 3) + strcat(screen_buf, " "); + else if(APP->found[idx].addr_size == 4) + strcat(screen_buf, " "); + snprintf(screen_buf + strlen(screen_buf), 16, " - %d", APP->found[idx].total); + canvas_draw_str(canvas, 0, 2 + i * 7, screen_buf); } } else { - a = &addrs; - canvas_draw_str(canvas, 0, 1 * 7, "Addresses:"); - } - if(a->addr_count > 0) { - snprintf(screen_buf, sizeof(screen_buf), "P0: "); - add_to_str_hex_bytes(screen_buf, (char*)a->addr_P0, a->addr_len); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[0]); - canvas_draw_str(canvas, 0, 2 * 7, screen_buf); - } - if(a->addr_count > 1) { - snprintf(screen_buf, sizeof(screen_buf), "P1: "); - add_to_str_hex_bytes(screen_buf, (char*)a->addr_P1, a->addr_len); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[1]); - canvas_draw_str(canvas, 0, 3 * 7, screen_buf); - } - if(a->addr_count > 2) { - canvas_draw_str(canvas, 0, 4 * 7, "P2: "); - snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P2); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[2]); - canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 4 * 7, screen_buf); - } - if(a->addr_count > 3) { - canvas_draw_str(canvas, 0, 5 * 7, "P3: "); - snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P3); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[3]); - canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 5 * 7, screen_buf); - } - if(a->addr_count > 4) { - canvas_draw_str(canvas, 0, 6 * 7, "P4: "); - snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P4); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[4]); - canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 6 * 7, screen_buf); - } - if(a->addr_count > 5) { - canvas_draw_str(canvas, 0, 7 * 7, "P5: "); - snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P5); - snprintf(screen_buf + strlen(screen_buf), 16, " - %d", found_total[5]); - canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 7 * 7, screen_buf); + struct ADDRS* a; + if(what_to_do == 1) { + a = &addrs_sniff; + canvas_draw_str(canvas, 0, 1 * 7, "Sniff prefix:"); + } else { + a = &addrs; + canvas_draw_str(canvas, 0, 1 * 7, "Addresses:"); + } + if(a->addr_count > 0) { + snprintf(screen_buf, sizeof(screen_buf), "P0: "); + add_to_str_hex_bytes(screen_buf, (char*)a->addr_P0, a->addr_len); + canvas_draw_str(canvas, 0, 2 * 7, screen_buf); + } + if(a->addr_count > 1) { + snprintf(screen_buf, sizeof(screen_buf), "P1: "); + add_to_str_hex_bytes(screen_buf, (char*)a->addr_P1, a->addr_len); + canvas_draw_str(canvas, 0, 3 * 7, screen_buf); + } + if(a->addr_count > 2) { + canvas_draw_str(canvas, 0, 4 * 7, "P2: "); + snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P2); + canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 4 * 7, screen_buf); + } + if(a->addr_count > 3) { + canvas_draw_str(canvas, 0, 5 * 7, "P3: "); + snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P3); + canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 5 * 7, screen_buf); + } + if(a->addr_count > 4) { + canvas_draw_str(canvas, 0, 6 * 7, "P4: "); + snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P4); + canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 6 * 7, screen_buf); + } + if(a->addr_count > 5) { + canvas_draw_str(canvas, 0, 7 * 7, "P5: "); + snprintf(screen_buf, sizeof(screen_buf), "%02X", a->addr_P5); + canvas_draw_str(canvas, (4 + (a->addr_len - 1) * 2) * 5, 7 * 7, screen_buf); + } } if(log_arr_idx) { uint8_t* ptr = APP->log_arr + view_log_arr_idx * LOG_REC_SIZE; @@ -1304,9 +1312,20 @@ int32_t nrf24scan_app(void* p) { free(APP->plugin_state); return 255; } + APP->log_arr = malloc(LOG_REC_SIZE * MAX_LOG_RECORDS); + if(APP->log_arr == NULL) { + FURI_LOG_E(TAG, "Not enouch memory: %d", LOG_REC_SIZE * MAX_LOG_RECORDS); + strcpy(addr_file_name, "MEMORY LOW!"); + } + clear_log(); + APP->found = malloc(sizeof(struct FOUND) * MAX_LOG_RECORDS); + if(APP->found == NULL) { + FURI_LOG_E(TAG, "Not enouch memory: %d", sizeof(struct FOUND) * MAX_LOG_RECORDS); + strcpy(addr_file_name, "MEMORY LOW!!"); + } + memset((uint8_t*)&addrs, 0, sizeof(addrs)); memset((uint8_t*)&addrs_sniff, 0, sizeof(addrs_sniff)); - memset((uint8_t*)&addrs_found, 0, sizeof(addrs_found)); nrf24_init(); // Set system callbacks @@ -1348,7 +1367,6 @@ int32_t nrf24scan_app(void* p) { file_stream_close(file_stream); stream_free(file_stream); furi_string_free(path); - allocate_log_array(); PluginEvent event; for(bool processing = true; processing;) { @@ -1371,7 +1389,7 @@ int32_t nrf24scan_app(void* p) { view_log_arr_idx -= event.input.type == InputTypeRepeat ? 10 : 1; if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = 0; } else if(what_doing == 2) { - view_details_type = 0; + if(view_found > -1) view_found--; } } break; @@ -1386,7 +1404,7 @@ int32_t nrf24scan_app(void* p) { view_log_arr_idx += event.input.type == InputTypeRepeat ? 10 : 1; if(view_log_arr_idx >= log_arr_idx) view_log_arr_idx = log_arr_idx - 1; } else if(what_doing == 2) { - view_details_type = 1; + if(view_found < found_total / 7) view_found++; } } break; @@ -1559,7 +1577,6 @@ int32_t nrf24scan_app(void* p) { else if(event.input.type == InputTypeShort) { if(what_doing) what_doing--; if(what_doing == 0) { - memcpy(&addrs, &addrs_found, sizeof(addrs)); nrf24_set_idle(nrf24_HANDLE); } } @@ -1596,6 +1613,7 @@ int32_t nrf24scan_app(void* p) { furi_message_queue_free(APP->event_queue); free(APP->plugin_state); if(APP->log_arr) free(APP->log_arr); + if(APP->found) free(APP->found); free(APP); return 0; } diff --git a/applications/plugins/nrf24scan/nrf24scan.h b/applications/plugins/nrf24scan/nrf24scan.h index c3fa2891a..ea8d7ac04 100644 --- a/applications/plugins/nrf24scan/nrf24scan.h +++ b/applications/plugins/nrf24scan/nrf24scan.h @@ -23,6 +23,12 @@ typedef struct { int y; } PluginState; +struct FOUND { + uint8_t addr_size; + uint8_t addr[5]; + uint16_t total; +}; + typedef struct { Gui* gui; FuriMessageQueue* event_queue; @@ -31,4 +37,5 @@ typedef struct { Storage* storage; NotificationApp* notification; uint8_t* log_arr; + struct FOUND* found; } Nrf24Scan; From 5b2d2600962ceb0e7daf093f1ed074fbdaf3f129 Mon Sep 17 00:00:00 2001 From: RogueMaster Date: Tue, 20 Dec 2022 01:02:19 -0500 Subject: [PATCH 2/2] Latest Release RM1220-0057-0.73.2-971ef79 on PATREON --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 289bdc274..78b407cae 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -16,7 +16,7 @@ Thank you to all the supporters! - Donations: ETH: `0xC32Ea488DBeCF95992A5C81BD411e56Bd418BC5f` - [Join THE Flipper Uncensored Discord](https://discord.gg/gF2bBUzAFe) -## Latest Updates - [PATREON: Latest Release RM1219-2313-0.73.2-5a642f3](https://www.patreon.com/posts/latest-release-0-76139893) +## Latest Updates - [PATREON: Latest Release RM1220-0057-0.73.2-971ef79](https://www.patreon.com/posts/76142361) ## [BUILDS NOW AVAILABLE WITH STOCK, RM SELECT, RM SELECT + 18PLUS, RM MINIMAL (default) and RM 18PLUS ANIMATION SETS](https://www.patreon.com/RogueMaster/membership) - Last Synced/Checked [Unleashed/xMasterX](https://github.com/DarkFlippers/unleashed-firmware), changes in [changelog](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/blob/420/CHANGELOG.md): `2022-12-19 23:13 EST`