diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 49ab3b0c17..a56e67c98b 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -4527,7 +4528,7 @@ static void wifi_scan_callback(retro_task_t *task, { unsigned i; file_list_t *file_list = NULL; - struct string_list *ssid_list = NULL; + wifi_network_scan_t *scan = NULL; const char *path = NULL; const char *label = NULL; @@ -4543,21 +4544,19 @@ static void wifi_scan_callback(retro_task_t *task, file_list = menu_entries_get_selection_buf_ptr(0); menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list); - ssid_list = string_list_new(); + scan = driver_wifi_get_ssids(); + if (!scan) + return; - driver_wifi_get_ssids(ssid_list); - - for (i = 0; i < ssid_list->size; i++) + for (i = 0; i < RBUF_LEN(scan->net_list); i++) { - const char *ssid = ssid_list->elems[i].data; + const char *ssid = scan->net_list[i].ssid; menu_entries_append_enum(file_list, ssid, msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_WIFI), MENU_ENUM_LABEL_CONNECT_WIFI, MENU_WIFI, 0, 0); } - - string_list_free(ssid_list); } #endif @@ -5459,17 +5458,17 @@ unsigned menu_displaylist_build_list( settings_t *settings = config_get_ptr(); if (!string_is_equal(settings->arrays.wifi_driver, "null")) { - struct string_list *ssid_list = string_list_new(); - driver_wifi_get_ssids(ssid_list); + wifi_network_scan_t *scan = driver_wifi_get_ssids(); - if (ssid_list->size == 0) + /* Temporary hack: scan periodically, until we have a submenu */ + if (!scan || RBUF_LEN(scan->net_list) == 0 || time(NULL) > scan->scan_time + 120) task_push_wifi_scan(wifi_scan_callback); else { unsigned i; - for (i = 0; i < ssid_list->size; i++) + for (i = 0; i < RBUF_LEN(scan->net_list); i++) { - const char *ssid = ssid_list->elems[i].data; + const char *ssid = scan->net_list[i].ssid; if (menu_entries_append_enum(list, ssid, msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_WIFI), diff --git a/retroarch.c b/retroarch.c index b042e381d4..44d7b25c2d 100644 --- a/retroarch.c +++ b/retroarch.c @@ -18937,10 +18937,10 @@ void driver_wifi_scan(void) p_rarch->wifi_driver->scan(p_rarch->wifi_data); } -void driver_wifi_get_ssids(struct string_list* ssids) +wifi_network_scan_t* driver_wifi_get_ssids() { struct rarch_state *p_rarch = &rarch_st; - p_rarch->wifi_driver->get_ssids(p_rarch->wifi_data, ssids); + return p_rarch->wifi_driver->get_ssids(p_rarch->wifi_data); } bool driver_wifi_ssid_is_online(unsigned i) diff --git a/wifi/drivers/connmanctl.c b/wifi/drivers/connmanctl.c index 97cb1c1daf..5bc83dcded 100644 --- a/wifi/drivers/connmanctl.c +++ b/wifi/drivers/connmanctl.c @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include #include @@ -29,9 +31,7 @@ typedef struct { - bool connman_cache[64]; - unsigned connman_counter; - struct string_list* lines; + wifi_network_scan_t scan; char command[256]; bool connmanctl_widgets_supported; } connman_t; @@ -47,6 +47,9 @@ static void *connmanctl_init(void) static void connmanctl_free(void *data) { + connman_t *connman = (connman_t*)data; + if (connman->scan.net_list) + RBUF_FREE(connman->scan.net_list); if (data) free(data); } @@ -164,15 +167,12 @@ static void connmanctl_tether_toggle( static void connmanctl_scan(void *data) { char line[512]; - union string_list_elem_attr attr; FILE *serv_file = NULL; settings_t *settings = config_get_ptr(); connman_t *connman = (connman_t*)data; - attr.i = RARCH_FILETYPE_UNSET; - if (connman->lines) - free(connman->lines); - connman->lines = string_list_new(); + if (connman->scan.net_list) + RBUF_FREE(connman->scan.net_list); if (connmanctl_tether_status(connman)) { @@ -195,74 +195,61 @@ static void connmanctl_scan(void *data) serv_file = popen("connmanctl services", "r"); while (fgets(line, 512, serv_file)) { + int i; + struct string_list* list = NULL; + wifi_network_info_t entry; size_t len = strlen(line); if (len > 0 && line[len-1] == '\n') line[--len] = '\0'; - string_list_append(connman->lines, line, attr); + /* Parse lines directly and store net info directly */ + memset(&entry, 0, sizeof(entry)); + entry.connected = (line[2] == 'R' || line[2] == 'O'); + entry.saved_password = (line[0] == '*'); + + /* connmanctl services outputs a 4 character prefixed lines, + * either whitespace or an identifier. i.e.: + * $ connmanctl services + * '*A0 SSID some_unique_id' + * ' SSID some_another_unique_id' + */ + list = string_split(&line[4], " "); + if (!list) + break; + + if (list->size == 0) + continue; + + for (i = 0; i < list->size-1; i++) + { + strlcat(entry.ssid, list->elems[i].data, sizeof(entry.ssid)-1); + strlcat(entry.ssid, " ", sizeof(entry.ssid)-1); + } + /* Store the connman network id here, for later */ + strlcpy(entry.netid, list->elems[list->size-1].data, sizeof(entry.netid)-1); + string_list_free(list); + + /* Filter only wifi nets */ + if (!strncmp(entry.netid, "wifi_", 5)) + RBUF_PUSH(connman->scan.net_list, entry); } + + connman->scan.scan_time = time(NULL); pclose(serv_file); } -static void connmanctl_get_ssids(void *data, struct string_list* ssids) +static wifi_network_scan_t* connmanctl_get_ssids(void *data) { unsigned i; - union string_list_elem_attr attr; - attr.i = RARCH_FILETYPE_UNSET; connman_t *connman = (connman_t*)data; - if (!connman->lines) - return; - - for (i = 0; i < connman->lines->size; i++) - { - char ssid[32]; - const char *line = connman->lines->elems[i].data; - - strlcpy(ssid, line+4, sizeof(ssid)); - string_list_append(ssids, ssid, attr); - } + return &connman->scan; } static bool connmanctl_ssid_is_online(void *data, unsigned i) { - char ln[512] = {0}; - char service[128] = {0}; connman_t *connman = (connman_t*)data; - const char *line = connman->lines->elems[i].data; - FILE *command_file = NULL; - - if (connman->connman_counter >= 64) - { - static struct string_list* list = NULL; - connman->connman_counter = 0; - list = string_split(line, " "); - if (!list) - return false; - - if (list->size == 0) - { - string_list_free(list); - return false; - } - - strlcpy(service, list->elems[list->size-1].data, sizeof(service)); - string_list_free(list); - - snprintf(connman->command, sizeof(connman->command), "\ - connmanctl services %s | grep 'State = \\(online\\|ready\\)'", - service); - - command_file = popen(connman->command, "r"); - connman->connman_cache[i] = (fgets(ln, 512, command_file)); - pclose(command_file); - } - else - { - connman->connman_counter++; - } - - return connman->connman_cache[i]; + return connman->scan.net_list[i].connected; } static bool connmanctl_connect_ssid( @@ -270,46 +257,19 @@ static bool connmanctl_connect_ssid( { unsigned i; char ln[512] = {0}; - char name[64] = {0}; - char service[128] = {0}; char settings_dir[PATH_MAX_LENGTH] = {0}; char settings_path[PATH_MAX_LENGTH] = {0}; FILE *command_file = NULL; FILE *settings_file = NULL; connman_t *connman = (connman_t*)data; - const char *line = connman->lines->elems[idx].data; + wifi_network_info_t *netinfo = &connman->scan.net_list[idx]; settings_t *settings = config_get_ptr(); static struct string_list* list = NULL; #ifdef HAVE_GFX_WIDGETS bool widgets_active = connman->connmanctl_widgets_supported; #endif - /* connmanctl services outputs a 4 character prefixed lines, - * either whitespace or an identifier. i.e.: - * $ connmanctl services - * '*A0 SSID some_unique_id' - * ' SSID some_another_unique_id' - */ - list = string_split(line+4, " "); - if (!list) - return false; - - if (list->size == 0) - { - string_list_free(list); - return false; - } - - for (i = 0; i < list->size-1; i++) - { - strlcat(name, list->elems[i].data, sizeof(name)); - strlcat(name, " ", sizeof(name)); - } - strlcpy(service, list->elems[list->size-1].data, sizeof(service)); - - string_list_free(list); - strlcat(settings_dir, LAKKA_CONNMAN_DIR, sizeof(settings_dir)); - strlcat(settings_dir, service, sizeof(settings_dir)); + strlcat(settings_dir, netinfo->netid, sizeof(settings_dir)); path_mkdir(settings_dir); @@ -317,12 +277,12 @@ static bool connmanctl_connect_ssid( strlcat(settings_path, "/settings", sizeof(settings_path)); settings_file = fopen(settings_path, "w"); - fprintf(settings_file, "[%s]\n", service); - fprintf(settings_file, "Name=%s\n", name); + fprintf(settings_file, "[%s]\n", netinfo->netid); + fprintf(settings_file, "Name=%s\n", netinfo->ssid); fprintf(settings_file, "SSID="); - for (i = 0; i < strlen(name); i++) - fprintf(settings_file, "%02x", (unsigned int) name[i]); + for (i = 0; i < strlen(netinfo->ssid); i++) + fprintf(settings_file, "%02x", (unsigned int) netinfo->ssid[i]); fprintf(settings_file, "\n"); fprintf(settings_file, "Favorite=%s\n", "true"); @@ -345,7 +305,7 @@ static bool connmanctl_connect_ssid( snprintf(connman->command, sizeof(connman->command), "\ connmanctl connect %s 2>&1", - service); + netinfo->netid); command_file = popen(connman->command, "r"); diff --git a/wifi/wifi_driver.h b/wifi/wifi_driver.h index da9c531b7e..11ab811fda 100644 --- a/wifi/wifi_driver.h +++ b/wifi/wifi_driver.h @@ -22,7 +22,6 @@ #include #include -#include RETRO_BEGIN_DECLS @@ -41,6 +40,21 @@ enum rarch_wifi_ctl_state RARCH_WIFI_CTL_INIT }; +typedef struct wifi_network_info +{ + char ssid[33]; + bool connected; + bool saved_password; + char netid[160]; /* Do not use, internal */ + /* TODO Add signal strength & other info */ +} wifi_network_info_t; + +typedef struct wifi_network_scan +{ + time_t scan_time; + wifi_network_info_t *net_list; /* This is an rbuf array */ +} wifi_network_scan_t; + typedef struct wifi_driver { void *(*init)(void); @@ -51,7 +65,7 @@ typedef struct wifi_driver void (*stop)(void *data); void (*scan)(void *data); - void (*get_ssids)(void *data, struct string_list *list); + wifi_network_scan_t* (*get_ssids)(void *data); bool (*ssid_is_online)(void *data, unsigned i); bool (*connect_ssid)(void *data, unsigned i, const char* passphrase); void (*tether_start_stop)(void *data, bool start, char* configfile); @@ -78,7 +92,7 @@ bool driver_wifi_start(void); void driver_wifi_scan(void); -void driver_wifi_get_ssids(struct string_list *list); +wifi_network_scan_t* driver_wifi_get_ssids(); bool driver_wifi_ssid_is_online(unsigned i);