diff --git a/.gitignore b/.gitignore index 793bb303..09614836 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/.cache /build /build_emu linux-4.9 diff --git a/mkapp/app/script/wlan_stop.sh b/mkapp/app/script/wlan_stop.sh index fa8622f7..515ed325 100755 --- a/mkapp/app/script/wlan_stop.sh +++ b/mkapp/app/script/wlan_stop.sh @@ -2,6 +2,7 @@ /mnt/app/app/record/gogglecmd -live quit sleep 1 killall rtspLive +killall wpa_supplicant killall hostapd killall udhcpd killall dropbear diff --git a/src/core/defines.h b/src/core/defines.h index d9dacbf0..d6295708 100644 --- a/src/core/defines.h +++ b/src/core/defines.h @@ -1,8 +1,8 @@ #pragma once -#define DIAL_SENSITIVITY 1 // number of clicks before dial event is triggered +#define DIAL_SENSITIVITY 1 // number of clicks before dial event is triggered #define DIAL_SENSITIVTY_TIMEOUT_MS 1000 // ms -#define CHANNEL_SHOWTIME 30 // must <= 127 +#define CHANNEL_SHOWTIME 30 // must <= 127 #define GPIO_BEEP 131 @@ -20,8 +20,9 @@ #define DEV_SPI_VRX_L "/dev/mtd9" #define DEV_SPI_VA "/dev/mtd10" -#define SELF_TEST_FILE "/mnt/extsd/self_test.txt" -#define NO_DIAL_FILE "/mnt/extsd/no_dial.txt" -#define APP_LOG_FILE "/mnt/extsd/HDZGOGGLE.log" -#define APP_BIN_FILE "/mnt/extsd/HDZGOGGLE" -#define DEVELOP_SCRIPT "/mnt/extsd/develop.sh" +#define SELF_TEST_FILE "/mnt/extsd/self_test.txt" +#define NO_DIAL_FILE "/mnt/extsd/no_dial.txt" +#define APP_LOG_FILE "/mnt/extsd/HDZGOGGLE.log" +#define APP_BIN_FILE "/mnt/extsd/HDZGOGGLE" +#define DEVELOP_SCRIPT "/mnt/extsd/develop.sh" +#define MAC_OVERRIDE_FILE "/mnt/extsd/macaddr.txt" \ No newline at end of file diff --git a/src/core/settings.c b/src/core/settings.c index 1af64c74..03118b8e 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -1,13 +1,11 @@ #include "settings.h" -#include #include #include #include #include -#include "core/self_test.h" #include "ui/page_common.h" #include "util/filesystem.h" #include "util/system.h" @@ -197,7 +195,6 @@ const setting_t g_setting_defaults = { .wifi = { .enable = false, .mode = 0, - .clientid = {""}, .ssid = {"HDZero", "MySSID"}, .passwd = {"divimath", "MyPassword"}, .dhcp = true, @@ -435,7 +432,6 @@ void settings_load(void) { // wifi g_setting.wifi.enable = settings_get_bool("wifi", "enable", g_setting_defaults.wifi.enable); g_setting.wifi.mode = ini_getl("wifi", "mode", g_setting_defaults.wifi.mode, SETTING_INI); - ini_gets("wifi", "clientid", g_setting_defaults.wifi.clientid, g_setting.wifi.clientid, WIFI_CLIENTID_MAX, SETTING_INI); ini_gets("wifi", "ap_ssid", g_setting_defaults.wifi.ssid[0], g_setting.wifi.ssid[0], WIFI_SSID_MAX, SETTING_INI); ini_gets("wifi", "ap_passwd", g_setting_defaults.wifi.passwd[0], g_setting.wifi.passwd[0], WIFI_PASSWD_MAX, SETTING_INI); ini_gets("wifi", "sta_ssid", g_setting_defaults.wifi.ssid[1], g_setting.wifi.ssid[1], WIFI_SSID_MAX, SETTING_INI); @@ -448,6 +444,7 @@ void settings_load(void) { g_setting.wifi.rf_channel = ini_getl("wifi", "rf_channel", g_setting_defaults.wifi.rf_channel, SETTING_INI); ini_gets("wifi", "root_pw", g_setting_defaults.wifi.root_pw, g_setting.wifi.root_pw, WIFI_PASSWD_MAX, SETTING_INI); g_setting.wifi.ssh = settings_get_bool("wifi", "ssh", g_setting_defaults.wifi.ssh); + ini_gets("wifi", "mac", "", g_setting.wifi.mac, 18, SETTING_INI); // no dial under video mode g_setting.ease.no_dial = fs_file_exists(NO_DIAL_FILE); @@ -466,4 +463,4 @@ void settings_load(void) { unlink(APP_LOG_FILE); g_setting.storage.logging = log_file_open(APP_LOG_FILE); } -} +} \ No newline at end of file diff --git a/src/core/settings.h b/src/core/settings.h index d978de1c..e52cd919 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -209,7 +209,6 @@ enum { typedef struct { bool enable; uint8_t mode; // 0 == WIFI_MODE_AP, 1 == WIFI_MODE_STA - char clientid[WIFI_CLIENTID_MAX]; char ssid[WIFI_MODE_COUNT][WIFI_SSID_MAX]; char passwd[WIFI_MODE_COUNT][WIFI_PASSWD_MAX]; bool dhcp; @@ -220,6 +219,7 @@ typedef struct { uint8_t rf_channel; char root_pw[WIFI_SSID_MAX]; bool ssh; + char mac[18]; } wifi_t; typedef struct { @@ -291,6 +291,8 @@ int settings_put_osd_element_pos_y(const setting_osd_goggle_element_positions_t int settings_put_osd_element_pos_x(const setting_osd_goggle_element_positions_t *pos, char *config_name); int settings_put_osd_element_shown(bool show, char *config_name); +static bool is_valid_mac_address(const char mac_address[]); + #ifdef __cplusplus } #endif diff --git a/src/ui/page_wifi.c b/src/ui/page_wifi.c index fbd48aa4..dc181d7a 100644 --- a/src/ui/page_wifi.c +++ b/src/ui/page_wifi.c @@ -1,7 +1,6 @@ #include "page_wifi.h" #include -#include #include #include #include @@ -15,8 +14,8 @@ #include "core/common.hh" #include "core/dvr.h" #include "core/settings.h" +#include "lvgl/src/core/lv_obj.h" #include "ui/page_common.h" -#include "ui/ui_attribute.h" #include "ui/ui_keyboard.h" #include "ui/ui_style.h" #include "util/filesystem.h" @@ -143,15 +142,18 @@ static void page_wifi_update_services() { if ((fp = fopen(WIFI_STA_ON, "w"))) { fprintf(fp, "#!/bin/sh\n"); fprintf(fp, "insmod /mnt/app/ko/xradio_mac.ko\n"); + fprintf(fp, "insmod /mnt/app/ko/xradio_mac.ko\n"); fprintf(fp, "insmod /mnt/app/ko/xradio_core.ko\n"); fprintf(fp, "insmod /mnt/app/ko/xradio_wlan.ko\n"); + fprintf(fp, "ifconfig wlan0 hw ether %s\n", g_setting.wifi.mac); + fprintf(fp, "ifconfig wlan0 up\n"); if (g_setting.wifi.dhcp) { fprintf(fp, "udhcpc -x hostname:%s -x 0x3d:%s -r %s -i wlan0 -b&\n", g_setting.wifi.ssid[WIFI_MODE_AP], - g_setting.wifi.clientid, + g_setting.wifi.mac, g_setting.wifi.ip_addr); } @@ -259,6 +261,50 @@ static void page_wifi_mask_password(lv_obj_t *obj, int size) { lv_label_set_text(obj, buffer); } +static bool page_wifi_is_valid_mac_address(const char mac_address[]) { + for (int i = 0; i < 17; i++) { + // first byte has to be even to be a valid MAC address for our usecase + if (i == 1 && (mac_address[i] != '0' && mac_address[i] != '2' && mac_address[i] != '4' && mac_address[i] != '6' && mac_address[i] != '8' && mac_address[i] != 'a' && mac_address[i] != 'A' && mac_address[i] != 'c' && mac_address[i] != 'C' && mac_address[i] != 'e' && mac_address[i] != 'E')) { + return false; + } + if (i % 3 == 2) { + if (mac_address[i] != ':') { + return false; + } + } else { + if (!( + mac_address[i] >= '0' && mac_address[i] <= '9' || + mac_address[i] >= 'A' && mac_address[i] <= 'F' || + mac_address[i] >= 'a' && mac_address[i] <= 'f')) { + return false; + } + } + } + return true; +} + +static void page_wifi_generate_mac_address(char *mac_address) { + srandom(time(NULL)); + sprintf(mac_address, "%02lx:%02lx:%02lx:%02lx:%02lx:%02lx", + random() & 254, // First byte must be even. + random() & 255, + random() & 255, + random() & 255, + random() & 255, + random() & 255); +} + +static void page_wifi_read_mac_file(char *mac_address) { + FILE *file = fopen(MAC_OVERRIDE_FILE, "r"); + char read_mac[18]; + if (fgets(read_mac, 18, file) != NULL) { + if (page_wifi_is_valid_mac_address(read_mac)) { + strcpy(mac_address, read_mac); + } + } + fclose(file); +} + /** * Update settings and apply them. */ @@ -278,9 +324,16 @@ static void page_wifi_update_settings() { snprintf(g_setting.wifi.root_pw, WIFI_PASSWD_MAX, "%s", page_wifi.page_3.root_pw.text); - if (0 == strlen(g_setting.wifi.clientid)) { - page_wifi_generate_clientid(g_setting.wifi.clientid, WIFI_CLIENTID_MAX); - ini_puts("wifi", "clientid", g_setting.wifi.clientid, SETTING_INI); + // Generate one random MAC if none is set or if it is invalid. + if (0 == strlen(g_setting.wifi.mac) || !page_wifi_is_valid_mac_address(g_setting.wifi.mac)) { + page_wifi_generate_mac_address(g_setting.wifi.mac); + ini_puts("wifi", "mac", g_setting.wifi.mac, SETTING_INI); + } + + // Check for override file and apply if it exists. + if (fs_file_exists(MAC_OVERRIDE_FILE)) { + page_wifi_read_mac_file(g_setting.wifi.mac); + ini_puts("wifi", "mac", g_setting.wifi.mac, SETTING_INI); } settings_put_bool("wifi", "enable", g_setting.wifi.enable); @@ -314,7 +367,7 @@ static void page_wifi_update_settings() { } /** - * Acquire the actual address in use. + * Acquire the actual IP address in use. */ static const char *page_wifi_get_real_address() { const char *address = NULL; @@ -336,7 +389,37 @@ static const char *page_wifi_get_real_address() { } /** - * Updates the all notes on every page. + * Acquire the MAC address in use. + */ +static const char *page_wifi_get_real_mac_address() { + const char *address = NULL; + int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + + if (fd >= 0) { + struct ifreq ifr; + strcpy(ifr.ifr_name, "wlan0"); + + char mac[18]; + + if (0 == ioctl(fd, SIOCGIFHWADDR, &ifr)) { + sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", + (unsigned char)ifr.ifr_addr.sa_data[0], + (unsigned char)ifr.ifr_addr.sa_data[1], + (unsigned char)ifr.ifr_addr.sa_data[2], + (unsigned char)ifr.ifr_addr.sa_data[3], + (unsigned char)ifr.ifr_addr.sa_data[4], + (unsigned char)ifr.ifr_addr.sa_data[5]); + } + address = mac; + + close(fd); + } + + return address; +} + +/** + * Updates the notes on page 1. */ static void page_wifi_update_page_1_notes() { const char *address = page_wifi_get_real_address(); @@ -361,12 +444,23 @@ static void page_wifi_update_page_1_notes() { lv_label_set_text(page_wifi.page_1.note, buffer); } +/** + * Updates the notes on page 3. + */ static void page_wifi_update_page_3_notes() { + const char *mac = page_wifi_get_real_mac_address(); + static char buffer[1024]; snprintf(buffer, sizeof(buffer), "Password Requirements:\n" - " Minimum 8 characters, maximum 64 characters.\n\n"); + " Minimum 8 characters, maximum 64 characters.\n\n" + "MAC-address:\n" + " %s\n\n" + "You can override the fixed MAC in client mode by creating the file macaddr.txt\n" + "with the new MAC inside on the SD card. Make sure there are no spaces!\n" + "Valid mac addresses start with an even byte.\n\n", + mac); lv_label_set_text(page_wifi.page_3.note, buffer); } @@ -473,8 +567,8 @@ static void page_wifi_update_current_page(int which) { lv_obj_clear_flag(page_wifi.page_2.gateway.input, LV_OBJ_FLAG_HIDDEN); if (page_wifi.page_1.mode.button.current == WIFI_MODE_AP || - (page_wifi.page_1.mode.button.current == WIFI_MODE_STA && - page_wifi.page_2.dhcp.button.current == 1)) { + (page_wifi.page_1.mode.button.current == WIFI_MODE_STA && + page_wifi.page_2.dhcp.button.current == 1)) { lv_obj_clear_state(page_wifi.page_2.netmask.label, STATE_DISABLED); lv_obj_clear_state(page_wifi.page_2.netmask.input, STATE_DISABLED); lv_obj_clear_state(page_wifi.page_2.gateway.label, STATE_DISABLED); @@ -1145,4 +1239,4 @@ void page_wifi_get_statusbar_text(char *buffer, int size) { } else { snprintf(buffer, size, "WiFi: Off"); } -} +} \ No newline at end of file