mirror of
https://github.com/libretro/RetroArch
synced 2024-12-29 12:31:05 +00:00
803 lines
23 KiB
C
803 lines
23 KiB
C
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2014-2017 - Jean-André Santoni
|
|
*
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <compat/strl.h>
|
|
#include <file/file_path.h>
|
|
#include <array/rbuf.h>
|
|
#include <lists/string_list.h>
|
|
#include <string/stdstring.h>
|
|
#include <retro_miscellaneous.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "../wifi_driver.h"
|
|
|
|
#include "../../configuration.h"
|
|
#include "../../retroarch.h"
|
|
#include "../../verbosity.h"
|
|
#include "../../lakka.h"
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
#include "../../gfx/gfx_widgets.h"
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
wifi_network_scan_t scan;
|
|
char command[300];
|
|
bool connmanctl_widgets_supported;
|
|
} connman_t;
|
|
|
|
static void *connmanctl_init(void)
|
|
{
|
|
connman_t *connman = (connman_t*)calloc(1, sizeof(connman_t));
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
connman->connmanctl_widgets_supported = gfx_widgets_ready();
|
|
#endif
|
|
return connman;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
static bool connmanctl_start(void *data)
|
|
{
|
|
(void)data;
|
|
return true;
|
|
}
|
|
|
|
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;
|
|
size_t ssid_len;
|
|
wifi_network_info_t entry;
|
|
struct string_list* list = NULL;
|
|
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'
|
|
*/
|
|
if (!(list = string_split(&line[4], " ")))
|
|
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 ((ssid_len = strlen(entry.ssid)) > 0)
|
|
entry.ssid[ssid_len - 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
|
|
* false when tethering is not active
|
|
*/
|
|
size_t ln_size;
|
|
FILE *command_file = NULL;
|
|
char ln[3] = {0};
|
|
|
|
/* Following command lists 'technologies' of connman,
|
|
* greps the wifi + 10 following lines, then first
|
|
* occurance of 'Tethering', then 'True' and counts
|
|
* the matching lines.
|
|
* Expected result is either 1 (active) or 0 (not active)
|
|
*/
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
connmanctl technologies | \
|
|
grep \"/net/connman/technology/wifi\" -A 10 | \
|
|
grep \"^ Tethering =\" -m 1 | \
|
|
grep \"True\" | \
|
|
wc -l");
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
fgets(ln, sizeof(ln), command_file);
|
|
|
|
ln_size = strlen(ln) - 1;
|
|
if (ln[ln_size] == '\n')
|
|
ln[ln_size] = '\0';
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether Status: command: \"%s\", output: \"%s\"\n",
|
|
connman->command, ln);
|
|
|
|
pclose(command_file);
|
|
|
|
if (!ln)
|
|
return false;
|
|
if (ln[0] == '0')
|
|
return false;
|
|
if (ln[0] == '1')
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static void connmanctl_tether_toggle(
|
|
connman_t *connman, bool switch_on, char* ap_name, char *pass_key)
|
|
{
|
|
/* Starts / stops the tethering service on wi-fi device */
|
|
char output[256] = {0};
|
|
FILE *command_file = NULL;
|
|
settings_t *settings = config_get_ptr();
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
bool widgets_active = connman->connmanctl_widgets_supported;
|
|
#endif
|
|
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
connmanctl tether wifi %s %s %s",
|
|
switch_on ? "on" : "off", ap_name, pass_key);
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether toggle: command: \"%s\"\n",
|
|
connman->command);
|
|
|
|
while (fgets(output, sizeof(output), command_file))
|
|
{
|
|
size_t output_size = strlen(output) - 1;
|
|
if (output[output_size] == '\n')
|
|
output[output_size] = '\0';
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether toggle: output: \"%s\"\n",
|
|
output);
|
|
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
if (!widgets_active)
|
|
#endif
|
|
runloop_msg_queue_push(output, 1, 180, true,
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
}
|
|
|
|
pclose(command_file);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether toggle: command finished\n");
|
|
|
|
if (switch_on)
|
|
{
|
|
if (!connmanctl_tether_status(connman))
|
|
configuration_set_bool(settings,
|
|
settings->bools.localap_enable, false);
|
|
}
|
|
else
|
|
{
|
|
if (connmanctl_tether_status(connman))
|
|
configuration_set_bool(settings,
|
|
settings->bools.localap_enable, true);
|
|
}
|
|
}
|
|
|
|
static void connmanctl_scan(void *data)
|
|
{
|
|
settings_t *settings = config_get_ptr();
|
|
connman_t *connman = (connman_t*)data;
|
|
|
|
if (connmanctl_tether_status(connman))
|
|
{
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_SWITCHING_OFF),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
configuration_set_bool(settings,
|
|
settings->bools.localap_enable, false);
|
|
connmanctl_tether_toggle(connman, false, "", "");
|
|
}
|
|
|
|
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);
|
|
|
|
/* Refresh now the services, to read the discovered networks */
|
|
connman->scan.scan_time = time(NULL);
|
|
connmanctl_refresh_services(connman);
|
|
}
|
|
|
|
static wifi_network_scan_t* connmanctl_get_ssids(void *data)
|
|
{
|
|
unsigned i;
|
|
connman_t *connman = (connman_t*)data;
|
|
|
|
return &connman->scan;
|
|
}
|
|
|
|
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/FIXME: 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, const wifi_network_info_t *netinfo)
|
|
{
|
|
unsigned i;
|
|
char netid[160];
|
|
char settings_dir[PATH_MAX_LENGTH];
|
|
char settings_path[PATH_MAX_LENGTH];
|
|
bool success = false;
|
|
connman_t *connman = (connman_t*)data;
|
|
settings_t *settings = config_get_ptr();
|
|
static struct string_list* list = NULL;
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
bool widgets_active =
|
|
connman->connmanctl_widgets_supported;
|
|
#endif
|
|
strlcpy(netid, netinfo->netid, sizeof(netid));
|
|
fill_pathname_join_special(settings_dir, LAKKA_CONNMAN_DIR,
|
|
netid, sizeof(settings_dir));
|
|
|
|
path_mkdir(settings_dir);
|
|
|
|
fill_pathname_join_special(settings_path, settings_dir, "settings",
|
|
sizeof(settings_path));
|
|
|
|
if (!netinfo->saved_password)
|
|
{
|
|
size_t ssid_len;
|
|
FILE *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=");
|
|
|
|
ssid_len = strlen(netinfo->ssid);
|
|
for (i = 0; i < ssid_len; 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", 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 */
|
|
if (!path_is_valid(settings_path))
|
|
{
|
|
/* Usually a mismatch between connman state and config, reload */
|
|
system("systemctl restart connman.service");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (connmanctl_tether_status(connman))
|
|
{
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_SWITCHING_OFF),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
configuration_set_bool(settings,
|
|
settings->bools.localap_enable, false);
|
|
connmanctl_tether_toggle(connman, false, "", "");
|
|
}
|
|
|
|
strlcpy(connman->command, "connmanctl connect ", sizeof(connman->command));
|
|
strlcat(connman->command, netinfo->netid, sizeof(connman->command));
|
|
|
|
pclose(popen(connman->command, "r"));
|
|
|
|
/* 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)
|
|
#endif
|
|
{
|
|
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);
|
|
}
|
|
|
|
return success;
|
|
}
|
|
|
|
static void connmanctl_get_connected_ssid(
|
|
connman_t *connman, char* ssid, size_t buffersize)
|
|
{
|
|
size_t ssid_size;
|
|
/* Stores the SSID of the currently connected Wi-Fi
|
|
* network in ssid
|
|
*/
|
|
FILE *command_file = NULL;
|
|
|
|
if (buffersize < 1)
|
|
return;
|
|
|
|
/* Following command lists all connman services, greps
|
|
* 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");
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
fgets(ssid, buffersize, command_file);
|
|
|
|
pclose(command_file);
|
|
|
|
ssid_size = strlen(ssid) - 1;
|
|
|
|
if ((ssid_size + 1) > 0)
|
|
if (ssid[ssid_size] == '\n')
|
|
ssid[ssid_size] = '\0';
|
|
|
|
RARCH_LOG("[CONNMANCTL] Get Connected SSID: command: \"%s\", output: \"%s\"\n",
|
|
connman->command, (ssid_size + 1) ? ssid : "<nothing_found>");
|
|
}
|
|
|
|
static void connmanctl_get_connected_servicename(
|
|
connman_t *connman, char* servicename, size_t buffersize)
|
|
{
|
|
/* Stores the service name of currently connected Wi-Fi
|
|
* network in servicename
|
|
*/
|
|
FILE *command_file = NULL;
|
|
FILE *service_file = NULL;
|
|
char ln[3] = {0};
|
|
char *temp;
|
|
|
|
if (buffersize < 1)
|
|
return;
|
|
|
|
temp = (char*)malloc(sizeof(char) * buffersize);
|
|
|
|
/* Following command lists all stored services in
|
|
* connman settings folder, which are then used in
|
|
* the next while loop for parsing if the service
|
|
* is currently online/ready
|
|
*/
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
for serv in %s/wifi_*/ ; do \
|
|
if [ -d $serv ] ; then \
|
|
basename $serv ; \
|
|
fi ; \
|
|
done",
|
|
LAKKA_CONNMAN_DIR);
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
RARCH_LOG("[CONNMANCTL] Testing configured services for activity: command: \"%s\"\n",
|
|
connman->command);
|
|
|
|
while (fgets(temp, buffersize, command_file))
|
|
{
|
|
size_t ln_size;
|
|
size_t temp_size = strlen(temp) - 1;
|
|
|
|
if ((temp_size + 1) > 0)
|
|
if (temp[temp_size] == '\n')
|
|
temp[temp_size] = '\0';
|
|
|
|
if ((temp_size + 1) == 0)
|
|
{
|
|
RARCH_WARN("[CONNMANCTL] Service name empty.\n");
|
|
continue;
|
|
}
|
|
|
|
/* Here we test the found service for online | ready
|
|
* status and count the lines. Expected results are
|
|
* 0 = is not active, 1 = is active
|
|
*/
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
connmanctl services %s | \
|
|
grep \"^ State = \\(online\\|ready\\)\" | \
|
|
wc -l",
|
|
temp);
|
|
|
|
service_file = popen(connman->command, "r");
|
|
|
|
fgets(ln, sizeof(ln), service_file);
|
|
ln_size = strlen(ln) - 1;
|
|
|
|
if (ln[ln_size] == '\n')
|
|
ln[ln_size] = '\0';
|
|
|
|
pclose(service_file);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Service: \"%s\", status: \"%s\"\n",
|
|
temp, ln);
|
|
|
|
if (ln[0] == '1')
|
|
{
|
|
pclose(command_file);
|
|
|
|
strlcpy(servicename, temp, buffersize);
|
|
|
|
free(temp);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Service \"%s\" considered as currently online\n",
|
|
servicename);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
pclose(command_file);
|
|
}
|
|
|
|
static void connmanctl_tether_start_stop(void *data, bool start, char* configfile)
|
|
{
|
|
/* Start / stop wrapper for the tethering service
|
|
* It also checks, if we are currently connected
|
|
* to a wi-fi network, which needs to be disconnected
|
|
* before starting the tethering service, or if the
|
|
* tethering service is already running / not running
|
|
* before performing the desired action
|
|
*/
|
|
char ap_name[64];
|
|
char pass_key[256];
|
|
FILE *command_file = NULL;
|
|
char ln[512] = {0};
|
|
char ssid[64] = {0};
|
|
char service[256] = {0};
|
|
connman_t *connman = (connman_t*)data;
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
bool widgets_active = connman->connmanctl_widgets_supported;
|
|
#endif
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: begin\n");
|
|
|
|
if (start) /* we want to start tethering */
|
|
{
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: request to start access point\n");
|
|
|
|
if (connmanctl_tether_status(connman)) /* check if already tethering and bail out if so */
|
|
{
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: AP already running\n");
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_ALREADY_RUNNING),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
return;
|
|
}
|
|
|
|
/* check if there is a config file, if not, create one, if yes, parse it */
|
|
if (!(command_file = fopen(configfile, "r")))
|
|
{
|
|
RARCH_WARN("[CONNMANCTL] Tether start stop: config \"%s\" does not exist\n",
|
|
configfile);
|
|
|
|
if (!(command_file = fopen(configfile, "w")))
|
|
{
|
|
RARCH_ERR("[CONNMANCTL] Tether start stop: cannot create config file \"%s\"\n",
|
|
configfile);
|
|
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_ERROR_CONFIG_CREATE),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_ERROR);
|
|
|
|
return;
|
|
}
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: creating new config \"%s\"\n",
|
|
configfile);
|
|
|
|
strlcpy(ap_name, "LakkaAccessPoint", sizeof(ap_name));
|
|
strlcpy(pass_key, "RetroArch", sizeof(pass_key));
|
|
|
|
fprintf(command_file, "APNAME=%s\nPASSWORD=%s", ap_name, pass_key);
|
|
|
|
fclose(command_file);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: new config \"%s\" created\n",
|
|
configfile);
|
|
}
|
|
else
|
|
{
|
|
fclose(command_file);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: config \"%s\" exists, reading it\n",
|
|
configfile);
|
|
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
grep -m 1 \"^APNAME=\" %s | cut -d '=' -f 2- && \
|
|
grep -m 1 \"^PASSWORD=\" %s | cut -d '=' -f 2-",
|
|
configfile, configfile);
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
int i = 0;
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: parsing command: \"%s\"\n",
|
|
connman->command);
|
|
|
|
while (fgets(ln, sizeof(ln), command_file))
|
|
{
|
|
size_t ln_size = strlen(ln) - 1;
|
|
|
|
i++;
|
|
if ((ln_size + 1) > 1)
|
|
{
|
|
if (ln[ln_size] == '\n')
|
|
ln[ln_size] = '\0';
|
|
|
|
if (i == 1)
|
|
{
|
|
strlcpy(ap_name, ln, sizeof(ap_name));
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: found APNAME: \"%s\"\n",
|
|
ap_name);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (i == 2)
|
|
{
|
|
strlcpy(pass_key, ln, sizeof(pass_key));
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: found PASSWORD: \"%s\"\n",
|
|
pass_key);
|
|
continue;
|
|
}
|
|
|
|
if (i > 2)
|
|
{
|
|
RARCH_WARN("[CONNMANCTL] Tether start stop: you should not get here...\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pclose(command_file);
|
|
}
|
|
|
|
if (!ap_name || !pass_key)
|
|
{
|
|
RARCH_ERR("[CONNMANCTL] Tether start stop: APNAME or PASSWORD missing\n");
|
|
|
|
snprintf(ln, sizeof(ln),
|
|
msg_hash_to_str(MSG_LOCALAP_ERROR_CONFIG_PARSE),
|
|
configfile);
|
|
|
|
runloop_msg_queue_push(ln,
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_ERROR);
|
|
|
|
return;
|
|
}
|
|
|
|
/* check if connected to a wi-fi network */
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: checking if not connected to a wi-fi network...\n");
|
|
connmanctl_get_connected_ssid(connman, ssid, sizeof(ssid));
|
|
|
|
if (strlen(ssid) != 0)
|
|
{
|
|
connmanctl_get_connected_servicename(connman, service, sizeof(service));
|
|
|
|
if (strlen(service) != 0)
|
|
{
|
|
/* disconnect from wi-fi network */
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: connected to SSID \"%s\", service \"%s\"\n",
|
|
ssid, service);
|
|
|
|
snprintf(ln, sizeof(ln),
|
|
msg_hash_to_str(MSG_WIFI_DISCONNECT_FROM),
|
|
ssid);
|
|
|
|
runloop_msg_queue_push(ln, 1, 180, true,
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
|
|
snprintf(connman->command, sizeof(connman->command), "\
|
|
connmanctl disconnect %s",
|
|
service);
|
|
|
|
command_file = popen(connman->command, "r");
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: disconnecting from service \"%s\", command: \"%s\"\n",
|
|
service, connman->command);
|
|
|
|
while (fgets(ln, sizeof(ln), command_file))
|
|
{
|
|
size_t ln_size = strlen(ln) - 1;
|
|
if (ln[ln_size] == '\n')
|
|
ln[ln_size] = '\0';
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: output: \"%s\"\n",
|
|
ln);
|
|
|
|
#ifdef HAVE_GFX_WIDGETS
|
|
if (!widgets_active)
|
|
#endif
|
|
runloop_msg_queue_push(ln, 1, 180, true,
|
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
}
|
|
|
|
pclose(command_file);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: disconnect end\n");
|
|
}
|
|
}
|
|
|
|
snprintf(connman->command, sizeof(connman->command),
|
|
msg_hash_to_str(MSG_LOCALAP_STARTING),
|
|
ap_name, pass_key);
|
|
|
|
runloop_msg_queue_push(connman->command,
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
}
|
|
else /* we want to stop tethering */
|
|
{
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: request to stop access point\n");
|
|
|
|
if (!connmanctl_tether_status(connman)) /* check if not tethering and when not, bail out */
|
|
{
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: access point is not running\n");
|
|
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_NOT_RUNNING),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
|
|
return;
|
|
}
|
|
|
|
runloop_msg_queue_push(msg_hash_to_str(MSG_LOCALAP_SWITCHING_OFF),
|
|
1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT,
|
|
MESSAGE_QUEUE_CATEGORY_INFO);
|
|
}
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: calling tether_toggle()\n");
|
|
|
|
/* call the tether toggle function */
|
|
connmanctl_tether_toggle(connman, start, ap_name, pass_key);
|
|
|
|
RARCH_LOG("[CONNMANCTL] Tether start stop: end\n");
|
|
}
|
|
|
|
wifi_driver_t wifi_connmanctl = {
|
|
connmanctl_init,
|
|
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",
|
|
};
|