333 lines
No EOL
11 KiB
C
333 lines
No EOL
11 KiB
C
/* abandon all hope, this shit is a mess */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <unistd.h>
|
|
#include <ncurses.h>
|
|
#include <rtl-sdr.h>
|
|
#include <curl/curl.h>
|
|
|
|
/* define ANSI escape chars and math */
|
|
#define RESET "\033[0m"
|
|
#define BOLD "\033[1m"
|
|
#define UNDERLINE "\033[4m"
|
|
#define BLINK "\033[5m"
|
|
#define REVERSED "\033[7m"
|
|
#define BLACK "\033[30m"
|
|
#define RED "\033[31m"
|
|
#define GREEN "\033[32m"
|
|
#define YELLOW "\033[33m"
|
|
#define BLUE "\033[34m"
|
|
#define MAGENTA "\033[35m"
|
|
#define CYAN "\033[36m"
|
|
#define WHITE "\033[37m"
|
|
#define BG_BLACK "\033[40m"
|
|
#define BG_RED "\033[41m"
|
|
#define BG_GREEN "\033[42m"
|
|
#define BG_YELLOW "\033[43m"
|
|
#define BG_BLUE "\033[44m"
|
|
#define BG_MAGENTA "\033[45m"
|
|
#define BG_CYAN "\033[46m"
|
|
#define BG_WHITE "\033[47m"
|
|
|
|
#define M_PI 3.14159265358979323846
|
|
|
|
/* declare global variables */
|
|
|
|
rtlsdr_dev_t *dev = NULL;
|
|
uint32_t device_index = 0;
|
|
uint32_t MHz = 1000000;
|
|
uint32_t kHz = 1000;
|
|
uint32_t bandwidth;
|
|
uint32_t center_freq;
|
|
bool SDR_PRESENT = false;
|
|
bool RSS_LIST_PRESENT = false;
|
|
bool COMMS_AVAILABLE = false;
|
|
bool CURL_AVAILABLE = false;
|
|
|
|
/* declare reusable functions */
|
|
|
|
/* read out shell command output */
|
|
char* readout(const char* command, char* buffer, size_t size) {
|
|
FILE *fp = popen(command, "r");
|
|
if (fp == NULL) {
|
|
perror("popen");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (fgets(buffer, size, fp) == NULL) {
|
|
perror("fgets");
|
|
pclose(fp);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
pclose(fp);
|
|
/* remove the newline character at the end of the buffer */
|
|
buffer[strcspn(buffer, "\n")] = 0;
|
|
return buffer;
|
|
}
|
|
|
|
void startup_screen() {
|
|
printf("\n\n");
|
|
printf(CYAN" █████ ███ ████ \n");
|
|
printf(" ░░███ ░░░ ░░███ \n");
|
|
printf(" █████ ██████ ████████ ███████ ████ ████████ ██████ ░███ \n");
|
|
printf(" ███░░ ███░░███░░███░░███ ░░░███░ ░░███ ░░███░░███ ███░░███ ░███ \n");
|
|
printf("░░█████ ░███████ ░███ ░███ ░███ ░███ ░███ ░███ ░███████ ░███ \n");
|
|
printf(" ░░░░███░███░░░ ░███ ░███ ░███ ███ ░███ ░███ ░███ ░███░░░ ░███ \n");
|
|
printf(" ██████ ░░██████ ████ █████ ░░█████ █████ ████ █████░░██████ █████\n");
|
|
printf("░░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░ ░░░░░ ░░░░░░ ░░░░░ \n\n");
|
|
printf(" v0.0.1\n" RESET);
|
|
}
|
|
|
|
/* declare functions for startup checks */
|
|
void util_check() {
|
|
printf("curl: ");
|
|
if (system("curl --version > /dev/null 2>&1") == 0) {
|
|
printf(GREEN"OK\n"RESET);
|
|
CURL_AVAILABLE = true;
|
|
} else {
|
|
printf(RED"FAIL\n"RESET);
|
|
}
|
|
printf("rtl-sdr: ");
|
|
if (system("ls /usr/bin/rtl_sdr > /dev/null 2>&1") == 0) {
|
|
printf(GREEN"OK\n"RESET);
|
|
SDR_PRESENT = true;
|
|
} else {
|
|
printf(RED"FAIL\n"RESET);
|
|
}
|
|
}
|
|
|
|
void rtl_sdr_check() {
|
|
|
|
if (rtlsdr_open != NULL && SDR_PRESENT == true) {
|
|
int index;
|
|
const char* device_name;
|
|
char serial[256], product[256], manufact[256];
|
|
device_name = rtlsdr_get_device_name(device_index);
|
|
rtlsdr_get_device_usb_strings(index, manufact, product, serial);
|
|
printf("device name: " GREEN);
|
|
printf(device_name);
|
|
printf("\n" RESET);
|
|
printf(YELLOW"serial: %s\n", serial);
|
|
printf("product: %s\n", product);
|
|
printf("manufacturer: %s\n", manufact);
|
|
printf(RESET);
|
|
rtlsdr_close;
|
|
} else {
|
|
printf(RED"SDR not detected! skipping...\n"RESET);
|
|
}
|
|
}
|
|
|
|
void defcon_level_check() {
|
|
FILE *fp = fopen(".last_known_defcon", "r");
|
|
if ( fp == NULL) {
|
|
printf(YELLOW"DEFCON level cache file not found or corrupted, creating new...\n"RESET);
|
|
FILE *fp = fopen(".last_known_defcon", "w");
|
|
fputc(5, fp);
|
|
fclose(fp);
|
|
} else {
|
|
int last_known = fgetc(fp);
|
|
printf("DEFCON level cache file found! last known level: %d\n", last_known);
|
|
fclose(fp);
|
|
}
|
|
}
|
|
|
|
void rss_sources_check() {
|
|
if (COMMS_AVAILABLE == true) {
|
|
FILE *fp = fopen(".rss_feed_list", "r");
|
|
if ( fp == NULL) {
|
|
printf(RED"RSS feed source list not found!\n"RESET);
|
|
fclose(fp);
|
|
} else {
|
|
printf(GREEN"RSS feed source list found! sources:\n\n"RESET);
|
|
RSS_LIST_PRESENT = true;
|
|
int line_count = 0;
|
|
char buffer[256];
|
|
|
|
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
|
line_count++;
|
|
}
|
|
|
|
char feed_source[line_count][256];
|
|
fseek(fp, 0, SEEK_SET);
|
|
for (int i = 0; i < line_count; i++) {
|
|
fgets(feed_source[i], sizeof(feed_source[i]), fp);
|
|
printf(GREEN"%s\n"RESET, feed_source[i]);
|
|
}
|
|
fclose(fp);
|
|
}
|
|
} else {
|
|
printf(RED"internet not available! skipping..."RESET);
|
|
}
|
|
}
|
|
|
|
|
|
/* making sure program has everything it needs to run, more checks will be introduced as capabilities are added */
|
|
void startup_checks() {
|
|
printf("######################################################################\n");
|
|
printf(MAGENTA"STARTUP CHECKS\n"RESET);
|
|
printf("----------------------------------------------------------------------\n");
|
|
printf(MAGENTA"SYSTEM STATUS\n\n"RESET);
|
|
printf("date: %s\n", readout("date \"+%D\"", (char[100]){0}, 100));
|
|
printf("time: %s\n", readout("date \"+%T\"", (char[100]){0}, 100));
|
|
/* internet connectivity check */
|
|
int status = system("ping -c 1 fsf.org > /dev/null 2>&1");
|
|
if (status == 0) {
|
|
printf("internet connectivity status: ");
|
|
printf(GREEN"online\n"RESET);
|
|
COMMS_AVAILABLE = true;
|
|
} else {
|
|
printf("internet connectivity status: ");
|
|
printf(RED"offline\n"RESET);
|
|
printf(RED"internet-dependent capabilities will be unavailable!"RESET);
|
|
COMMS_AVAILABLE = false;
|
|
}
|
|
printf("----------------------------------------------------------------------\n");
|
|
/* utilities presence check */
|
|
printf(MAGENTA"UTILITIES\n\n"RESET);
|
|
util_check();
|
|
printf("----------------------------------------------------------------------\n");
|
|
printf(MAGENTA"SOFTWARE-DEFINED RADIO\n\n"RESET);
|
|
rtl_sdr_check();
|
|
printf("----------------------------------------------------------------------\n");
|
|
printf(MAGENTA"DEFCON LEVEL STATUS\n\n"RESET);
|
|
defcon_level_check();
|
|
printf("----------------------------------------------------------------------\n");
|
|
printf(MAGENTA"RSS AGGREGATOR CHECK\n\n"RESET);
|
|
rss_sources_check();
|
|
printf("----------------------------------------------------------------------\n");
|
|
printf(MAGENTA"all checks finished!\n"RESET);
|
|
printf("######################################################################\n");
|
|
printf(BLUE"initializing in 5 seconds...\n\n"RESET);
|
|
usleep(5000000);
|
|
if (SDR_PRESENT == true)
|
|
{
|
|
printf(GREEN"initializing RTL-SDR...\n"RESET);
|
|
rtlsdr_open(&dev, device_index);
|
|
}
|
|
if (RSS_LIST_PRESENT == true && COMMS_AVAILABLE == true && CURL_AVAILABLE == true) {
|
|
printf(GREEN"initializing RSS aggregator...\n"RESET);
|
|
}
|
|
|
|
}
|
|
|
|
/* signal analysis function */
|
|
void fourier_transform(unsigned char *buf, double *out, int n) {
|
|
for (int k = 0; k < n; k++) {
|
|
double real = 0.0;
|
|
double imag = 0.0;
|
|
for (int t = 0; t < n; t++) {
|
|
double angle = 2 * M_PI * t * k / n;
|
|
real += buf[t] * cos(angle);
|
|
imag -= buf[t] * sin(angle);
|
|
}
|
|
out[k] = sqrt(real * real + imag * imag);
|
|
}
|
|
}
|
|
|
|
/* define functions for dashboard - WIP */
|
|
|
|
void init_colors() {
|
|
start_color();
|
|
init_pair(1, COLOR_RED, COLOR_BLACK);
|
|
init_pair(2, COLOR_GREEN, COLOR_BLACK);
|
|
init_pair(3, COLOR_YELLOW, COLOR_BLACK);
|
|
init_pair(4, COLOR_BLUE, COLOR_BLACK);
|
|
init_pair(5, COLOR_MAGENTA, COLOR_BLACK);
|
|
init_pair(6, COLOR_CYAN, COLOR_BLACK);
|
|
init_pair(7, COLOR_WHITE, COLOR_BLACK);
|
|
}
|
|
|
|
void draw_bar_graph(double *data, int size) {
|
|
clear();
|
|
double max_value = 0.0;
|
|
attron(COLOR_PAIR(6));
|
|
printw("center frequency: %.3f MHz gain: %d bandwidth: %.3f MHz", center_freq / (double)MHz, rtlsdr_get_tuner_gain(dev), bandwidth / (double)MHz);
|
|
attroff(COLOR_PAIR(6));
|
|
double bottom = center_freq - bandwidth / 2.0;
|
|
double step = bandwidth / (double)size;
|
|
for (int i = 0; i < size; i++) {
|
|
if (data[i] > max_value) {
|
|
max_value = data[i];
|
|
}
|
|
}
|
|
attron(COLOR_PAIR(4));
|
|
for (int i = 0; i < size; i++) {
|
|
mvprintw(i + 1, 0, "%.3f MHz: ", bottom / (double)MHz + i * step / (double)MHz);
|
|
for (int j = 0; j < data[i] * 50 / max_value; j++) {
|
|
printw(">");
|
|
}
|
|
}
|
|
attroff(COLOR_PAIR(4));
|
|
refresh();
|
|
}
|
|
|
|
|
|
/* define rtl-sdr specific functions and general SDR workflow - WIP */
|
|
|
|
void rtl_sdr_processing(unsigned char *buf, int buffer_length) {
|
|
int n = buffer_length;
|
|
double *out = (double *)malloc(n * sizeof(double));
|
|
fourier_transform(buf, out, n);
|
|
/* debug
|
|
for (int i = 0; i < n; i++) {
|
|
printf("%f\n", out[i]);
|
|
} */
|
|
draw_bar_graph(out, n);
|
|
free(out);
|
|
}
|
|
|
|
void rtl_sdr_waterfall() {
|
|
bandwidth = 10*MHz;
|
|
rtlsdr_set_tuner_bandwidth(dev, bandwidth);
|
|
uint32_t buffer_length = 40, n_read = 10; // example buffer length
|
|
unsigned char *buffer = (unsigned char *)malloc(buffer_length);
|
|
rtlsdr_set_center_freq(dev, 104*MHz); //104MHz for testing purposes
|
|
center_freq = rtlsdr_get_center_freq(dev);
|
|
rtlsdr_read_sync(dev, buffer, buffer_length, &n_read);
|
|
rtl_sdr_processing(buffer, buffer_length);
|
|
usleep(500000);
|
|
}
|
|
|
|
void sdr_not_available() {
|
|
clear();
|
|
attron(COLOR_PAIR(1));
|
|
printw("SDR NOT AVAILABLE");
|
|
attroff(COLOR_PAIR(1));
|
|
refresh();
|
|
usleep(5000000);
|
|
}
|
|
|
|
/* DEFCON level functions */
|
|
|
|
|
|
/* main dashboard function */
|
|
|
|
void start_dashboard() {
|
|
initscr();
|
|
cbreak();
|
|
noecho();
|
|
init_colors();
|
|
if (SDR_PRESENT == true) {
|
|
do{
|
|
rtl_sdr_waterfall();
|
|
} while (true);
|
|
}
|
|
else {
|
|
do{
|
|
sdr_not_available();
|
|
} while (true);
|
|
}
|
|
rtlsdr_close(dev);
|
|
endwin();
|
|
}
|
|
|
|
|
|
int main() {
|
|
startup_screen();
|
|
startup_checks();
|
|
start_dashboard();
|
|
|
|
return 0;
|
|
} |