Add a proper WiFi menu, with Enable/Disable & Disconnect options

This also allows WiFi passwords to be remembered. The underlying
tool (connman) allows to store passswords (that's why it auto connects
whenever you boot a Lakka device), so we expose this so that the user
does not have to re-input the pass when connecting to a saved wifi.

Option to forget a password to come in a future PR, for now a password
is automatically forgotten if the Wifi connect operation fails (we assume
it fails due to password).

Changes the WiFi API to enable these features of course!
This commit is contained in:
David Guillen Fandos 2020-12-09 20:10:22 +01:00
parent 0bb70902a8
commit ed7b3aa415
19 changed files with 532 additions and 149 deletions

View File

@ -148,6 +148,8 @@
#define DEFAULT_PLAYLIST_ENTRY_RENAME true
#define DEFAULT_WIFI_ENABLE true
#define DEFAULT_ACCESSIBILITY_ENABLE false
#define DEFAULT_ACCESSIBILITY_NARRATOR_SPEECH_SPEED 5

View File

@ -706,6 +706,7 @@ typedef struct settings
/* WiFi */
bool wifi_allow;
bool wifi_enabled;
/* Location */
bool location_allow;

View File

@ -412,6 +412,22 @@ MSG_HASH(
MENU_ENUM_LABEL_CONNECT_WIFI,
"connect_wifi"
)
MSG_HASH(
MENU_ENUM_LABEL_WIFI_DISCONNECT,
"disconnect_wifi"
)
MSG_HASH(
MENU_ENUM_LABEL_WIFI_NETWORKS,
"wifi_list_networks"
)
MSG_HASH(
MENU_ENUM_LABEL_WIFI_ENABLED,
"wifi_enabled"
)
MSG_HASH(
MENU_ENUM_LABEL_WIFI_NETWORK_SCAN,
"wifi_network_scan"
)
MSG_HASH(
MENU_ENUM_LABEL_CONNECT_NETPLAY_ROOM,
"connect_room"
@ -1028,6 +1044,10 @@ MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST,
"deferred_wifi_settings_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST,
"deferred_wifi_networks_list"
)
MSG_HASH(
MENU_ENUM_LABEL_DEFERRED_INFORMATION,
"deferred_information"

View File

@ -11272,6 +11272,18 @@ MSG_HASH(
MSG_SCANNING_WIRELESS_NETWORKS,
"Scanning wireless networks..."
)
MSG_HASH(
MSG_ENABLING_WIRELESS,
"Enabling Wi-Fi..."
)
MSG_HASH(
MSG_DISABLING_WIRELESS,
"Disabling Wi-Fi..."
)
MSG_HASH(
MSG_DISCONNECTING_WIRELESS,
"Disconnecting Wi-Fi..."
)
MSG_HASH(
MSG_NETPLAY_LAN_SCANNING,
"Scanning for netplay hosts..."
@ -11710,6 +11722,22 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_WIFI_SETTINGS,
"Scans for wireless networks and establishes connection."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_WIFI_ENABLED,
"Enable Wi-Fi"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_WIFI_NETWORK_SCAN,
"Connect to Network"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_WIFI_NETWORKS,
"Connect to Network"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_WIFI_DISCONNECT,
"Disconnect"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_VIDEO_VFILTER,
"Deflicker"
@ -11900,6 +11928,14 @@ MSG_HASH(
MSG_WIFI_DISCONNECT_FROM,
"Disconnecting from Wi-Fi '%s'"
)
MSG_HASH(
MSG_WIFI_CONNECTING_TO,
"Connecting to Wi-Fi '%s'"
)
MSG_HASH(
MSG_WIFI_EMPTY_SSID,
"[No SSID]"
)
MSG_HASH(
MSG_LOCALAP_ALREADY_RUNNING,
"Wi-Fi Access Point is already started"

View File

@ -201,6 +201,7 @@ GENERIC_DEFERRED_PUSH(deferred_push_retro_achievements_settings_list,DISPLAYLIST
GENERIC_DEFERRED_PUSH(deferred_push_updater_settings_list, DISPLAYLIST_UPDATER_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_bluetooth_settings_list, DISPLAYLIST_BLUETOOTH_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_wifi_settings_list, DISPLAYLIST_WIFI_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_wifi_networks_list, DISPLAYLIST_WIFI_NETWORKS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_network_settings_list, DISPLAYLIST_NETWORK_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_subsystem_settings_list, DISPLAYLIST_SUBSYSTEM_SETTINGS_LIST)
GENERIC_DEFERRED_PUSH(deferred_push_network_hosting_settings_list, DISPLAYLIST_NETWORK_HOSTING_SETTINGS_LIST)
@ -714,6 +715,7 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
{MENU_ENUM_LABEL_DEFERRED_NETWORK_HOSTING_SETTINGS_LIST, deferred_push_network_hosting_settings_list},
{MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST, deferred_push_bluetooth_settings_list},
{MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST, deferred_push_wifi_settings_list},
{MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST, deferred_push_wifi_networks_list},
{MENU_ENUM_LABEL_DEFERRED_LAKKA_SERVICES_LIST, deferred_push_lakka_services_list},
{MENU_ENUM_LABEL_DEFERRED_USER_SETTINGS_LIST, deferred_push_user_settings_list},
{MENU_ENUM_LABEL_DEFERRED_DIRECTORY_SETTINGS_LIST, deferred_push_directory_settings_list},

View File

@ -16,6 +16,7 @@
*/
#include <compat/strl.h>
#include <array/rbuf.h>
#include <file/file_path.h>
#include <retro_assert.h>
#include <string/stdstring.h>
@ -383,6 +384,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
return MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST;
case ACTION_OK_DL_WIFI_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST;
case ACTION_OK_DL_WIFI_NETWORKS_LIST:
return MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST;
case ACTION_OK_DL_NETPLAY:
return MENU_ENUM_LABEL_DEFERRED_NETPLAY;
case ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST:
@ -1283,6 +1286,7 @@ int generic_action_ok_displaylist_push(const char *path,
case ACTION_OK_DL_SUBSYSTEM_SETTINGS_LIST:
case ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST:
case ACTION_OK_DL_WIFI_SETTINGS_LIST:
case ACTION_OK_DL_WIFI_NETWORKS_LIST:
case ACTION_OK_DL_NETPLAY:
case ACTION_OK_DL_NETPLAY_LAN_SCAN_SETTINGS_LIST:
case ACTION_OK_DL_LAKKA_SERVICES_LIST:
@ -2661,8 +2665,15 @@ static int action_ok_bluetooth(const char *path, const char *label,
static void menu_input_wifi_cb(void *userdata, const char *passphrase)
{
unsigned idx = menu_input_dialog_get_kb_idx();
wifi_network_scan_t *scan = driver_wifi_get_ssids();
wifi_network_info_t *netinfo = &scan->net_list[idx];
driver_wifi_connect_ssid(idx, passphrase);
if (idx < RBUF_LEN(scan->net_list) && passphrase)
{
/* Need to fill in the passphrase that we got from the user! */
strlcpy(netinfo->passphrase, passphrase, sizeof(netinfo->passphrase));
task_push_wifi_connect(NULL, netinfo);
}
menu_input_dialog_end();
}
@ -2818,6 +2829,34 @@ enum
ACTION_OK_SHADER_PRESET_REMOVE_GAME
};
static int action_ok_wifi(const char *path, const char *label_setting,
unsigned type, size_t idx, size_t entry_idx)
{
wifi_network_scan_t* scan = driver_wifi_get_ssids();
if (idx >= RBUF_LEN(scan->net_list))
return -1;
if (scan->net_list[idx].saved_password)
{
/* No need to ask for a password, should be stored */
task_push_wifi_connect(NULL, &scan->net_list[idx]);
return 0;
}
else
{
/* Show password input dialog */
menu_input_ctx_line_t line;
line.label = "Passphrase";
line.label_setting = label_setting;
line.type = type;
line.idx = (unsigned)idx;
line.cb = menu_input_wifi_cb;
if (!menu_input_dialog_start(&line))
return -1;
return 0;
}
}
static int generic_action_ok_shader_preset_remove(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx,
unsigned action_type)
@ -3051,10 +3090,6 @@ DEFAULT_ACTION_DIALOG_START(action_ok_enable_settings,
msg_hash_to_str(MSG_INPUT_ENABLE_SETTINGS_PASSWORD),
(unsigned)entry_idx,
menu_input_st_string_cb_enable_settings)
DEFAULT_ACTION_DIALOG_START(action_ok_wifi,
"Passphrase",
(unsigned)idx,
menu_input_wifi_cb)
#ifdef HAVE_CHEATS
DEFAULT_ACTION_DIALOG_START(action_ok_cheat_file_save_as,
msg_hash_to_str(MSG_INPUT_CHEAT_FILENAME),
@ -5228,6 +5263,7 @@ DEFAULT_ACTION_OK_FUNC(action_ok_subsystem_list, ACTION_OK_DL_SUBSYSTEM_SETTINGS
DEFAULT_ACTION_OK_FUNC(action_ok_database_manager_list, ACTION_OK_DL_DATABASE_MANAGER_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_bluetooth_list, ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_wifi_list, ACTION_OK_DL_WIFI_SETTINGS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_wifi_networks_list, ACTION_OK_DL_WIFI_NETWORKS_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_cursor_manager_list, ACTION_OK_DL_CURSOR_MANAGER_LIST)
DEFAULT_ACTION_OK_FUNC(action_ok_compressed_archive_push, ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH)
DEFAULT_ACTION_OK_FUNC(action_ok_compressed_archive_push_detect_core, ACTION_OK_DL_COMPRESSED_ARCHIVE_PUSH_DETECT_CORE)
@ -5378,6 +5414,22 @@ static int action_ok_shader_pass(const char *path,
}
#endif
static void wifi_menu_refresh_callback(retro_task_t *task,
void *task_data,
void *user_data, const char *error)
{
bool refresh = false;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
static int action_ok_wifi_disconnect(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
task_push_wifi_disconnect(wifi_menu_refresh_callback);
return true;
}
static int action_ok_netplay_connect_room(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
@ -7445,6 +7497,8 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_UPDATER_SETTINGS, action_ok_updater_list},
{MENU_ENUM_LABEL_BLUETOOTH_SETTINGS, action_ok_bluetooth_list},
{MENU_ENUM_LABEL_WIFI_SETTINGS, action_ok_wifi_list},
{MENU_ENUM_LABEL_WIFI_NETWORK_SCAN, action_ok_wifi_networks_list},
{MENU_ENUM_LABEL_WIFI_DISCONNECT, action_ok_wifi_disconnect},
{MENU_ENUM_LABEL_NETWORK_HOSTING_SETTINGS, action_ok_network_hosting_list},
{MENU_ENUM_LABEL_SUBSYSTEM_SETTINGS, action_ok_subsystem_list},
{MENU_ENUM_LABEL_NETWORK_SETTINGS, action_ok_network_list},

View File

@ -566,6 +566,7 @@ DEFAULT_TITLE_MACRO(action_get_menu_sounds_list, MENU_ENUM_LABEL_
DEFAULT_TITLE_MACRO(action_get_menu_file_browser_settings_list, MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_retro_achievements_settings_list,MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_bluetooth_settings_list, MENU_ENUM_LABEL_VALUE_BLUETOOTH_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_wifi_networks_list, MENU_ENUM_LABEL_VALUE_WIFI_NETWORKS)
DEFAULT_TITLE_MACRO(action_get_wifi_settings_list, MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_network_hosting_settings_list, MENU_ENUM_LABEL_VALUE_NETWORK_HOSTING_SETTINGS)
DEFAULT_TITLE_MACRO(action_get_subsystem_settings_list, MENU_ENUM_LABEL_VALUE_SUBSYSTEM_SETTINGS)
@ -883,6 +884,7 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
{MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST, action_get_menu_file_browser_settings_list},
{MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST, action_get_retro_achievements_settings_list},
{MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST, action_get_bluetooth_settings_list},
{MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST, action_get_wifi_networks_list},
{MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST, action_get_wifi_settings_list},
{MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST, action_get_updater_settings_list},
{MENU_ENUM_LABEL_DEFERRED_NETWORK_HOSTING_SETTINGS_LIST, action_get_network_hosting_settings_list},

View File

@ -181,6 +181,7 @@ enum
ACTION_OK_DL_UPDATER_SETTINGS_LIST,
ACTION_OK_DL_BLUETOOTH_SETTINGS_LIST,
ACTION_OK_DL_WIFI_SETTINGS_LIST,
ACTION_OK_DL_WIFI_NETWORKS_LIST,
ACTION_OK_DL_NETWORK_SETTINGS_LIST,
ACTION_OK_DL_SUBSYSTEM_SETTINGS_LIST,
ACTION_OK_DL_NETWORK_HOSTING_SETTINGS_LIST,

View File

@ -4526,37 +4526,9 @@ static void wifi_scan_callback(retro_task_t *task,
void *task_data,
void *user_data, const char *error)
{
unsigned i;
file_list_t *file_list = NULL;
wifi_network_scan_t *scan = NULL;
const char *path = NULL;
const char *label = NULL;
unsigned menu_type = 0;
menu_entries_get_last_stack(&path, &label, &menu_type, NULL, NULL);
/* Don't push the results if we left the wifi menu */
if (!string_is_equal(label,
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST)))
return;
file_list = menu_entries_get_selection_buf_ptr(0);
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, file_list);
scan = driver_wifi_get_ssids();
if (!scan)
return;
for (i = 0; i < RBUF_LEN(scan->net_list); i++)
{
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);
}
bool refresh = false;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
}
#endif
@ -5453,6 +5425,43 @@ unsigned menu_displaylist_build_list(
#endif
break;
case DISPLAYLIST_WIFI_SETTINGS_LIST:
{
settings_t *settings = config_get_ptr();
bool wifi_enabled = settings->bools.wifi_enabled;
bool connected = driver_wifi_connection_info(NULL);
menu_displaylist_build_info_selective_t build_list[] = {
{MENU_ENUM_LABEL_WIFI_ENABLED, PARSE_ONLY_BOOL, true},
{MENU_ENUM_LABEL_WIFI_NETWORK_SCAN, PARSE_ACTION, false},
{MENU_ENUM_LABEL_WIFI_DISCONNECT, PARSE_ACTION, false},
};
for (i = 0; i < ARRAY_SIZE(build_list); i++)
{
switch (build_list[i].enum_idx)
{
case MENU_ENUM_LABEL_WIFI_NETWORK_SCAN:
build_list[i].checked = wifi_enabled;
break;
case MENU_ENUM_LABEL_WIFI_DISCONNECT:
build_list[i].checked = wifi_enabled && connected;
break;
default:
break;
}
}
for (i = 0; i < ARRAY_SIZE(build_list); i++)
{
if (build_list[i].checked &&
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(list,
build_list[i].enum_idx, build_list[i].parse_type,
false) == 0)
count++;
}
}
break;
case DISPLAYLIST_WIFI_NETWORKS_LIST:
#ifdef HAVE_NETWORKING
{
settings_t *settings = config_get_ptr();
@ -5461,7 +5470,7 @@ unsigned menu_displaylist_build_list(
wifi_network_scan_t *scan = driver_wifi_get_ssids();
/* Temporary hack: scan periodically, until we have a submenu */
if (!scan || RBUF_LEN(scan->net_list) == 0 || time(NULL) > scan->scan_time + 120)
if (!scan || time(NULL) > scan->scan_time + 30)
task_push_wifi_scan(wifi_scan_callback);
else
{
@ -5470,7 +5479,7 @@ unsigned menu_displaylist_build_list(
{
const char *ssid = scan->net_list[i].ssid;
if (menu_entries_append_enum(list,
ssid,
strlen(ssid) ? ssid : msg_hash_to_str(MSG_WIFI_EMPTY_SSID),
msg_hash_to_str(MENU_ENUM_LABEL_CONNECT_WIFI),
MENU_ENUM_LABEL_CONNECT_WIFI,
MENU_WIFI, 0, 0))
@ -11099,6 +11108,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
case DISPLAYLIST_SYSTEM_INFO:
case DISPLAYLIST_BLUETOOTH_SETTINGS_LIST:
case DISPLAYLIST_WIFI_SETTINGS_LIST:
case DISPLAYLIST_WIFI_NETWORKS_LIST:
case DISPLAYLIST_AUDIO_MIXER_SETTINGS_LIST:
case DISPLAYLIST_BROWSE_URL_START:
case DISPLAYLIST_CONTENT_SETTINGS:
@ -11159,7 +11169,7 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type,
MENU_ENUM_LABEL_NO_BT_DEVICES_FOUND,
0, 0, 0);
break;
case DISPLAYLIST_WIFI_SETTINGS_LIST:
case DISPLAYLIST_WIFI_NETWORKS_LIST:
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_NETWORKS_FOUND),
msg_hash_to_str(MENU_ENUM_LABEL_NO_NETWORKS_FOUND),

View File

@ -242,7 +242,8 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_MANUAL_CONTENT_SCAN_DAT_FILES,
DISPLAYLIST_CORE_RESTORE_BACKUP_LIST,
DISPLAYLIST_CORE_DELETE_BACKUP_LIST,
DISPLAYLIST_PENDING_CLEAR
DISPLAYLIST_PENDING_CLEAR,
DISPLAYLIST_WIFI_NETWORKS_LIST,
};
enum filebrowser_enums

View File

@ -127,6 +127,7 @@ enum menu_settings_type
MENU_SETTING_PLAYLIST_MANAGER_SORT_MODE,
MENU_BLUETOOTH,
MENU_WIFI,
MENU_WIFI_DISCONNECT,
MENU_ROOM,
MENU_ROOM_LAN,
MENU_ROOM_RELAY,

View File

@ -284,6 +284,7 @@ enum settings_list_type
SETTINGS_LIST_ACCESSIBILITY,
SETTINGS_LIST_USER_INTERFACE,
SETTINGS_LIST_POWER_MANAGEMENT,
SETTINGS_LIST_WIFI_MANAGEMENT,
SETTINGS_LIST_MENU_SOUNDS,
SETTINGS_LIST_PLAYLIST,
SETTINGS_LIST_CHEEVOS,
@ -7492,6 +7493,12 @@ static void general_write_handler(rarch_setting_t *setting)
*setting->value.target.unsigned_integer);
}
break;
case MENU_ENUM_LABEL_WIFI_ENABLED:
if (*setting->value.target.boolean)
task_push_wifi_enable(NULL);
else
task_push_wifi_disable(NULL);
break;
default:
break;
}
@ -15781,6 +15788,51 @@ static bool setting_append_list(
SD_FLAG_CMD_APPLY_AUTO);
#endif
END_SUB_GROUP(list, list_info, parent_group);
END_GROUP(list, list_info, parent_group);
break;
case SETTINGS_LIST_WIFI_MANAGEMENT:
START_GROUP(list, list_info, &group_info,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS),
parent_group);
parent_group = msg_hash_to_str(MENU_ENUM_LABEL_WIFI_SETTINGS);
START_SUB_GROUP(list, list_info, "State", &group_info, &subgroup_info, parent_group);
CONFIG_BOOL(
list, list_info,
&settings->bools.wifi_enabled,
MENU_ENUM_LABEL_WIFI_ENABLED,
MENU_ENUM_LABEL_VALUE_WIFI_ENABLED,
DEFAULT_WIFI_ENABLE,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE);
(*list)[list_info->index - 1].action_ok = &setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_left = &setting_bool_action_left_with_refresh;
(*list)[list_info->index - 1].action_right = &setting_bool_action_right_with_refresh;
CONFIG_ACTION(
list, list_info,
MENU_ENUM_LABEL_WIFI_NETWORK_SCAN,
MENU_ENUM_LABEL_VALUE_WIFI_NETWORK_SCAN,
&group_info,
&subgroup_info,
parent_group);
CONFIG_ACTION(
list, list_info,
MENU_ENUM_LABEL_WIFI_DISCONNECT,
MENU_ENUM_LABEL_VALUE_WIFI_DISCONNECT,
&group_info,
&subgroup_info,
parent_group);
END_SUB_GROUP(list, list_info, parent_group);
END_GROUP(list, list_info, parent_group);
break;
@ -19001,6 +19053,7 @@ static rarch_setting_t *menu_setting_new_internal(rarch_setting_info_t *list_inf
SETTINGS_LIST_ACCESSIBILITY,
SETTINGS_LIST_USER_INTERFACE,
SETTINGS_LIST_POWER_MANAGEMENT,
SETTINGS_LIST_WIFI_MANAGEMENT,
SETTINGS_LIST_MENU_SOUNDS,
SETTINGS_LIST_PLAYLIST,
SETTINGS_LIST_CHEEVOS,

View File

@ -376,8 +376,13 @@ enum msg_hash_enums
MSG_PRESS_AGAIN_TO_QUIT,
MSG_BLUETOOTH_SCAN_COMPLETE,
MSG_WIFI_SCAN_COMPLETE,
MSG_WIFI_CONNECTING_TO,
MSG_WIFI_EMPTY_SSID,
MSG_SCANNING_BLUETOOTH_DEVICES,
MSG_SCANNING_WIRELESS_NETWORKS,
MSG_ENABLING_WIRELESS,
MSG_DISABLING_WIRELESS,
MSG_DISCONNECTING_WIRELESS,
MSG_FAILED_TO_TAKE_SCREENSHOT,
MSG_CUSTOM_TIMING_GIVEN,
MSG_SAVING_STATE,
@ -1308,6 +1313,7 @@ enum msg_hash_enums
MENU_LABEL(UPDATER_SETTINGS),
MENU_LABEL(BLUETOOTH_SETTINGS),
MENU_LABEL(WIFI_SETTINGS),
MENU_LABEL(WIFI_NETWORKS),
MENU_LABEL(USER_SETTINGS),
MENU_LABEL(DIRECTORY_SETTINGS),
MENU_LABEL(PRIVACY_SETTINGS),
@ -1316,6 +1322,9 @@ enum msg_hash_enums
MENU_LABEL(NETWORK_HOSTING_SETTINGS),
MENU_LABEL(NETWORK_SETTINGS),
MENU_LABEL(NETPLAY_LAN_SCAN_SETTINGS),
MENU_LABEL(WIFI_ENABLED),
MENU_LABEL(WIFI_NETWORK_SCAN),
MENU_LABEL(WIFI_DISCONNECT),
MENU_ENUM_LABEL_CONNECT_BLUETOOTH,
MENU_ENUM_LABEL_CONNECT_WIFI,
@ -1485,6 +1494,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_BLUETOOTH_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_WIFI_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_WIFI_NETWORKS_LIST,
MENU_ENUM_LABEL_DEFERRED_SUBSYSTEM_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_NETWORK_HOSTING_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_NETWORK_SETTINGS_LIST,

View File

@ -18937,6 +18937,18 @@ void driver_wifi_scan(void)
p_rarch->wifi_driver->scan(p_rarch->wifi_data);
}
bool driver_wifi_enable(bool enabled)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->wifi_driver->enable(p_rarch->wifi_data, enabled);
}
bool driver_wifi_connection_info(wifi_network_info_t *netinfo)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->wifi_driver->connection_info(p_rarch->wifi_data, netinfo);
}
wifi_network_scan_t* driver_wifi_get_ssids()
{
struct rarch_state *p_rarch = &rarch_st;
@ -18949,10 +18961,16 @@ bool driver_wifi_ssid_is_online(unsigned i)
return p_rarch->wifi_driver->ssid_is_online(p_rarch->wifi_data, i);
}
bool driver_wifi_connect_ssid(unsigned i, const char* passphrase)
bool driver_wifi_connect_ssid(const wifi_network_info_t* net)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->wifi_driver->connect_ssid(p_rarch->wifi_data, i, passphrase);
return p_rarch->wifi_driver->connect_ssid(p_rarch->wifi_data, net);
}
bool driver_wifi_disconnect_ssid(const wifi_network_info_t* net)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->wifi_driver->disconnect_ssid(p_rarch->wifi_data, net);
}
void driver_wifi_tether_start_stop(bool start, char* configfile)
@ -19041,13 +19059,6 @@ bool wifi_driver_ctl(enum rarch_wifi_ctl_state state, void *data)
return p_rarch->wifi_driver->start(p_rarch->wifi_data);
}
return false;
case RARCH_WIFI_CTL_SET_CB:
{
/*struct retro_wifi_callback *cb =
(struct retro_wifi_callback*)data;
wifi_cb = *cb;*/
}
break;
case RARCH_WIFI_CTL_INIT:
/* Resource leaks will follow if wifi is initialized twice. */
if (p_rarch->wifi_data)
@ -19059,17 +19070,18 @@ bool wifi_driver_ctl(enum rarch_wifi_ctl_state state, void *data)
{
p_rarch->wifi_data = p_rarch->wifi_driver->init();
if (!p_rarch->wifi_data)
if (p_rarch->wifi_data)
{
p_rarch->wifi_driver->enable(p_rarch->wifi_data,
settings->bools.wifi_enabled);
}
else
{
RARCH_ERR("Failed to initialize wifi driver. Will continue without wifi.\n");
wifi_driver_ctl(RARCH_WIFI_CTL_UNSET_ACTIVE, NULL);
}
}
#if 0
if (wifi_cb.initialized)
wifi_cb.initialized();
#endif
break;
default:
break;

