~morphis/aethercast/add-urfkill-support2

« back to all changes in this revision

Viewing changes to src/w11tng/urfkillmanager.cpp

  • Committer: Simon Fels
  • Date: 2016-06-28 08:28:52 UTC
  • Revision ID: simon.fels@canonical.com-20160628082852-dr6h341t6bkrsizh
Implement URfkill based rfkill manager

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2016 Canonical, Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License version 3, as published
 
6
 * by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
11
 * PURPOSE.  See the GNU General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU General Public License along
 
14
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 */
 
17
 
 
18
#include "w11tng/urfkillmanager.h"
 
19
 
 
20
#include "ac/logger.h"
 
21
#include "ac/keep_alive.h"
 
22
#include "ac/dbus/helpers.h"
 
23
 
 
24
#include <string.h>
 
25
#include <errno.h>
 
26
 
 
27
namespace w11tng {
 
28
URfkillManager::Ptr URfkillManager::Create() {
 
29
    return std::shared_ptr<URfkillManager>(new URfkillManager)->FinalizeConstruction();
 
30
}
 
31
 
 
32
URfkillManager::URfkillManager()  {
 
33
}
 
34
 
 
35
URfkillManager::~URfkillManager() {
 
36
}
 
37
 
 
38
URfkillManager::Ptr URfkillManager::FinalizeConstruction() {
 
39
    auto sp = shared_from_this();
 
40
 
 
41
    GError *error = nullptr;
 
42
    connection_.reset(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error));
 
43
    if (!connection_) {
 
44
        AC_ERROR("Failed to connect to system bus: %s", error->message);
 
45
        g_error_free(error);
 
46
        return sp;
 
47
    }
 
48
 
 
49
    g_dbus_connection_signal_subscribe(connection_.get(),
 
50
                                       kBusName,
 
51
                                       "org.freedesktop.DBus.Properties",
 
52
                                       "PropertiesChanged",
 
53
                                       kObjectPath,
 
54
                                       nullptr,
 
55
                                       G_DBUS_SIGNAL_FLAGS_NONE,
 
56
                                       &URfkillManager::OnPropertiesChanged,
 
57
                                       new ac::WeakKeepAlive<URfkillManager>(shared_from_this()),
 
58
                                       [](gpointer data) { delete static_cast<ac::WeakKeepAlive<URfkillManager>*>(data); });
 
59
 
 
60
    SyncProperties();
 
61
 
 
62
    return sp;
 
63
}
 
64
 
 
65
void URfkillManager::OnPropertiesChanged(GDBusConnection *connection, const gchar *sender_name, const gchar *object_path,
 
66
                                        const gchar *interface_name, const gchar *signal_name, GVariant *parameters,
 
67
                                        gpointer user_data) {
 
68
 
 
69
    auto thiz = static_cast<ac::WeakKeepAlive<URfkillManager>*>(user_data)->GetInstance().lock();
 
70
 
 
71
    if (not thiz)
 
72
        return;
 
73
 
 
74
    thiz->ParseProperties(parameters);
 
75
}
 
76
 
 
77
void URfkillManager::SyncProperties() {
 
78
    g_dbus_connection_call(connection_.get(),
 
79
                           kBusName,
 
80
                           kObjectPath,
 
81
                           "org.freedesktop.DBus.Properties",
 
82
                           "GetAll",
 
83
                           g_variant_new ("(s)", "org.freedesktop.URfkill"),
 
84
                           G_VARIANT_TYPE("(a{sv})"),
 
85
                           G_DBUS_CALL_FLAGS_NONE,
 
86
                           -1, // Make sure we wait for the service being started up
 
87
                           nullptr,
 
88
                           [](GObject *source, GAsyncResult *res, gpointer user_data) {
 
89
 
 
90
        auto thiz = static_cast<ac::SharedKeepAlive<URfkillManager>*>(user_data)->ShouldDie();
 
91
 
 
92
        GError *error = nullptr;
 
93
        auto result = g_dbus_connection_call_finish(thiz->connection_.get(), res, &error);
 
94
        if (!result) {
 
95
            AC_ERROR("Failed to query urfkill service: %s", error->message);
 
96
            g_error_free(error);
 
97
            return;
 
98
        }
 
99
 
 
100
        thiz->ParseProperties(g_variant_get_child_value(result, 0));
 
101
 
 
102
    }, new ac::SharedKeepAlive<URfkillManager>{shared_from_this()});
 
103
}
 
104
 
 
105
void URfkillManager::ParseProperties(GVariant *properties) {
 
106
    ac::dbus::Helpers::ParseDictionary(properties, [&](const std::string &key, GVariant *value) {
 
107
        if (key == "state") {
 
108
            const auto state = g_variant_get_int32(g_variant_get_variant(value));
 
109
            const auto type = Type::kWLAN;
 
110
            block_status_[type] = (state == 0);
 
111
            if (auto sp = delegate_.lock())
 
112
                sp->OnRfkillChanged(type);
 
113
        }
 
114
    });
 
115
}
 
116
 
 
117
bool URfkillManager::IsBlocked(const Type &type) {
 
118
    if (block_status_.find(type) == block_status_.end())
 
119
        return false;
 
120
 
 
121
    return block_status_[type];
 
122
}
 
123
} // namespace w11tng