We can now enable tethering on the device. The user still has to reconnect to the wifi network after disabling tethering, the network manager is lazy. 
old-commit-hash: ec671d4741
commatwo_master
grekiki 4 years ago committed by GitHub
parent fb9298b120
commit c76d239a8e
  1. 39
      selfdrive/ui/qt/offroad/wifi.cc
  2. 4
      selfdrive/ui/qt/offroad/wifi.hpp
  3. 123
      selfdrive/ui/qt/offroad/wifiManager.cc
  4. 8
      selfdrive/ui/qt/offroad/wifiManager.hpp

@ -6,7 +6,7 @@
#include <QLineEdit>
#include "wifi.hpp"
#include "widgets/toggle.hpp"
void clearLayout(QLayout* layout) {
while (QLayoutItem* item = layout->takeAt(0)) {
@ -30,9 +30,31 @@ WifiUI::WifiUI(QWidget *parent, int page_length) : QWidget(parent), networks_per
// Networks page
wifi_widget = new QWidget;
QVBoxLayout* networkLayout = new QVBoxLayout;
QHBoxLayout *tethering_field = new QHBoxLayout;
tethering_field->addWidget(new QLabel("Enable Tethering"));
Toggle* toggle_switch = new Toggle(this);
toggle_switch->setFixedSize(150, 100);
tethering_field->addWidget(toggle_switch);
if (wifi->tetheringEnabled()){
toggle_switch->togglePosition();
}
QObject::connect(toggle_switch, SIGNAL(stateChanged(int)), this, SLOT(toggleTethering(int)));
QWidget* tetheringWidget = new QWidget;
tetheringWidget->setLayout(tethering_field);
tetheringWidget->setFixedHeight(150);
networkLayout->addWidget(tetheringWidget);
vlayout = new QVBoxLayout;
wifi_widget->setLayout(vlayout);
swidget->addWidget(wifi_widget);
networkLayout->addWidget(wifi_widget);
QWidget* networkWidget = new QWidget;
networkWidget->setLayout(networkLayout);
swidget->addWidget(networkWidget);
// Keyboard page
input_field = new InputField();
@ -163,11 +185,19 @@ void WifiUI::refresh() {
vlayout->addWidget(w);
}
void WifiUI::toggleTethering(int enable){
if(enable){
wifi->enableTethering();
}else{
wifi->disableTethering();
}
}
void WifiUI::handleButton(QAbstractButton* button) {
QPushButton* btn = static_cast<QPushButton*>(button);
Network n = wifi->seen_networks[connectButtons->id(btn)];
input_field->setPromptText("Enter password for \"" + n.ssid + "\"");
connectToNetwork(n);
}
@ -176,6 +206,7 @@ void WifiUI::connectToNetwork(Network n){
if(n.security_type == SecurityType::OPEN){
wifi->connect(n);
} else if (n.security_type == SecurityType::WPA){
input_field->setPromptText("Enter password for \"" + n.ssid + "\"");
QString password = getStringFromUser();
if(password.size()){
wifi->connect(n, password);

@ -15,7 +15,7 @@ class WifiUI : public QWidget {
public:
int page;
explicit WifiUI(QWidget *parent = 0, int page_length = 6);
explicit WifiUI(QWidget *parent = 0, int page_length = 5);
private:
WifiManager* wifi;
@ -30,12 +30,14 @@ private:
QTimer *timer;
QString text;
QButtonGroup *connectButtons;
bool tetheringEnabled;
void connectToNetwork(Network n);
QString getStringFromUser();
private slots:
void handleButton(QAbstractButton* m_button);
void toggleTethering(int enable);
void refresh();
void receiveText(QString text);
void wrongPassword(QString ssid);

@ -1,11 +1,26 @@
#include <algorithm>
#include <set>
#include <stdlib.h>
#include <iostream>
#include "wifiManager.hpp"
#include "common/params.h"
/**
* We are using a NetworkManager DBUS API : https://developer.gnome.org/NetworkManager/1.26/spec.html
* */
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApFlags
const int NM_802_11_AP_FLAGS_PRIVACY = 0x00000001;
// https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NM80211ApSecurityFlags
const int NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001;
const int NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002;
const int NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010;
const int NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020;
const int NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100;
const int NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200;
QString nm_path = "/org/freedesktop/NetworkManager";
QString nm_settings_path = "/org/freedesktop/NetworkManager/Settings";
@ -40,12 +55,14 @@ bool compare_by_strength(const Network &a, const Network &b){
return a.strength > b.strength;
}
WifiManager::WifiManager(){
qDBusRegisterMetaType<Connection>();
qDBusRegisterMetaType<IpConfig>();
connecting_to_network = "";
adapter = get_adapter();
has_adapter = adapter != "";
if(has_adapter){
if (has_adapter){
QDBusInterface nm(nm_service, adapter, device_iface, bus);
bus.connect(nm_service, adapter, device_iface, "StateChanged", this, SLOT(change(unsigned int, unsigned int, unsigned int)));
@ -54,6 +71,13 @@ WifiManager::WifiManager(){
raw_adapter_state = get_response<uint>(response);
change(raw_adapter_state, 0, 0);
}
// Compute tethering ssid as "Weedle" + first 4 characters of a dongle id
tethering_ssid = "weedle";
std::string bytes = Params().get("DongleId");
if (bytes.length() >= 4){
tethering_ssid+="-"+QString::fromStdString(bytes.substr(0,4));
}
}
void WifiManager::refreshNetworks(){
@ -64,7 +88,7 @@ void WifiManager::refreshNetworks(){
seen_ssids.clear();
for (Network &network : get_networks()){
if(seen_ssids.count(network.ssid)){
if (seen_ssids.count(network.ssid)){
continue;
}
seen_ssids.push_back(network.ssid);
@ -89,12 +113,12 @@ QList<Network> WifiManager::get_networks(){
unsigned int strength = get_ap_strength(path.path());
SecurityType security = getSecurityType(path.path());
ConnectedType ctype;
if(path.path() != active_ap){
if (path.path() != active_ap){
ctype = ConnectedType::DISCONNECTED;
}else{
if(ssid == connecting_to_network){
}else {
if (ssid == connecting_to_network){
ctype = ConnectedType::CONNECTING;
}else{
}else {
ctype = ConnectedType::CONNECTED;
}
}
@ -116,9 +140,12 @@ SecurityType WifiManager::getSecurityType(QString path){
int rsnflag = get_property(path, "RsnFlags").toInt();
int wpa_props = wpaflag | rsnflag;
if(sflag == 0){
// obtained by looking at flags of networks in the office as reported by an Android phone
const int supports_wpa = NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104 | NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_KEY_MGMT_PSK;
if (sflag == 0){
return SecurityType::OPEN;
} else if((sflag & 0x1) && (wpa_props & (0x333) && !(wpa_props & 0x200))) {
} else if ((sflag & NM_802_11_AP_FLAGS_PRIVACY) && (wpa_props & supports_wpa) && !(wpa_props & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) {
return SecurityType::WPA;
} else {
return SecurityType::UNSUPPORTED;
@ -135,10 +162,7 @@ void WifiManager::connect(Network n, QString password){
void WifiManager::connect(Network n, QString username, QString password){
connecting_to_network = n.ssid;
QString active_ap = get_active_ap();
if(active_ap!="" && active_ap!="/"){
deactivate_connections(get_property(active_ap, "Ssid")); //Disconnect from any connected networks
}
disconnect();
clear_connections(n.ssid); //Clear all connections that may already exist to the network we are connecting
connect(n.ssid, username, password, n.security_type);
}
@ -147,13 +171,13 @@ void WifiManager::connect(QByteArray ssid, QString username, QString password, S
Connection connection;
connection["connection"]["type"] = "802-11-wireless";
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
connection["connection"]["id"] = "OpenPilot connection "+QString::fromStdString(ssid.toStdString());
connection["connection"]["autoconnect-retries"] = 0;
connection["802-11-wireless"]["ssid"] = ssid;
connection["802-11-wireless"]["mode"] = "infrastructure";
if(security_type == SecurityType::WPA){
if (security_type == SecurityType::WPA){
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
connection["802-11-wireless-security"]["auth-alg"] = "open";
connection["802-11-wireless-security"]["psk"] = password;
@ -163,16 +187,16 @@ void WifiManager::connect(QByteArray ssid, QString username, QString password, S
connection["ipv6"]["method"] = "ignore";
QDBusInterface nm_settings(nm_service, nm_settings_path, nm_settings_iface, bus);
QDBusReply<QDBusObjectPath> result = nm_settings.call("AddConnection", QVariant::fromValue(connection));
nm_settings.call("AddConnection", QVariant::fromValue(connection));
}
void WifiManager::deactivate_connections(QString ssid){
for(QDBusObjectPath active_connection_raw : get_active_connections()){
for (QDBusObjectPath active_connection_raw : get_active_connections()){
QString active_connection = active_connection_raw.path();
QDBusInterface nm(nm_service, active_connection, props_iface, bus);
QDBusObjectPath pth = get_response<QDBusObjectPath>(nm.call("Get", connection_iface, "SpecificObject"));
QString Ssid = get_property(pth.path(), "Ssid");
if(Ssid == ssid){
if (Ssid == ssid){
QDBusInterface nm2(nm_service, nm_path, nm_iface, bus);
nm2.call("DeactivateConnection", QVariant::fromValue(active_connection_raw));
}
@ -210,12 +234,12 @@ void WifiManager::clear_connections(QString ssid){
QMap<QString,QMap<QString,QVariant> > map;
dbusArg >> map;
for(QString outer_key : map.keys()) {
for (QString outer_key : map.keys()) {
QMap<QString,QVariant> innerMap = map.value(outer_key);
for(QString inner_key : innerMap.keys()) {
if(inner_key == "ssid"){
for (QString inner_key : innerMap.keys()) {
if (inner_key == "ssid"){
QString value = innerMap.value(inner_key).value<QString>();
if(value == ssid){
if (value == ssid){
nm2.call("Delete");
}
}
@ -288,9 +312,58 @@ QString WifiManager::get_adapter(){
void WifiManager::change(unsigned int new_state,unsigned int previous_state,unsigned int change_reason){
raw_adapter_state = new_state;
if(new_state == state_need_auth && change_reason == reason_wrong_password){
if (new_state == state_need_auth && change_reason == reason_wrong_password){
emit wrongPassword(connecting_to_network);
}else if(new_state == state_connected){
connecting_to_network="";
}else if (new_state == state_connected){
connecting_to_network = "";
}
}
void WifiManager::disconnect(){
QString active_ap = get_active_ap();
if (active_ap!="" && active_ap!="/"){
deactivate_connections(get_property(active_ap, "Ssid"));
}
}
//Functions for tethering
void WifiManager::enableTethering(){
disconnect();
Connection connection;
connection["connection"]["id"] = "Hotspot";
connection["connection"]["uuid"] = QUuid::createUuid().toString().remove('{').remove('}');
connection["connection"]["type"] = "802-11-wireless";
connection["connection"]["interface-name"] = "wlan0";
connection["802-11-wireless"]["band"] = "bg";
connection["802-11-wireless"]["mode"] = "ap";
connection["802-11-wireless"]["ssid"] = tethering_ssid.toUtf8();
connection["802-11-wireless-security"]["group"] = QStringList("ccmp");
connection["802-11-wireless-security"]["key-mgmt"] = "wpa-psk";
connection["802-11-wireless-security"]["pairwise"] = QStringList("ccmp");
connection["802-11-wireless-security"]["proto"] = QStringList("rsn");
connection["802-11-wireless-security"]["psk"] = "swagswagcomma";
connection["ipv4"]["method"] = "shared";
QMap<QString,QVariant> adress1;
adress1["address"] = "192.168.43.1";
adress1["prefix"] = 24u;
connection["ipv4"]["address-data"] = QVariant::fromValue(IpConfig() << adress1);
connection["ipv4"]["gateway"] = "192.168.43.1";
connection["ipv6"]["method"] = "ignore";
QDBusInterface nm_settings(nm_service, nm_settings_path, nm_settings_iface, bus);
nm_settings.call("AddConnection", QVariant::fromValue(connection));
}
void WifiManager::disableTethering(){
clear_connections(tethering_ssid);
}
bool WifiManager::tetheringEnabled(){
QString active_ap = get_active_ap();
return get_property(active_ap, "Ssid") == tethering_ssid;
}

@ -15,6 +15,7 @@ enum class ConnectedType{
};
typedef QMap<QString, QMap<QString, QVariant>> Connection;
typedef QVector<QMap<QString, QVariant>> IpConfig;
struct Network {
QString path;
@ -37,6 +38,11 @@ public:
void connect(Network ssid);
void connect(Network ssid, QString password);
void connect(Network ssid, QString username, QString password);
// Tethering functions
void enableTethering();
void disableTethering();
bool tetheringEnabled();
private:
QVector<QByteArray> seen_ssids;
@ -44,6 +50,7 @@ private:
QDBusConnection bus = QDBusConnection::systemBus();
unsigned int raw_adapter_state;//Connection status https://developer.gnome.org/NetworkManager/1.26/nm-dbus-types.html#NMDeviceState
QString connecting_to_network;
QString tethering_ssid;
QString get_adapter();
QList<Network> get_networks();
@ -56,6 +63,7 @@ private:
QByteArray get_property(QString network_path, QString property);
unsigned int get_ap_strength(QString network_path);
SecurityType getSecurityType(QString ssid);
void disconnect();
private slots:
void change(unsigned int new_state, unsigned int previous_state, unsigned int change_reason);

Loading…
Cancel
Save