View File

@ -688,10 +688,13 @@ static wifi_driver_t wifi_null = {
NULL, /* free */
NULL, /* start */
NULL, /* stop */
NULL, /* enable */
NULL, /* connection_info */
NULL, /* scan */
NULL, /* get_ssids */
NULL, /* ssid_is_online */
NULL, /* connect_ssid */
NULL, /* disconnect_ssid */
NULL, /* tether_start_stop */
"null",
};

View File

@ -26,6 +26,22 @@
#include "../verbosity.h"
#include "../wifi/wifi_driver.h"
#define FUNC_PUSH_TASK(funcname, handlerfunc, message) \
bool funcname(retro_task_callback_t cb) \
{ \
retro_task_t *task = task_init(); \
if (!task) \
return false; \
task->type = TASK_TYPE_BLOCKING; \
task->state = NULL; \
task->handler = handlerfunc; \
task->callback = cb; \
task->title = strdup(msg_hash_to_str( \
message)); \
task_queue_push(task); \
return true; \
}
static void task_wifi_scan_handler(retro_task_t *task)
{
driver_wifi_scan();
@ -36,23 +52,64 @@ static void task_wifi_scan_handler(retro_task_t *task)
task_set_finished(task, true);
}
bool task_push_wifi_scan(retro_task_callback_t cb)
static void task_wifi_enable_handler(retro_task_t *task)
{
retro_task_t *task = task_init();
driver_wifi_enable(true);
task_set_progress(task, 100);
task_set_finished(task, true);
}
static void task_wifi_disable_handler(retro_task_t *task)
{
driver_wifi_enable(false);
task_set_progress(task, 100);
task_set_finished(task, true);
}
static void task_wifi_disconnect_handler(retro_task_t *task)
{
wifi_network_info_t netinfo;
if (driver_wifi_connection_info(&netinfo))
driver_wifi_disconnect_ssid(&netinfo);
task_set_progress(task, 100);
task_set_finished(task, true);
}
static void task_wifi_connect_handler(retro_task_t *task)
{
driver_wifi_connect_ssid(task->user_data);
task_set_progress(task, 100);
task_set_finished(task, true);
}
bool task_push_wifi_connect(retro_task_callback_t cb, void *netptr) {
char msg[128];
retro_task_t *task = task_init();
wifi_network_info_t *netinfo = (wifi_network_info_t*)netptr;
if (!task)
return false;
snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_WIFI_CONNECTING_TO), netinfo->ssid);
/* blocking means no other task can run while this one is running,
* which is the default */
task->type = TASK_TYPE_BLOCKING;
task->state = NULL;
task->handler = task_wifi_scan_handler;
task->handler = task_wifi_connect_handler;
task->callback = cb;
task->title = strdup(msg_hash_to_str(
MSG_SCANNING_WIRELESS_NETWORKS));
task->title = strdup(msg);
task->user_data = malloc(sizeof(*netinfo));
memcpy(task->user_data, netinfo, sizeof(*netinfo));
task_queue_push(task);
return true;
}
FUNC_PUSH_TASK(task_push_wifi_scan, task_wifi_scan_handler, MSG_SCANNING_WIRELESS_NETWORKS)
FUNC_PUSH_TASK(task_push_wifi_enable, task_wifi_enable_handler, MSG_ENABLING_WIRELESS)
FUNC_PUSH_TASK(task_push_wifi_disable, task_wifi_disable_handler, MSG_DISABLING_WIRELESS)
FUNC_PUSH_TASK(task_push_wifi_disconnect, task_wifi_disconnect_handler, MSG_DISCONNECTING_WIRELESS)

