GCC Code Coverage Report


Directory: ./
File: panels/network/net-device-mobile.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 397 0.0%
Functions: 0 27 0.0%
Branches: 0 233 0.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
4 * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
5 *
6 * Licensed under the GNU General Public License Version 2
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "config.h"
24
25 #include <glib-object.h>
26 #include <glib/gi18n.h>
27
28 #include <NetworkManager.h>
29 #include <libmm-glib.h>
30 #include <nma-mobile-providers.h>
31
32 #include "panel-common.h"
33 #include "network-dialogs.h"
34 #include "net-device-mobile.h"
35
36 static void nm_device_mobile_refresh_ui (NetDeviceMobile *self);
37
38 struct _NetDeviceMobile
39 {
40 GtkBox parent;
41
42 GtkLabel *device_label;
43 GtkSwitch *device_off_switch;
44 GtkLabel *dns4_heading_label;
45 GtkLabel *dns4_label;
46 GtkLabel *dns6_heading_label;
47 GtkLabel *dns6_label;
48 GtkLabel *imei_heading_label;
49 GtkLabel *imei_label;
50 GtkLabel *ipv4_heading_label;
51 GtkLabel *ipv4_label;
52 GtkLabel *ipv6_heading_label;
53 GtkLabel *ipv6_label;
54 GtkListStore *mobile_connections_list_store;
55 GtkComboBox *network_combo;
56 GtkLabel *network_label;
57 GtkButton *options_button;
58 GtkLabel *provider_heading_label;
59 GtkLabel *provider_label;
60 GtkLabel *route_heading_label;
61 GtkLabel *route_label;
62 GtkLabel *status_label;
63
64 NMClient *client;
65 NMDevice *device;
66 GDBusObject *modem;
67 GCancellable *cancellable;
68
69 gboolean updating_device;
70
71 /* Old MM < 0.7 support */
72 GDBusProxy *gsm_proxy;
73 GDBusProxy *cdma_proxy;
74
75 /* New MM >= 0.7 support */
76 MMObject *mm_object;
77
78 NMAMobileProvidersDatabase *mpd;
79 };
80
81 enum {
82 COLUMN_ID,
83 COLUMN_TITLE,
84 COLUMN_LAST
85 };
86
87 G_DEFINE_TYPE (NetDeviceMobile, net_device_mobile, GTK_TYPE_BOX)
88
89 static void
90 connection_activate_cb (GObject *source_object,
91 GAsyncResult *res,
92 gpointer user_data)
93 {
94 g_autoptr(GError) error = NULL;
95
96 if (!nm_client_activate_connection_finish (NM_CLIENT (source_object), res, &error)) {
97 /* failed to activate */
98 nm_device_mobile_refresh_ui (user_data);
99 }
100 }
101
102 static void
103 network_combo_changed_cb (NetDeviceMobile *self)
104 {
105 gboolean ret;
106 g_autofree gchar *object_path = NULL;
107 GtkTreeIter iter;
108 GtkTreeModel *model;
109 NMConnection *connection;
110
111 if (self->updating_device)
112 return;
113
114 ret = gtk_combo_box_get_active_iter (self->network_combo, &iter);
115 if (!ret)
116 return;
117
118 /* get entry */
119 model = gtk_combo_box_get_model (self->network_combo);
120 gtk_tree_model_get (model, &iter,
121 COLUMN_ID, &object_path,
122 -1);
123 if (g_strcmp0 (object_path, NULL) == 0) {
124 GtkNative *native = gtk_widget_get_native (GTK_WIDGET (self));
125 cc_network_panel_connect_to_3g_network (GTK_WIDGET (native), self->client, self->device);
126 return;
127 }
128
129 /* activate the connection */
130 g_debug ("try to switch to connection %s", object_path);
131 connection = (NMConnection*) nm_client_get_connection_by_path (self->client, object_path);
132 if (connection != NULL) {
133 nm_device_disconnect_async (self->device, NULL, NULL, NULL);
134 nm_client_activate_connection_async (self->client,
135 connection,
136 self->device, NULL, NULL,
137 connection_activate_cb,
138 self);
139 return;
140 }
141 }
142
143 static void
144 mobilebb_enabled_toggled (NetDeviceMobile *self)
145 {
146 gboolean enabled = FALSE;
147
148 if (nm_client_wwan_get_enabled (self->client)) {
149 NMDeviceState state;
150
151 state = nm_device_get_state (self->device);
152 if (state == NM_DEVICE_STATE_UNKNOWN ||
153 state == NM_DEVICE_STATE_UNMANAGED ||
154 state == NM_DEVICE_STATE_UNAVAILABLE ||
155 state == NM_DEVICE_STATE_DISCONNECTED ||
156 state == NM_DEVICE_STATE_DEACTIVATING ||
157 state == NM_DEVICE_STATE_FAILED) {
158 enabled = FALSE;
159 } else {
160 enabled = TRUE;
161 }
162 }
163
164 self->updating_device = TRUE;
165 gtk_switch_set_active (self->device_off_switch, enabled);
166 self->updating_device = FALSE;
167 }
168
169 static void
170 device_add_device_connections (NetDeviceMobile *self,
171 NMDevice *nm_device,
172 GtkListStore *liststore,
173 GtkComboBox *combobox)
174 {
175 GSList *list, *l;
176 GtkTreeIter treeiter;
177 NMActiveConnection *active_connection;
178 NMConnection *connection;
179
180 /* get the list of available connections for this device */
181 list = net_device_get_valid_connections (self->client, nm_device);
182 gtk_list_store_clear (liststore);
183 active_connection = nm_device_get_active_connection (nm_device);
184 for (l = list; l; l = g_slist_next (l)) {
185 connection = NM_CONNECTION (l->data);
186 gtk_list_store_append (liststore, &treeiter);
187 gtk_list_store_set (liststore,
188 &treeiter,
189 COLUMN_ID, nm_connection_get_uuid (connection),
190 COLUMN_TITLE, nm_connection_get_id (connection),
191 -1);
192
193 /* is this already activated? */
194 if (active_connection != NULL &&
195 g_strcmp0 (nm_connection_get_uuid (connection),
196 nm_active_connection_get_uuid (active_connection)) == 0) {
197 self->updating_device = TRUE;
198 gtk_combo_box_set_active_iter (combobox, &treeiter);
199 self->updating_device = FALSE;
200 }
201 }
202
203 /* add new connection entry */
204 gtk_list_store_append (liststore, &treeiter);
205 gtk_list_store_set (liststore,
206 &treeiter,
207 COLUMN_ID, NULL,
208 COLUMN_TITLE, _("Add new connection"),
209 -1);
210
211 g_slist_free (list);
212 }
213
214 static void
215 device_mobile_refresh_equipment_id (NetDeviceMobile *self)
216 {
217 const gchar *equipment_id = NULL;
218
219 if (self->mm_object != NULL) {
220 MMModem *modem;
221
222 /* Modem interface should always be present */
223 modem = mm_object_peek_modem (self->mm_object);
224 equipment_id = mm_modem_get_equipment_identifier (modem);
225
226 /* Set equipment ID */
227 if (equipment_id != NULL) {
228 g_debug ("[%s] Equipment ID set to '%s'",
229 mm_object_get_path (self->mm_object),
230 equipment_id);
231 }
232 } else {
233 /* Assume old MM handling */
234 equipment_id = g_object_get_data (G_OBJECT (self),
235 "ControlCenter::EquipmentIdentifier");
236 }
237
238 gtk_label_set_label (self->imei_label, equipment_id);
239 gtk_widget_set_visible (GTK_WIDGET (self->imei_heading_label), equipment_id != NULL);
240 gtk_widget_set_visible (GTK_WIDGET (self->imei_label), equipment_id != NULL);
241 }
242
243 static gchar *
244 device_mobile_find_provider (NetDeviceMobile *self,
245 const gchar *mccmnc,
246 guint32 sid)
247 {
248 NMAMobileProvider *provider;
249 GString *name = NULL;
250
251 if (self->mpd == NULL) {
252 g_autoptr(GError) error = NULL;
253
254 /* Use defaults */
255 self->mpd = nma_mobile_providers_database_new_sync (NULL, NULL, NULL, &error);
256 if (self->mpd == NULL) {
257 g_debug ("Couldn't load mobile providers database: %s",
258 error ? error->message : "");
259 return NULL;
260 }
261 }
262
263 if (mccmnc != NULL) {
264 provider = nma_mobile_providers_database_lookup_3gpp_mcc_mnc (self->mpd, mccmnc);
265 if (provider != NULL)
266 name = g_string_new (nma_mobile_provider_get_name (provider));
267 }
268
269 if (sid != 0) {
270 provider = nma_mobile_providers_database_lookup_cdma_sid (self->mpd, sid);
271 if (provider != NULL) {
272 if (name == NULL)
273 name = g_string_new (nma_mobile_provider_get_name (provider));
274 else
275 g_string_append_printf (name, ", %s", nma_mobile_provider_get_name (provider));
276 }
277 }
278
279 return (name != NULL ? g_string_free (name, FALSE) : NULL);
280 }
281
282 static void
283 device_mobile_refresh_operator_name (NetDeviceMobile *self)
284 {
285 g_autofree gchar *operator_name = NULL;
286
287 if (self->mm_object != NULL) {
288 MMModem3gpp *modem_3gpp;
289 MMModemCdma *modem_cdma;
290
291 modem_3gpp = mm_object_peek_modem_3gpp (self->mm_object);
292 modem_cdma = mm_object_peek_modem_cdma (self->mm_object);
293
294 if (modem_3gpp != NULL) {
295 const gchar *operator_name_unsafe;
296
297 operator_name_unsafe = mm_modem_3gpp_get_operator_name (modem_3gpp);
298 if (operator_name_unsafe != NULL && operator_name_unsafe[0] != '\0')
299 operator_name = g_strescape (operator_name_unsafe, NULL);
300 }
301
302 /* If not directly given in the 3GPP interface, try to guess from
303 * MCCMNC/SID */
304 if (operator_name == NULL) {
305 const gchar *mccmnc = NULL;
306 guint32 sid = 0;
307
308 if (modem_3gpp != NULL)
309 mccmnc = mm_modem_3gpp_get_operator_code (modem_3gpp);
310 if (modem_cdma != NULL)
311 sid = mm_modem_cdma_get_sid (modem_cdma);
312 operator_name = device_mobile_find_provider (self, mccmnc, sid);
313 }
314
315 /* Set operator name */
316 if (operator_name != NULL) {
317 g_debug ("[%s] Operator name set to '%s'",
318 mm_object_get_path (self->mm_object),
319 operator_name);
320 }
321
322 } else {
323 const gchar *gsm;
324 const gchar *cdma;
325
326 /* Assume old MM handling */
327 gsm = g_object_get_data (G_OBJECT (self),
328 "ControlCenter::OperatorNameGsm");
329 cdma = g_object_get_data (G_OBJECT (self),
330 "ControlCenter::OperatorNameCdma");
331
332 if (gsm != NULL && cdma != NULL)
333 operator_name = g_strdup_printf ("%s, %s", gsm, cdma);
334 else if (gsm != NULL)
335 operator_name = g_strdup (gsm);
336 else if (cdma != NULL)
337 operator_name = g_strdup (cdma);
338 }
339
340 gtk_label_set_label (self->provider_label, operator_name);
341 gtk_widget_set_visible (GTK_WIDGET (self->provider_heading_label), operator_name != NULL);
342 gtk_widget_set_visible (GTK_WIDGET (self->provider_label), operator_name != NULL);
343 }
344
345 static void
346 nm_device_mobile_refresh_ui (NetDeviceMobile *self)
347 {
348 gboolean is_connected;
349 NMDeviceModemCapabilities caps;
350 g_autofree gchar *status = NULL;
351 NMIPConfig *ipv4_config = NULL, *ipv6_config = NULL;
352 gboolean have_ipv4_address = FALSE, have_ipv6_address = FALSE;
353 gboolean have_dns4 = FALSE, have_dns6 = FALSE;
354 const gchar *route4_text = NULL, *route6_text = NULL;
355
356 /* set up the device on/off switch */
357 gtk_widget_set_visible (GTK_WIDGET (self->device_off_switch), TRUE);
358 mobilebb_enabled_toggled (self);
359
360 /* set device state, with status */
361 status = panel_device_status_to_localized_string (self->device, NULL);
362 gtk_label_set_label (self->status_label, status);
363
364 /* sensitive for other connection types if the device is currently connected */
365 is_connected = net_device_get_find_connection (self->client, self->device) != NULL;
366 gtk_widget_set_sensitive (GTK_WIDGET (self->options_button), is_connected);
367
368 caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (self->device));
369 if ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
370 (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) ||
371 (caps & NM_DEVICE_MODEM_CAPABILITY_LTE)) {
372 device_mobile_refresh_operator_name (self);
373 device_mobile_refresh_equipment_id (self);
374 }
375
376 /* add possible connections to device */
377 device_add_device_connections (self,
378 self->device,
379 self->mobile_connections_list_store,
380 self->network_combo);
381
382 ipv4_config = nm_device_get_ip4_config (self->device);
383 if (ipv4_config != NULL) {
384 GPtrArray *addresses;
385 const gchar *ipv4_text = NULL;
386 g_autofree gchar *ip4_dns = NULL;
387
388 addresses = nm_ip_config_get_addresses (ipv4_config);
389 if (addresses->len > 0)
390 ipv4_text = nm_ip_address_get_address (g_ptr_array_index (addresses, 0));
391 gtk_label_set_label (self->ipv4_label, ipv4_text);
392 gtk_widget_set_visible (GTK_WIDGET (self->ipv4_heading_label), ipv4_text != NULL);
393 gtk_widget_set_visible (GTK_WIDGET (self->ipv4_label), ipv4_text != NULL);
394 have_ipv4_address = ipv4_text != NULL;
395
396 ip4_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv4_config));
397 if (!*ip4_dns)
398 ip4_dns = NULL;
399 gtk_label_set_label (self->dns4_label, ip4_dns);
400 gtk_widget_set_visible (GTK_WIDGET (self->dns4_heading_label), ip4_dns != NULL);
401 gtk_widget_set_visible (GTK_WIDGET (self->dns4_label), ip4_dns != NULL);
402 have_dns4 = ip4_dns != NULL;
403
404 route4_text = nm_ip_config_get_gateway (ipv4_config);
405 } else {
406 gtk_widget_set_visible (GTK_WIDGET (self->ipv4_heading_label), FALSE);
407 gtk_widget_set_visible (GTK_WIDGET (self->ipv4_label), FALSE);
408 gtk_widget_set_visible (GTK_WIDGET (self->dns4_heading_label), FALSE);
409 gtk_widget_set_visible (GTK_WIDGET (self->dns4_label), FALSE);
410 }
411
412 ipv6_config = nm_device_get_ip6_config (self->device);
413 if (ipv6_config != NULL) {
414 g_autofree gchar *ipv6_text = NULL;
415 g_autofree gchar *ip6_dns = NULL;
416
417 ipv6_text = net_device_get_ip6_addresses (ipv6_config);
418 gtk_label_set_label (self->ipv6_label, ipv6_text);
419 gtk_widget_set_visible (GTK_WIDGET (self->ipv6_heading_label), ipv6_text != NULL);
420 gtk_widget_set_valign (GTK_WIDGET (self->ipv6_heading_label), GTK_ALIGN_START);
421 gtk_widget_set_visible (GTK_WIDGET (self->ipv6_label), ipv6_text != NULL);
422 have_ipv6_address = ipv6_text != NULL;
423
424 ip6_dns = g_strjoinv (" ", (char **) nm_ip_config_get_nameservers (ipv6_config));
425 if (!*ip6_dns)
426 ip6_dns = NULL;
427 gtk_label_set_label (self->dns6_label, ip6_dns);
428 gtk_widget_set_visible (GTK_WIDGET (self->dns6_heading_label), ip6_dns != NULL);
429 gtk_widget_set_visible (GTK_WIDGET (self->dns6_label), ip6_dns != NULL);
430 have_dns6 = ip6_dns != NULL;
431
432 route6_text = nm_ip_config_get_gateway (ipv6_config);
433 } else {
434 gtk_widget_set_visible (GTK_WIDGET (self->ipv6_heading_label), FALSE);
435 gtk_widget_set_visible (GTK_WIDGET (self->ipv6_label), FALSE);
436 gtk_widget_set_visible (GTK_WIDGET (self->dns6_heading_label), FALSE);
437 gtk_widget_set_visible (GTK_WIDGET (self->dns6_label), FALSE);
438 }
439
440 if (have_ipv4_address && have_ipv6_address) {
441 gtk_label_set_label (self->ipv4_heading_label, _("IPv4 Address"));
442 gtk_label_set_label (self->ipv6_heading_label, _("IPv6 Address"));
443 }
444 else {
445 gtk_label_set_label (self->ipv4_heading_label, _("IP Address"));
446 gtk_label_set_label (self->ipv6_heading_label, _("IP Address"));
447 }
448
449 if (have_dns4 && have_dns6) {
450 gtk_label_set_label (self->dns4_heading_label, _("DNS4"));
451 gtk_label_set_label (self->dns6_heading_label, _("DNS6"));
452 } else {
453 gtk_label_set_label (self->dns4_heading_label, _("DNS"));
454 gtk_label_set_label (self->dns6_heading_label, _("DNS"));
455 }
456
457 if (route4_text != NULL || route6_text != NULL) {
458 g_autofree const gchar *routes_text = NULL;
459
460 if (route4_text == NULL) {
461 routes_text = g_strdup (route6_text);
462 } else if (route6_text == NULL) {
463 routes_text = g_strdup (route4_text);
464 } else {
465 routes_text = g_strjoin ("\n", route4_text, route6_text, NULL);
466 }
467 gtk_label_set_label (self->route_label, routes_text);
468 gtk_widget_set_visible (GTK_WIDGET (self->route_heading_label), routes_text != NULL);
469 gtk_widget_set_valign (GTK_WIDGET (self->route_heading_label), GTK_ALIGN_START);
470 gtk_widget_set_visible (GTK_WIDGET (self->route_label), routes_text != NULL);
471 } else {
472 gtk_widget_set_visible (GTK_WIDGET (self->route_heading_label), FALSE);
473 gtk_widget_set_visible (GTK_WIDGET (self->route_label), FALSE);
474 }
475 }
476
477 static void
478 device_off_switch_changed_cb (NetDeviceMobile *self)
479 {
480 const GPtrArray *acs;
481 gboolean active;
482 gint i;
483 NMActiveConnection *a;
484 NMConnection *connection;
485
486 if (self->updating_device)
487 return;
488
489 connection = net_device_get_find_connection (self->client, self->device);
490 if (connection == NULL)
491 return;
492
493 active = gtk_switch_get_active (self->device_off_switch);
494 if (active) {
495 nm_client_activate_connection_async (self->client,
496 connection,
497 self->device,
498 NULL, NULL, NULL, NULL);
499 } else {
500 const gchar *uuid;
501
502 uuid = nm_connection_get_uuid (connection);
503 acs = nm_client_get_active_connections (self->client);
504 for (i = 0; acs && i < acs->len; i++) {
505 a = (NMActiveConnection*)acs->pdata[i];
506 if (strcmp (nm_active_connection_get_uuid (a), uuid) == 0) {
507 nm_client_deactivate_connection_async (self->client, a, NULL, NULL, NULL);
508 break;
509 }
510 }
511 }
512 }
513
514 static void
515 options_button_clicked_cb (NetDeviceMobile *self)
516 {
517 const gchar *uuid;
518 g_autofree gchar *cmdline = NULL;
519 g_autoptr(GError) error = NULL;
520 NMConnection *connection;
521
522 connection = net_device_get_find_connection (self->client, self->device);
523 uuid = nm_connection_get_uuid (connection);
524 cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
525 g_debug ("Launching '%s'\n", cmdline);
526 if (!g_spawn_command_line_async (cmdline, &error))
527 g_warning ("Failed to launch nm-connection-editor: %s", error->message);
528 }
529
530 static void
531 device_mobile_device_got_modem_manager_cb (GObject *source_object,
532 GAsyncResult *res,
533 gpointer user_data)
534 {
535 g_autoptr(GError) error = NULL;
536 g_autoptr(GVariant) result = NULL;
537 g_autoptr(GDBusProxy) proxy = NULL;
538 NetDeviceMobile *self = (NetDeviceMobile *)user_data;
539
540 proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
541 if (!proxy) {
542 g_warning ("Error creating ModemManager proxy: %s",
543 error->message);
544 return;
545 }
546
547 /* get the IMEI */
548 result = g_dbus_proxy_get_cached_property (proxy,
549 "EquipmentIdentifier");
550
551 /* save */
552 if (result)
553 g_object_set_data_full (G_OBJECT (self),
554 "ControlCenter::EquipmentIdentifier",
555 g_variant_dup_string (result, NULL),
556 g_free);
557
558 device_mobile_refresh_equipment_id (self);
559 }
560
561 static void
562 device_mobile_save_operator_name (NetDeviceMobile *self,
563 const gchar *field,
564 const gchar *operator_name)
565 {
566 gchar *operator_name_safe = NULL;
567
568 if (operator_name != NULL && operator_name[0] != '\0')
569 operator_name_safe = g_strescape (operator_name, NULL);
570
571 /* save */
572 g_object_set_data_full (G_OBJECT (self),
573 field,
574 operator_name_safe,
575 g_free);
576 /* refresh */
577 device_mobile_refresh_operator_name (self);
578 }
579
580 static void
581 device_mobile_get_registration_info_cb (GObject *source_object,
582 GAsyncResult *res,
583 gpointer user_data)
584 {
585 g_autofree gchar *operator_code = NULL;
586 g_autoptr(GError) error = NULL;
587 guint registration_status;
588 g_autoptr(GVariant) result = NULL;
589 g_autofree gchar *operator_name = NULL;
590 NetDeviceMobile *self = (NetDeviceMobile *)user_data;
591
592 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
593 if (result == NULL) {
594 g_warning ("Error getting registration info: %s\n",
595 error->message);
596 return;
597 }
598
599 /* get values */
600 g_variant_get (result, "((uss))",
601 &registration_status,
602 &operator_code,
603 &operator_name);
604
605 /* If none give, try to guess it */
606 if (operator_name == NULL || operator_name[0] == '\0') {
607 g_free (operator_name);
608 operator_name = device_mobile_find_provider (self, operator_code, 0);
609 }
610
611 /* save and refresh */
612 device_mobile_save_operator_name (self,
613 "ControlCenter::OperatorNameGsm",
614 operator_name);
615 }
616
617 static void
618 device_mobile_gsm_signal_cb (NetDeviceMobile *self,
619 const gchar *sender_name,
620 const gchar *signal_name,
621 GVariant *parameters)
622 {
623 guint registration_status = 0;
624 g_autofree gchar *operator_code = NULL;
625 g_autofree gchar *operator_name = NULL;
626
627 if (!g_str_equal (signal_name, "RegistrationInfo"))
628 return;
629
630 g_variant_get (parameters,
631 "(uss)",
632 &registration_status,
633 &operator_code,
634 &operator_name);
635
636 /* If none given, try to guess it */
637 if (operator_name == NULL || operator_name[0] == '\0') {
638 g_free (operator_name);
639 operator_name = device_mobile_find_provider (self, operator_code, 0);
640 }
641
642 /* save and refresh */
643 device_mobile_save_operator_name (self,
644 "ControlCenter::OperatorNameGsm",
645 operator_name);
646 }
647
648 static void
649 device_mobile_device_got_modem_manager_gsm_cb (GObject *source_object,
650 GAsyncResult *res,
651 gpointer user_data)
652 {
653 g_autoptr(GError) error = NULL;
654 NetDeviceMobile *self = (NetDeviceMobile *)user_data;
655
656 self->gsm_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
657 if (self->gsm_proxy == NULL) {
658 g_warning ("Error creating ModemManager GSM proxy: %s\n",
659 error->message);
660 return;
661 }
662
663 /* Setup value updates */
664 g_signal_connect_object (self->gsm_proxy,
665 "g-signal",
666 G_CALLBACK (device_mobile_gsm_signal_cb),
667 self,
668 G_CONNECT_SWAPPED);
669
670 /* Load initial value */
671 g_dbus_proxy_call (self->gsm_proxy,
672 "GetRegistrationInfo",
673 NULL,
674 G_DBUS_CALL_FLAGS_NONE,
675 -1,
676 NULL,
677 device_mobile_get_registration_info_cb,
678 self);
679 }
680
681 static void
682 device_mobile_get_serving_system_cb (GObject *source_object,
683 GAsyncResult *res,
684 gpointer user_data)
685 {
686 NetDeviceMobile *self = (NetDeviceMobile *)user_data;
687 g_autoptr(GVariant) result = NULL;
688 g_autoptr(GError) error = NULL;
689
690 guint32 band_class;
691 g_autofree gchar *band = NULL;
692 guint32 sid;
693 gchar *operator_name;
694
695 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
696 if (result == NULL) {
697 g_warning ("Error getting serving system: %s\n",
698 error->message);
699 return;
700 }
701
702 /* get values */
703 g_variant_get (result, "((usu))",
704 &band_class,
705 &band,
706 &sid);
707
708 operator_name = device_mobile_find_provider (self, NULL, sid);
709
710 /* save and refresh */
711 device_mobile_save_operator_name (self,
712 "ControlCenter::OperatorNameCdma",
713 operator_name);
714 }
715
716 static void
717 device_mobile_device_got_modem_manager_cdma_cb (GObject *source_object,
718 GAsyncResult *res,
719 gpointer user_data)
720 {
721 g_autoptr(GError) error = NULL;
722 NetDeviceMobile *self = (NetDeviceMobile *)user_data;
723
724 self->cdma_proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
725 if (self->cdma_proxy == NULL) {
726 g_warning ("Error creating ModemManager CDMA proxy: %s\n",
727 error->message);
728 return;
729 }
730
731 /* Load initial value */
732 g_dbus_proxy_call (self->cdma_proxy,
733 "GetServingSystem",
734 NULL,
735 G_DBUS_CALL_FLAGS_NONE,
736 -1,
737 NULL,
738 device_mobile_get_serving_system_cb,
739 self);
740 }
741
742 static void
743 operator_name_updated (NetDeviceMobile *self)
744 {
745 device_mobile_refresh_operator_name (self);
746 }
747
748 static void
749 net_device_mobile_dispose (GObject *object)
750 {
751 NetDeviceMobile *self = NET_DEVICE_MOBILE (object);
752
753 g_cancellable_cancel (self->cancellable);
754
755 g_clear_object (&self->client);
756 g_clear_object (&self->device);
757 g_clear_object (&self->modem);
758 g_clear_object (&self->cancellable);
759 g_clear_object (&self->gsm_proxy);
760 g_clear_object (&self->cdma_proxy);
761 g_clear_object (&self->mm_object);
762 g_clear_object (&self->mpd);
763
764 G_OBJECT_CLASS (net_device_mobile_parent_class)->dispose (object);
765 }
766
767 static void
768 net_device_mobile_class_init (NetDeviceMobileClass *klass)
769 {
770 GObjectClass *object_class = G_OBJECT_CLASS (klass);
771 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
772
773 object_class->dispose = net_device_mobile_dispose;
774
775 gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/network/network-mobile.ui");
776
777 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, device_label);
778 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, device_off_switch);
779 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns4_heading_label);
780 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns4_label);
781 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns6_heading_label);
782 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, dns6_label);
783 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, imei_heading_label);
784 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, imei_label);
785 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv4_heading_label);
786 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv4_label);
787 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv6_heading_label);
788 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, ipv6_label);
789 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, mobile_connections_list_store);
790 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, network_combo);
791 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, network_label);
792 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, options_button);
793 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, provider_heading_label);
794 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, provider_label);
795 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, route_heading_label);
796 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, route_label);
797 gtk_widget_class_bind_template_child (widget_class, NetDeviceMobile, status_label);
798
799 gtk_widget_class_bind_template_callback (widget_class, device_off_switch_changed_cb);
800 gtk_widget_class_bind_template_callback (widget_class, network_combo_changed_cb);
801 gtk_widget_class_bind_template_callback (widget_class, options_button_clicked_cb);
802 }
803
804 static void
805 net_device_mobile_init (NetDeviceMobile *self)
806 {
807 g_autofree gchar *path = NULL;
808
809 gtk_widget_init_template (GTK_WIDGET (self));
810
811 self->cancellable = g_cancellable_new ();
812
813 path = g_find_program_in_path ("nm-connection-editor");
814 gtk_widget_set_visible (GTK_WIDGET (self->options_button), path != NULL);
815 }
816
817 NetDeviceMobile *
818 net_device_mobile_new (NMClient *client, NMDevice *device, GDBusObject *modem)
819 {
820 NetDeviceMobile *self;
821 NMDeviceModemCapabilities caps;
822
823 self = g_object_new (net_device_mobile_get_type (), NULL);
824 self->client = g_object_ref (client);
825 self->device = g_object_ref (device);
826
827 g_signal_connect_object (device, "state-changed", G_CALLBACK (nm_device_mobile_refresh_ui), self, G_CONNECT_SWAPPED);
828
829 if (modem != NULL) {
830 MMModem3gpp *modem_3gpp;
831
832 self->modem = g_object_ref (modem);
833
834 /* Load equipment ID initially */
835 device_mobile_refresh_equipment_id (self);
836
837 /* Follow changes in operator name and load initial values */
838 modem_3gpp = mm_object_peek_modem_3gpp (self->mm_object);
839 if (modem_3gpp != NULL) {
840 g_signal_connect_object (modem_3gpp,
841 "notify::operator-name",
842 G_CALLBACK (operator_name_updated),
843 self,
844 G_CONNECT_SWAPPED);
845 device_mobile_refresh_operator_name (self);
846 }
847 }
848
849 caps = nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device));
850
851 /* Only load proxies if we have broadband modems of the OLD ModemManager interface */
852 if (g_str_has_prefix (nm_device_get_udi (device), "/org/freedesktop/ModemManager/") &&
853 ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
854 (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) ||
855 (caps & NM_DEVICE_MODEM_CAPABILITY_LTE))) {
856 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
857 G_DBUS_PROXY_FLAGS_NONE,
858 NULL,
859 "org.freedesktop.ModemManager",
860 nm_device_get_udi (device),
861 "org.freedesktop.ModemManager.Modem",
862 self->cancellable,
863 device_mobile_device_got_modem_manager_cb,
864 self);
865
866 if ((caps & NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS) ||
867 (caps & NM_DEVICE_MODEM_CAPABILITY_LTE)) {
868 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
869 G_DBUS_PROXY_FLAGS_NONE,
870 NULL,
871 "org.freedesktop.ModemManager",
872 nm_device_get_udi (device),
873 "org.freedesktop.ModemManager.Modem.Gsm.Network",
874 self->cancellable,
875 device_mobile_device_got_modem_manager_gsm_cb,
876 self);
877 }
878
879 if (caps & NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO) {
880 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
881 G_DBUS_PROXY_FLAGS_NONE,
882 NULL,
883 "org.freedesktop.ModemManager",
884 nm_device_get_udi (device),
885 "org.freedesktop.ModemManager.Modem.Cdma",
886 self->cancellable,
887 device_mobile_device_got_modem_manager_cdma_cb,
888 self);
889 }
890 }
891
892 g_signal_connect_object (client, "notify::wwan-enabled",
893 G_CALLBACK (mobilebb_enabled_toggled),
894 self, G_CONNECT_SWAPPED);
895 nm_device_mobile_refresh_ui (self);
896
897 return self;
898 }
899
900 NMDevice *
901 net_device_mobile_get_device (NetDeviceMobile *self)
902 {
903 g_return_val_if_fail (NET_IS_DEVICE_MOBILE (self), NULL);
904 return self->device;
905 }
906
907 void
908 net_device_mobile_set_title (NetDeviceMobile *self, const gchar *title)
909 {
910 g_return_if_fail (NET_IS_DEVICE_MOBILE (self));
911 gtk_label_set_label (self->device_label, title);
912 }
913