1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 20:49:49 +04:00

Merge pull request #51 from mothball187/nrfsniffer-improvements

tweak sniff parameters for more speed and reliability
This commit is contained in:
MX
2022-08-28 05:59:06 +03:00
committed by GitHub
2 changed files with 80 additions and 64 deletions

View File

@@ -9,8 +9,10 @@
#include <toolbox/stream/file_stream.h> #include <toolbox/stream/file_stream.h>
#define LOGITECH_MAX_CHANNEL 85 #define LOGITECH_MAX_CHANNEL 85
#define COUNT_THRESHOLD 4 #define COUNT_THRESHOLD 2
#define SAMPLE_TIME 20000 #define DEFAULT_SAMPLE_TIME 8000
#define MAX_ADDRS 100
#define MAX_CONFIRMED 32
#define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff" #define NRFSNIFF_APP_PATH_FOLDER "/ext/nrfsniff"
#define NRFSNIFF_APP_FILENAME "addresses.txt" #define NRFSNIFF_APP_FILENAME "addresses.txt"
@@ -32,31 +34,36 @@ typedef struct {
} PluginState; } PluginState;
char rate_text_fmt[] = "Transfer rate: %dMbps"; char rate_text_fmt[] = "Transfer rate: %dMbps";
char sample_text_fmt[] = "Sample Time: %d ms";
char channel_text_fmt[] = "Channel: %d"; char channel_text_fmt[] = "Channel: %d";
char preamble_text_fmt[] = "Preamble: %02X"; char preamble_text_fmt[] = "Preamble: %02X";
char sniff_text_fmt[] = "Sniffing: %s Found: %d"; char sniff_text_fmt[] = "Sniffing: %s Found: %d";
char addresses_header_text[] = "Address,rate"; char addresses_header_text[] = "Address,rate";
char sniffed_address_fmt[] = "%s,%d"; char sniffed_address_fmt[] = "%s,%d";
char rate_text[46]; char rate_text[46];
char channel_text[42]; char channel_text[14];
char sample_text[32];
char preamble_text[14]; char preamble_text[14];
char sniff_text[38]; char sniff_text[38];
char sniffed_address[14]; char sniffed_address[14];
uint8_t target_channel = 0; uint8_t target_channel = 0;
uint32_t found_count = 0; uint32_t found_count = 0;
uint32_t sample_time = DEFAULT_SAMPLE_TIME;
uint8_t target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps) uint8_t target_rate = 8; // rate can be either 8 (2Mbps) or 0 (1Mbps)
uint8_t target_preamble[] = {0xAA, 0x00}; uint8_t target_preamble[] = {0xAA, 0x00};
uint8_t sniffing_state = false; uint8_t sniffing_state = false;
char top_address[12]; char top_address[12];
uint8_t candidates[100][5] = {0}; // top 100 recurring addresses uint8_t candidates[MAX_ADDRS][5] = {0}; // last 100 sniffed addresses
uint32_t counts[100]; uint32_t counts[MAX_ADDRS];
uint8_t total_candidates = 0; uint8_t confirmed[MAX_CONFIRMED][5] = {0}; // first 32 confirmed addresses
uint8_t last_cleanup_idx = 101; // avoid replacing the last replaced addr uint8_t confirmed_idx = 0;
uint32_t total_candidates = 0;
uint32_t candidate_idx = 0;
static int get_addr_index(uint8_t* addr, uint8_t addr_size) { static int get_addr_index(uint8_t* addr, uint8_t addr_size) {
for(int i = 0; i < total_candidates; i++) { for(uint32_t i = 0; i < total_candidates; i++) {
uint8_t* arr_item = candidates[i]; uint8_t* arr_item = candidates[i];
if(!memcmp(arr_item, addr, addr_size)) return i; if(!memcmp(arr_item, addr, addr_size)) return i;
} }
@@ -64,32 +71,10 @@ static int get_addr_index(uint8_t* addr, uint8_t addr_size) {
return -1; return -1;
} }
/* static int get_highest_idx() {
static uint32_t get_addr_count(uint8_t* addr, uint8_t addr_size)
{
return counts[get_addr_index(addr, addr_size)];
}
*/
static uint8_t get_lowest_idx() {
uint32_t lowest = 10000;
uint8_t lowest_idx = 0;
for(uint8_t i = 0; i < total_candidates; i++) {
if(i == last_cleanup_idx) continue;
if(counts[i] < lowest) {
lowest = counts[i];
lowest_idx = i;
}
}
last_cleanup_idx = lowest_idx;
return lowest_idx;
}
static uint8_t get_highest_idx() {
uint32_t highest = 0; uint32_t highest = 0;
uint8_t highest_idx = 0; int highest_idx = 0;
for(uint8_t i = 0; i < total_candidates; i++) { for(uint32_t i = 0; i < total_candidates; i++) {
if(counts[i] > highest) { if(counts[i] > highest) {
highest = counts[i]; highest = counts[i];
highest_idx = i; highest_idx = i;
@@ -99,15 +84,15 @@ static uint8_t get_highest_idx() {
return highest_idx; return highest_idx;
} }
// if array is full, start over from beginning
static void insert_addr(uint8_t* addr, uint8_t addr_size) { static void insert_addr(uint8_t* addr, uint8_t addr_size) {
uint8_t idx = total_candidates; if(candidate_idx >= MAX_ADDRS)
if(total_candidates > 99) { candidate_idx = 0;
// replace addr with lowest count
idx = get_lowest_idx(); memcpy(candidates[candidate_idx], addr, addr_size);
} counts[candidate_idx] = 1;
memcpy(candidates[idx], addr, addr_size); if(total_candidates < MAX_ADDRS) total_candidates++;
counts[idx] = 1; candidate_idx++;
if(total_candidates < 100) total_candidates++;
} }
static void render_callback(Canvas* const canvas, void* ctx) { static void render_callback(Canvas* const canvas, void* ctx) {
@@ -128,13 +113,15 @@ static void render_callback(Canvas* const canvas, void* ctx) {
snprintf(rate_text, sizeof(rate_text), rate_text_fmt, (int)rate); snprintf(rate_text, sizeof(rate_text), rate_text_fmt, (int)rate);
snprintf(channel_text, sizeof(channel_text), channel_text_fmt, (int)target_channel); snprintf(channel_text, sizeof(channel_text), channel_text_fmt, (int)target_channel);
snprintf(preamble_text, sizeof(preamble_text), preamble_text_fmt, target_preamble[0]); snprintf(sample_text, sizeof(sample_text), sample_text_fmt, (int)sample_time);
//snprintf(preamble_text, sizeof(preamble_text), preamble_text_fmt, target_preamble[0]);
snprintf(sniff_text, sizeof(sniff_text), sniff_text_fmt, sniffing, found_count); snprintf(sniff_text, sizeof(sniff_text), sniff_text_fmt, sniffing, found_count);
snprintf( snprintf(
sniffed_address, sizeof(sniffed_address), sniffed_address_fmt, top_address, (int)rate); sniffed_address, sizeof(sniffed_address), sniffed_address_fmt, top_address, (int)rate);
canvas_draw_str_aligned(canvas, 10, 10, AlignLeft, AlignBottom, rate_text); canvas_draw_str_aligned(canvas, 10, 10, AlignLeft, AlignBottom, rate_text);
canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, channel_text); canvas_draw_str_aligned(canvas, 10, 20, AlignLeft, AlignBottom, sample_text);
canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, preamble_text); canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, channel_text);
//canvas_draw_str_aligned(canvas, 10, 30, AlignLeft, AlignBottom, preamble_text);
canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, sniff_text); canvas_draw_str_aligned(canvas, 10, 40, AlignLeft, AlignBottom, sniff_text);
canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text); canvas_draw_str_aligned(canvas, 30, 50, AlignLeft, AlignBottom, addresses_header_text);
canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address); canvas_draw_str_aligned(canvas, 30, 60, AlignLeft, AlignBottom, sniffed_address);
@@ -256,12 +243,24 @@ void alt_address(uint8_t* addr, uint8_t* altaddr) {
for(int i = 0; i < 5; i++) altaddr[i] = tmpaddr[4 - i]; for(int i = 0; i < 5; i++) altaddr[i] = tmpaddr[4 - i];
} }
static bool previously_confirmed(uint8_t *addr){
bool found = false;
for(int i = 0; i < MAX_CONFIRMED; i++){
if(!memcmp(confirmed[i], addr, 5)){
found = true;
break;
}
}
return found;
}
static void wrap_up(Storage* storage, NotificationApp* notification) { static void wrap_up(Storage* storage, NotificationApp* notification) {
uint8_t ch; uint8_t ch;
uint8_t addr[5]; uint8_t addr[5];
uint8_t altaddr[5]; uint8_t altaddr[5];
char trying[12]; char trying[12];
uint8_t idx; int idx;
uint8_t rate = 0; uint8_t rate = 0;
if(target_rate == 8) rate = 2; if(target_rate == 8) rate = 2;
@@ -291,14 +290,25 @@ static void wrap_up(Storage* storage, NotificationApp* notification) {
hexlify(addr, 5, top_address); hexlify(addr, 5, top_address);
save_addr_to_file(storage, addr, 5, notification); save_addr_to_file(storage, addr, 5, notification);
found_count++; found_count++;
if(confirmed_idx < MAX_CONFIRMED)
memcpy(confirmed[confirmed_idx++], addr, 5);
break; break;
} }
} }
} }
static void start_sniffing() { static void clear_cache(){
found_count = 0;
confirmed_idx = 0;
candidate_idx = 0;
target_channel = 2;
total_candidates = 0;
memset(candidates, 0, sizeof(candidates)); memset(candidates, 0, sizeof(candidates));
memset(counts, 0, sizeof(counts)); memset(counts, 0, sizeof(counts));
memset(confirmed, 0, sizeof(confirmed));
}
static void start_sniffing() {
nrf24_init_promisc_mode(nrf24_HANDLE, target_channel, target_rate); nrf24_init_promisc_mode(nrf24_HANDLE, target_channel, target_rate);
} }
@@ -311,8 +321,8 @@ int32_t nrfsniff_app(void* p) {
PluginState* plugin_state = malloc(sizeof(PluginState)); PluginState* plugin_state = malloc(sizeof(PluginState));
ValueMutex state_mutex; ValueMutex state_mutex;
if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) {
FURI_LOG_E(TAG, "cannot create mutex\r\n");
furi_message_queue_free(event_queue); furi_message_queue_free(event_queue);
FURI_LOG_E(TAG, "cannot create mutex\r\n");
free(plugin_state); free(plugin_state);
return 255; return 255;
} }
@@ -366,18 +376,20 @@ int32_t nrfsniff_app(void* p) {
break; break;
case InputKeyRight: case InputKeyRight:
// increment channel // increment channel
if(!sniffing_state && target_channel <= LOGITECH_MAX_CHANNEL) //if(!sniffing_state && target_channel <= LOGITECH_MAX_CHANNEL)
target_channel++; // target_channel++;
sample_time += 500;
break; break;
case InputKeyLeft: case InputKeyLeft:
// decrement channel // decrement channel
if(!sniffing_state && target_channel > 0) target_channel--; //if(!sniffing_state && target_channel > 0) target_channel--;
if(sample_time > 500) sample_time -= 500;
break; break;
case InputKeyOk: case InputKeyOk:
// toggle sniffing // toggle sniffing
sniffing_state = !sniffing_state; sniffing_state = !sniffing_state;
if(sniffing_state) { if(sniffing_state) {
found_count = 0; clear_cache();
start_sniffing(); start_sniffing();
start = furi_get_tick(); start = furi_get_tick();
} else } else
@@ -398,6 +410,7 @@ int32_t nrfsniff_app(void* p) {
if(nrf24_sniff_address(nrf24_HANDLE, 5, address)) { if(nrf24_sniff_address(nrf24_HANDLE, 5, address)) {
int idx; int idx;
uint8_t* top_addr; uint8_t* top_addr;
if(!previously_confirmed(address)){
idx = get_addr_index(address, 5); idx = get_addr_index(address, 5);
if(idx == -1) if(idx == -1)
insert_addr(address, 5); insert_addr(address, 5);
@@ -407,13 +420,16 @@ int32_t nrfsniff_app(void* p) {
top_addr = candidates[get_highest_idx()]; top_addr = candidates[get_highest_idx()];
hexlify(top_addr, 5, top_address); hexlify(top_addr, 5, top_address);
} }
}
if(furi_get_tick() - start >= SAMPLE_TIME) { if(furi_get_tick() - start >= sample_time) {
wrap_up(storage, notification);
target_channel++; target_channel++;
if(target_channel > LOGITECH_MAX_CHANNEL) target_channel = 2; if(target_channel > LOGITECH_MAX_CHANNEL) target_channel = 2;
{
wrap_up(storage, notification);
start_sniffing(); start_sniffing();
}
start = furi_get_tick(); start = furi_get_tick();
} }
} }
@@ -422,6 +438,7 @@ int32_t nrfsniff_app(void* p) {
release_mutex(&state_mutex, plugin_state); release_mutex(&state_mutex, plugin_state);
} }
clear_cache();
furi_hal_spi_release(nrf24_HANDLE); furi_hal_spi_release(nrf24_HANDLE);
view_port_enabled_set(view_port, false); view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port); gui_remove_view_port(gui, view_port);

View File

@@ -350,12 +350,11 @@ void nrf24_init_promisc_mode(FuriHalSpiBusHandle* handle, uint8_t channel, uint8
nrf24_flush_tx(handle); nrf24_flush_tx(handle);
nrf24_write_reg(handle, REG_RF_CH, channel); nrf24_write_reg(handle, REG_RF_CH, channel);
nrf24_write_reg(handle, REG_RF_SETUP, rate); nrf24_write_reg(handle, REG_RF_SETUP, rate);
furi_delay_ms(200);
// prime for RX, no checksum // prime for RX, no checksum
nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC nrf24_write_reg(handle, REG_CONFIG, 0x03); // PWR_UP and PRIM_RX, disable AA and CRC
furi_hal_gpio_write(nrf24_CE_PIN, true); furi_hal_gpio_write(nrf24_CE_PIN, true);
furi_delay_ms(2000); furi_delay_ms(100);
} }
void hexlify(uint8_t* in, uint8_t size, char* out) { void hexlify(uint8_t* in, uint8_t size, char* out) {