View File

@ -74,6 +74,10 @@ task_retriever_info_t *http_task_get_transfer_list(void);
bool task_push_bluetooth_scan(retro_task_callback_t cb);
bool task_push_wifi_scan(retro_task_callback_t cb);
bool task_push_wifi_enable(retro_task_callback_t cb);
bool task_push_wifi_disable(retro_task_callback_t cb);
bool task_push_wifi_disconnect(retro_task_callback_t cb);
bool task_push_wifi_connect(retro_task_callback_t cb, void*);
bool task_push_netplay_lan_scan(retro_task_callback_t cb);

View File

@ -21,7 +21,7 @@
#include <retro_miscellaneous.h>
#include <configuration.h>
#include <verbosity.h>
#include <time.h>
#include "../wifi_driver.h"
#include "../../retroarch.h"
#include "../../lakka.h"
@ -32,7 +32,7 @@
typedef struct
{
wifi_network_scan_t scan;
char command[256];
char command[300];
bool connmanctl_widgets_supported;
} connman_t;
@ -65,6 +65,74 @@ static void connmanctl_stop(void *data)
(void)data;
}
static void connmanctl_refresh_services(connman_t *connman) {
char line[512];
FILE *serv_file = popen("connmanctl services", "r");
if (connman->scan.net_list)
RBUF_FREE(connman->scan.net_list);
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';
/* 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));
strlcat(entry.ssid, " ", sizeof(entry.ssid)-1);
}
if (strlen(entry.ssid))
entry.ssid[strlen(entry.ssid)-1] = 0;
/* Store the connman network id here, for later */
strlcpy(entry.netid, list->elems[list->size-1].data, sizeof(entry.netid));
string_list_free(list);
/* Filter only wifi nets */
if (!strncmp(entry.netid, "wifi_", 5))
RBUF_PUSH(connman->scan.net_list, entry);
}
pclose(serv_file);
}
static bool connmanctl_enable(void *data, bool enabled)
{
connman_t *connman = (connman_t*)data;
if (enabled)
pclose(popen("connmanctl enable wifi", "r"));
else
pclose(popen("connmanctl disable wifi", "r"));
/* Update the services, to ensure we properly show connection status */
connmanctl_refresh_services(connman);
return true;
}
static bool connmanctl_tether_status(connman_t *connman)
{
/* Returns true if the tethering is active
@ -166,14 +234,9 @@ static void connmanctl_tether_toggle(
static void connmanctl_scan(void *data)
{
char line[512];
FILE *serv_file = NULL;
settings_t *settings = config_get_ptr();
connman_t *connman = (connman_t*)data;
if (connman->scan.net_list)
RBUF_FREE(connman->scan.net_list);
if (connmanctl_tether_status(connman))
{
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_SWITCHING_OFF),
@ -184,58 +247,15 @@ static void connmanctl_scan(void *data)
connmanctl_tether_toggle(connman, false, "", "");
}
pclose(popen("connmanctl enable wifi", "r"));
pclose(popen("connmanctl scan wifi", "r"));
runloop_msg_queue_push(msg_hash_to_str(MSG_WIFI_SCAN_COMPLETE),
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
MESSAGE_QUEUE_CATEGORY_INFO);
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';
/* 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);
}
/* Refresh now the services, to read the discovered networks */
connman->scan.scan_time = time(NULL);
pclose(serv_file);
connmanctl_refresh_services(connman);
}
static wifi_network_scan_t* connmanctl_get_ssids(void *data)
@ -249,47 +269,108 @@ static wifi_network_scan_t* connmanctl_get_ssids(void *data)
static bool connmanctl_ssid_is_online(void *data, unsigned i)
{
connman_t *connman = (connman_t*)data;
if (!connman->scan.net_list || i >= RBUF_LEN(connman->scan.net_list))
return false;
return connman->scan.net_list[i].connected;
}
static bool connmanctl_connection_info(void *data, wifi_network_info_t *netinfo)
{
connman_t *connman = (connman_t*)data;
unsigned i;
if (!connman->scan.net_list)
return false;
for (i = 0; i < RBUF_LEN(connman->scan.net_list); i++)
{
if (connman->scan.net_list[i].connected)
{
if (netinfo)
memcpy(netinfo, &connman->scan.net_list[i], sizeof(*netinfo));
return true;
}
}
return false;
}
static bool connmanctl_disconnect_ssid(void *data, const wifi_network_info_t* netinfo)
{
connman_t *connman = (connman_t*)data;
/* TODO:Check whether this network is actually connected */
snprintf(connman->command, sizeof(connman->command),
"connmanctl disconnect %s 2>&1",
netinfo->netid);
pclose(popen(connman->command, "r"));
/* Refresh the state since it has definitely changed */
connmanctl_refresh_services(connman);
return true;
}
static bool connmanctl_connect_ssid(
void *data, unsigned idx, const char* passphrase)
void *data, const wifi_network_info_t *netinfo)
{
unsigned i;
char ln[512] = {0};
bool success = false;
char settings_dir[PATH_MAX_LENGTH] = {0};
char settings_path[PATH_MAX_LENGTH] = {0};
FILE *command_file = NULL;
char netid[160] = {0};
FILE *settings_file = NULL;
connman_t *connman = (connman_t*)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
strlcat(netid, netinfo->netid, sizeof(netid));
strlcat(settings_dir, LAKKA_CONNMAN_DIR, sizeof(settings_dir));
strlcat(settings_dir, netinfo->netid, sizeof(settings_dir));
strlcat(settings_dir, netid, sizeof(settings_dir));
path_mkdir(settings_dir);
strlcat(settings_path, settings_dir, sizeof(settings_path));
strlcat(settings_path, "/settings", sizeof(settings_path));
settings_file = fopen(settings_path, "w");
fprintf(settings_file, "[%s]\n", netinfo->netid);
fprintf(settings_file, "Name=%s\n", netinfo->ssid);
fprintf(settings_file, "SSID=");
if (!netinfo->saved_password)
{
settings_file = fopen(settings_path, "w");
if (!settings_file)
return false;
fprintf(settings_file, "[%s]\n", netid);
fprintf(settings_file, "Name=%s\n", netinfo->ssid);
fprintf(settings_file, "SSID=");
for (i = 0; i < strlen(netinfo->ssid); i++)
fprintf(settings_file, "%02x", (unsigned int) netinfo->ssid[i]);
fprintf(settings_file, "\n");
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");
fprintf(settings_file, "AutoConnect=%s\n", "true");
fprintf(settings_file, "Passphrase=%s\n", passphrase);
fprintf(settings_file, "IPv4.method=%s\n", "dhcp");
fclose(settings_file);
fprintf(settings_file, "Favorite=%s\n", "true");
fprintf(settings_file, "AutoConnect=%s\n", "true");
fprintf(settings_file, "Passphrase=%s\n", netinfo->passphrase);
fprintf(settings_file, "IPv4.method=%s\n", "dhcp");
fclose(settings_file);
/* connman does not pick this up automatically, so hack: */
system("systemctl restart connman.service");
}
else
{
/* No need for pass, config should be there already, verify it */
settings_file = fopen(settings_path, "r");
if (!settings_file)
{
/* Usually a mismatch between connman state and config, reload */
system("systemctl restart connman.service");
return false;
}
fclose(settings_file);
}
if (connmanctl_tether_status(connman))
{
@ -301,26 +382,46 @@ static bool connmanctl_connect_ssid(
connmanctl_tether_toggle(connman, false, "", "");
}
pclose(popen("systemctl restart connman", "r"));
snprintf(connman->command, sizeof(connman->command), "\
connmanctl connect %s 2>&1",
snprintf(connman->command, sizeof(connman->command),
"connmanctl connect %s",
netinfo->netid);
command_file = popen(connman->command, "r");
pclose(popen(connman->command, "r"));
while (fgets(ln, sizeof(ln), command_file))
/* Refresh status to reflect the updated state */
connmanctl_refresh_services(connman);
/* connman is a PITA, return code is not meaningful at all :( */
for (i = 0; i < RBUF_LEN(connman->scan.net_list); i++)
{
if (!strcmp(netid, connman->scan.net_list[i].netid))
{
/* Found it! Check if we are connected now */
success = connman->scan.net_list[i].connected;
if (!success)
{
/* TODO: Add forget password option, which gets rid of this hack */
connman->scan.net_list[i].saved_password = false;
unlink(settings_path);
}
}
}
#ifdef HAVE_GFX_WIDGETS
if (!widgets_active)
if (!widgets_active)
#endif
runloop_msg_queue_push(ln, 1, 180, true,
{
if (success)
runloop_msg_queue_push("Connected", 1, 180, true,
NULL, MESSAGE_QUEUE_ICON_DEFAULT,
MESSAGE_QUEUE_CATEGORY_INFO);
else
runloop_msg_queue_push("Connection failed!", 1, 180, true,
NULL, MESSAGE_QUEUE_ICON_DEFAULT,
MESSAGE_QUEUE_CATEGORY_INFO);
}
pclose(command_file);
return true;
return success;
}
static void connmanctl_get_connected_ssid(
@ -339,11 +440,11 @@ static void connmanctl_get_connected_ssid(
* only 'wifi_' services, then greps the one with
* 'R' (Ready) or 'O' (Online) flag and cuts out the ssid
*/
snprintf(connman->command, sizeof(connman->command), "\
connmanctl services | \
grep wifi_ | \
grep \"^..\\(R\\|O\\)\" | \
cut -d' ' -f 2");
snprintf(connman->command, sizeof(connman->command),
"connmanctl services | "
"grep wifi_ | "
"grep \"^..\\(R\\|O\\)\" | "
"cut -d' ' -f 2");
command_file = popen(connman->command, "r");
@ -687,10 +788,13 @@ wifi_driver_t wifi_connmanctl = {
connmanctl_free,
connmanctl_start,
connmanctl_stop,
connmanctl_enable,
connmanctl_connection_info,
connmanctl_scan,
connmanctl_get_ssids,
connmanctl_ssid_is_online,
connmanctl_connect_ssid,
connmanctl_disconnect_ssid,
connmanctl_tether_start_stop,
"connmanctl",
};

View File

@ -43,6 +43,7 @@ enum rarch_wifi_ctl_state
typedef struct wifi_network_info
{
char ssid[33];
char passphrase[33];
bool connected;
bool saved_password;
char netid[160]; /* Do not use, internal */
@ -64,10 +65,13 @@ typedef struct wifi_driver
bool (*start)(void *data);
void (*stop)(void *data);
bool (*enable)(void *data, bool enabled);
bool (*connection_info)(void *data, wifi_network_info_t *ssid);
void (*scan)(void *data);
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);
bool (*connect_ssid)(void *data, const wifi_network_info_t *netinfo);
bool (*disconnect_ssid)(void *data, const wifi_network_info_t *netinfo);
void (*tether_start_stop)(void *data, bool start, char* configfile);
const char *ident;
@ -90,13 +94,19 @@ void driver_wifi_stop(void);
bool driver_wifi_start(void);
bool driver_wifi_enable(bool);
bool driver_wifi_connection_info(wifi_network_info_t *network);
void driver_wifi_scan(void);
wifi_network_scan_t* driver_wifi_get_ssids();
bool driver_wifi_ssid_is_online(unsigned i);
bool driver_wifi_connect_ssid(unsigned i, const char* passphrase);
bool driver_wifi_connect_ssid(const wifi_network_info_t *netinfo);
bool driver_wifi_disconnect_ssid(const wifi_network_info_t* netinfo);
void driver_wifi_tether_start_stop(bool start, char* configfile);