~tiagoporangaba/ubuntu/saucy/network-manager-applet/fix-for-981472

« back to all changes in this revision

Viewing changes to .pc/lp330608_dxteam_gsm_connect_text.patch/src/applet-device-broadband.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2013-03-08 11:47:45 UTC
  • mfrom: (105.1.1 raring-proposed)
  • Revision ID: package-import@ubuntu.com-20130308114745-7p3ns9ikmfcluod4
Tags: 0.9.8.0-1ubuntu2
debian/control: add docbook-to-man to Build-Depends, missing in the
previous upload.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
/* NetworkManager Applet -- allow user control over networking
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
16
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
17
 *
 
18
 * (C) Copyright 2012 Aleksander Morgado <aleksander@gnu.org>
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#include <ctype.h>
 
26
 
 
27
#include <glib/gi18n.h>
 
28
#include <gtk/gtk.h>
 
29
 
 
30
#include <nm-device.h>
 
31
#include <nm-device-modem.h>
 
32
#include <nm-utils.h>
 
33
#include <gnome-keyring.h>
 
34
 
 
35
#include "applet.h"
 
36
#include "applet-device-broadband.h"
 
37
#include "applet-dialogs.h"
 
38
#include "mobile-helpers.h"
 
39
#include "nm-ui-utils.h"
 
40
#include "mb-menu-item.h"
 
41
 
 
42
typedef struct {
 
43
        NMApplet *applet;
 
44
        NMDevice *device;
 
45
 
 
46
        MMObject     *mm_object;
 
47
        MMModem      *mm_modem;
 
48
        MMModem3gpp  *mm_modem_3gpp;
 
49
        MMModemCdma  *mm_modem_cdma;
 
50
        MMSim        *mm_sim;
 
51
 
 
52
        /* Operator info */
 
53
        gchar *operator_name;
 
54
        guint operator_name_update_id;
 
55
        guint operator_code_update_id;
 
56
        guint sid_update_id;
 
57
        NMAMobileProvidersDatabase *mpd;
 
58
 
 
59
        /* Unlock dialog stuff */
 
60
        GtkWidget *dialog;
 
61
        gpointer keyring_id;
 
62
} BroadbandDeviceInfo;
 
63
 
 
64
/********************************************************************/
 
65
 
 
66
static gboolean
 
67
new_auto_connection (NMDevice *device,
 
68
                     gpointer dclass_data,
 
69
                     AppletNewAutoConnectionCallback callback,
 
70
                     gpointer callback_data)
 
71
{
 
72
        return mobile_helper_wizard (nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)),
 
73
                                     callback,
 
74
                                     callback_data);
 
75
}
 
76
 
 
77
/********************************************************************/
 
78
 
 
79
typedef struct {
 
80
        NMApplet *applet;
 
81
        NMDevice *device;
 
82
} ConnectNetworkInfo;
 
83
 
 
84
static void
 
85
add_and_activate_connection_done (NMClient *client,
 
86
                                  NMActiveConnection *active,
 
87
                                  const char *connection_path,
 
88
                                  GError *error,
 
89
                                  gpointer user_data)
 
90
{
 
91
        if (error)
 
92
                g_warning ("Failed to add/activate connection: (%d) %s", error->code, error->message);
 
93
}
 
94
 
 
95
static void
 
96
wizard_done (NMConnection *connection,
 
97
             gboolean auto_created,
 
98
             gboolean canceled,
 
99
             gpointer user_data)
 
100
{
 
101
        ConnectNetworkInfo *info = user_data;
 
102
 
 
103
        if (canceled == FALSE) {
 
104
                g_return_if_fail (connection != NULL);
 
105
 
 
106
                /* Ask NM to add the new connection and activate it; NM will fill in the
 
107
                 * missing details based on the specific object and the device.
 
108
                 */
 
109
                nm_client_add_and_activate_connection (info->applet->nm_client,
 
110
                                                       connection,
 
111
                                                       info->device,
 
112
                                                       "/",
 
113
                                                       add_and_activate_connection_done,
 
114
                                                       info->applet);
 
115
        }
 
116
 
 
117
        g_object_unref (info->device);
 
118
        g_free (info);
 
119
}
 
120
 
 
121
void
 
122
applet_broadband_connect_network (NMApplet *applet,
 
123
                                  NMDevice *device)
 
124
{
 
125
        ConnectNetworkInfo *info;
 
126
 
 
127
        info = g_malloc0 (sizeof (*info));
 
128
        info->applet = applet;
 
129
        info->device = g_object_ref (device);
 
130
 
 
131
        if (!mobile_helper_wizard (nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)),
 
132
                                   wizard_done,
 
133
                                   info)) {
 
134
                g_warning ("Couldn't run mobile wizard for broadband device");
 
135
                g_object_unref (info->device);
 
136
                g_free (info);
 
137
        }
 
138
}
 
139
 
 
140
/********************************************************************/
 
141
 
 
142
static void unlock_dialog_new (NMDevice *device,
 
143
                               BroadbandDeviceInfo *info);
 
144
 
 
145
static void
 
146
unlock_dialog_destroy (BroadbandDeviceInfo *info)
 
147
{
 
148
        gtk_widget_destroy (info->dialog);
 
149
        info->dialog = NULL;
 
150
}
 
151
 
 
152
static void
 
153
dialog_sim_send_puk_ready (MMSim *sim,
 
154
                           GAsyncResult *res,
 
155
                           BroadbandDeviceInfo *info)
 
156
{
 
157
        GError *error = NULL;
 
158
 
 
159
        if (!mm_sim_send_puk_finish (sim, res, &error)) {
 
160
                const gchar *msg;
 
161
 
 
162
                if (g_error_matches (error,
 
163
                                     MM_MOBILE_EQUIPMENT_ERROR,
 
164
                                     MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD))
 
165
                        msg = _("Wrong PUK code; please contact your provider.");
 
166
                else {
 
167
                        g_dbus_error_strip_remote_error (error);
 
168
                        msg = error ? error->message : NULL;
 
169
                }
 
170
 
 
171
                applet_mobile_pin_dialog_stop_spinner (info->dialog, msg);
 
172
 
 
173
                g_warning ("Failed to send PUK to devid: '%s' simid: '%s' : %s",
 
174
                           mm_modem_get_device_identifier (info->mm_modem),
 
175
                           mm_sim_get_identifier (info->mm_sim),
 
176
                           error->message);
 
177
 
 
178
                g_error_free (error);
 
179
                return;
 
180
        }
 
181
 
 
182
        /* Good */
 
183
        unlock_dialog_destroy (info);
 
184
}
 
185
 
 
186
static void
 
187
dialog_sim_send_pin_ready (MMSim *sim,
 
188
                           GAsyncResult *res,
 
189
                           BroadbandDeviceInfo *info)
 
190
{
 
191
        GError *error = NULL;
 
192
 
 
193
        if (!mm_sim_send_pin_finish (sim, res, &error)) {
 
194
                if (g_error_matches (error,
 
195
                                     MM_MOBILE_EQUIPMENT_ERROR,
 
196
                                     MM_MOBILE_EQUIPMENT_ERROR_SIM_PUK)) {
 
197
                        /* Destroy previous dialog and launch a new one rebuilt to ask for PUK */
 
198
                        unlock_dialog_destroy (info);
 
199
                        unlock_dialog_new (info->device, info);
 
200
                } else {
 
201
                        const gchar *msg = NULL;
 
202
 
 
203
                        /* Report error and re-try PIN request */
 
204
                        if (g_error_matches (error,
 
205
                                             MM_MOBILE_EQUIPMENT_ERROR,
 
206
                                             MM_MOBILE_EQUIPMENT_ERROR_INCORRECT_PASSWORD))
 
207
                                msg = _("Wrong PIN code; please contact your provider.");
 
208
                        else {
 
209
                                g_dbus_error_strip_remote_error (error);
 
210
                                msg = error ? error->message : NULL;
 
211
                        }
 
212
 
 
213
                        applet_mobile_pin_dialog_stop_spinner (info->dialog, msg);
 
214
                }
 
215
 
 
216
                g_warning ("Failed to send PIN to devid: '%s' simid: '%s' : %s",
 
217
                           mm_modem_get_device_identifier (info->mm_modem),
 
218
                           mm_sim_get_identifier (info->mm_sim),
 
219
                           error->message);
 
220
 
 
221
                g_error_free (error);
 
222
                return;
 
223
        }
 
224
 
 
225
        /* Good */
 
226
 
 
227
        if (applet_mobile_pin_dialog_get_auto_unlock (info->dialog)) {
 
228
                const gchar *code1;
 
229
 
 
230
                code1 = applet_mobile_pin_dialog_get_entry1 (info->dialog);
 
231
                mobile_helper_save_pin_in_keyring (mm_modem_get_device_identifier (info->mm_modem),
 
232
                                                   mm_sim_get_identifier (info->mm_sim),
 
233
                                                   code1);
 
234
        } else
 
235
                mobile_helper_delete_pin_in_keyring (mm_modem_get_device_identifier (info->mm_modem));
 
236
 
 
237
        unlock_dialog_destroy (info);
 
238
}
 
239
 
 
240
static void
 
241
unlock_dialog_response (GtkDialog *dialog,
 
242
                        gint response,
 
243
                        gpointer user_data)
 
244
{
 
245
        BroadbandDeviceInfo *info = user_data;
 
246
        const char *code1, *code2;
 
247
        MMModemLock lock;
 
248
 
 
249
        if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT) {
 
250
                unlock_dialog_destroy (info);
 
251
                return;
 
252
        }
 
253
 
 
254
        lock = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (info->dialog), "unlock-code"));
 
255
        g_assert (lock == MM_MODEM_LOCK_SIM_PIN || lock == MM_MODEM_LOCK_SIM_PUK);
 
256
 
 
257
        /* Start the spinner to show the progress of the unlock */
 
258
        applet_mobile_pin_dialog_start_spinner (info->dialog, _("Sending unlock code..."));
 
259
 
 
260
        code1 = applet_mobile_pin_dialog_get_entry1 (info->dialog);
 
261
        if (!code1 || !strlen (code1)) {
 
262
                g_warn_if_fail (code1 != NULL);
 
263
                g_warn_if_fail (strlen (code1));
 
264
                unlock_dialog_destroy (info);
 
265
                return;
 
266
        }
 
267
 
 
268
        /* Send the code to ModemManager */
 
269
        if (lock == MM_MODEM_LOCK_SIM_PIN) {
 
270
                mm_sim_send_pin (info->mm_sim,
 
271
                                 code1,
 
272
                                 NULL, /* cancellable */
 
273
                                 (GAsyncReadyCallback)dialog_sim_send_pin_ready,
 
274
                                 info);
 
275
                return;
 
276
        }
 
277
 
 
278
        if (lock == MM_MODEM_LOCK_SIM_PUK) {
 
279
                code2 = applet_mobile_pin_dialog_get_entry2 (info->dialog);
 
280
                if (!code2) {
 
281
                        g_warn_if_fail (code2 != NULL);
 
282
                        unlock_dialog_destroy (info);
 
283
                        return;
 
284
                }
 
285
 
 
286
                mm_sim_send_puk (info->mm_sim,
 
287
                                 code1, /* puk */
 
288
                                 code2, /* new pin */
 
289
                                 NULL, /* cancellable */
 
290
                                 (GAsyncReadyCallback)dialog_sim_send_puk_ready,
 
291
                                 info);
 
292
                return;
 
293
        }
 
294
 
 
295
        g_assert_not_reached ();
 
296
}
 
297
 
 
298
static void
 
299
unlock_dialog_new (NMDevice *device,
 
300
                   BroadbandDeviceInfo *info)
 
301
{
 
302
        MMModemLock lock;
 
303
        const gchar *unlock_required;
 
304
 
 
305
        if (info->dialog)
 
306
                return;
 
307
 
 
308
        /* We can only unlock PIN or PUK here */
 
309
        lock = mm_modem_get_unlock_required (info->mm_modem);
 
310
        if (lock == MM_MODEM_LOCK_SIM_PIN)
 
311
                unlock_required = "sim-pin";
 
312
        else if (lock == MM_MODEM_LOCK_SIM_PUK)
 
313
                unlock_required = "sim-puk";
 
314
        else {
 
315
                g_warning ("Cannot unlock devid: '%s' simid: '%s' : unhandled lock code '%s'",
 
316
                           mm_modem_get_device_identifier (info->mm_modem),
 
317
                           mm_sim_get_identifier (info->mm_sim),
 
318
                           mm_modem_lock_get_string (lock));
 
319
                return;
 
320
        }
 
321
 
 
322
        info->dialog = applet_mobile_pin_dialog_new (unlock_required,
 
323
                                                     nma_utils_get_device_description (device));
 
324
 
 
325
        g_object_set_data (G_OBJECT (info->dialog), "unlock-code", GUINT_TO_POINTER (lock));
 
326
        g_signal_connect (info->dialog, "response", G_CALLBACK (unlock_dialog_response), info);
 
327
 
 
328
        /* Need to resize the dialog after hiding widgets */
 
329
        gtk_window_resize (GTK_WINDOW (info->dialog), 400, 100);
 
330
 
 
331
        /* Show the dialog */
 
332
        gtk_widget_realize (info->dialog);
 
333
        gtk_window_present (GTK_WINDOW (info->dialog));
 
334
}
 
335
 
 
336
static void
 
337
autounlock_sim_send_pin_ready (MMSim *sim,
 
338
                               GAsyncResult *res,
 
339
                               BroadbandDeviceInfo *info)
 
340
{
 
341
        GError *error = NULL;
 
342
 
 
343
        if (!mm_sim_send_pin_finish (sim, res, &error)) {
 
344
                g_warning ("Failed to auto-unlock devid: '%s' simid: '%s' : %s",
 
345
                           mm_modem_get_device_identifier (info->mm_modem),
 
346
                           mm_sim_get_identifier (info->mm_sim),
 
347
                           error->message);
 
348
                g_error_free (error);
 
349
 
 
350
                /* Remove PIN from keyring right away */
 
351
                mobile_helper_delete_pin_in_keyring (mm_modem_get_device_identifier (info->mm_modem));
 
352
 
 
353
                /* Ask the user */
 
354
                unlock_dialog_new (info->device, info);
 
355
        }
 
356
}
 
357
 
 
358
static void
 
359
keyring_pin_check_cb (GnomeKeyringResult result,
 
360
                      GList *list,
 
361
                      gpointer user_data)
 
362
{
 
363
        BroadbandDeviceInfo *info = user_data;
 
364
        GList *iter;
 
365
        const char *pin = NULL;
 
366
        const char *simid;
 
367
 
 
368
        info->keyring_id = NULL;
 
369
 
 
370
        if (result != GNOME_KEYRING_RESULT_OK) {
 
371
                /* No saved PIN, just ask the user */
 
372
                unlock_dialog_new (info->device, info);
 
373
                return;
 
374
        }
 
375
 
 
376
        /* Look for a result with a matching "simid" attribute since that's
 
377
         * better than just using a matching "devid".  The PIN is really tied
 
378
         * to the SIM, not the modem itself.
 
379
         */
 
380
        simid = mm_sim_get_identifier (info->mm_sim);
 
381
        if (simid) {
 
382
                for (iter = list;
 
383
                     (pin == NULL) && iter;
 
384
                     iter = g_list_next (iter)) {
 
385
                        GnomeKeyringFound *found = iter->data;
 
386
                        int i;
 
387
 
 
388
                        /* Look for a matching "simid" attribute */
 
389
                        for (i = 0; (pin == NULL) && i < found->attributes->len; i++) {
 
390
                                GnomeKeyringAttribute attr = gnome_keyring_attribute_list_index (found->attributes, i);
 
391
 
 
392
                                if (g_strcmp0 (attr.name, "simid") == 0 &&
 
393
                                    attr.type == GNOME_KEYRING_ATTRIBUTE_TYPE_STRING &&
 
394
                                    g_strcmp0 (attr.value.string, simid) == 0) {
 
395
                                        pin = found->secret;
 
396
                                        break;
 
397
                                }
 
398
                        }
 
399
                }
 
400
        }
 
401
 
 
402
        if (pin == NULL) {
 
403
                /* Fall back to the first result's PIN */
 
404
                pin = ((GnomeKeyringFound *) list->data)->secret;
 
405
                if (pin == NULL) {
 
406
                        /* Should never get here */
 
407
                        g_warn_if_fail (pin != NULL);
 
408
                        unlock_dialog_new (info->device, info);
 
409
                        return;
 
410
                }
 
411
        }
 
412
 
 
413
        mm_sim_send_pin (info->mm_sim,
 
414
                         pin,
 
415
                         NULL, /* cancellable */
 
416
                         (GAsyncReadyCallback)autounlock_sim_send_pin_ready,
 
417
                         info);
 
418
}
 
419
 
 
420
static void
 
421
modem_get_sim_ready (MMModem *modem,
 
422
                     GAsyncResult *res,
 
423
                     BroadbandDeviceInfo *info)
 
424
{
 
425
        info->mm_sim = mm_modem_get_sim_finish (modem, res, NULL);
 
426
        if (!info->mm_sim)
 
427
                /* Ok, the modem may not need it actually */
 
428
                return;
 
429
 
 
430
        /* Do nothing if we're not locked */
 
431
        if (mm_modem_get_state (info->mm_modem) != MM_MODEM_STATE_LOCKED)
 
432
                return;
 
433
 
 
434
        /* If we have a device ID ask the keyring for any saved SIM-PIN codes */
 
435
        if (mm_modem_get_device_identifier (info->mm_modem) &&
 
436
            mm_modem_get_unlock_required (info->mm_modem) == MM_MODEM_LOCK_SIM_PIN) {
 
437
                g_warn_if_fail (info->keyring_id == NULL);
 
438
                info->keyring_id = gnome_keyring_find_itemsv (GNOME_KEYRING_ITEM_GENERIC_SECRET,
 
439
                                                              keyring_pin_check_cb,
 
440
                                                              info,
 
441
                                                              NULL,
 
442
                                                              "devid",
 
443
                                                              GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
 
444
                                                              mm_modem_get_device_identifier (info->mm_modem),
 
445
                                                              NULL);
 
446
                return;
 
447
        }
 
448
 
 
449
        /* Couldn't get a device ID, but unlock required; present dialog */
 
450
        unlock_dialog_new (info->device, info);
 
451
}
 
452
 
 
453
/********************************************************************/
 
454
 
 
455
static gboolean
 
456
get_secrets (SecretsRequest *req,
 
457
             GError **error)
 
458
{
 
459
        NMDevice *device;
 
460
        BroadbandDeviceInfo *devinfo;
 
461
 
 
462
        device = applet_get_device_for_connection (req->applet, req->connection);
 
463
        if (!device) {
 
464
                g_set_error (error,
 
465
                             NM_SECRET_AGENT_ERROR,
 
466
                             NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
 
467
                             "%s.%d (%s): failed to find device for active connection.",
 
468
                             __FILE__, __LINE__, __func__);
 
469
                return FALSE;
 
470
        }
 
471
 
 
472
        if (!mobile_helper_get_secrets (nm_device_modem_get_current_capabilities (NM_DEVICE_MODEM (device)),
 
473
                                        req,
 
474
                                        error))
 
475
                return FALSE;
 
476
 
 
477
        devinfo = g_object_get_data (G_OBJECT (device), "devinfo");
 
478
        g_assert (devinfo);
 
479
 
 
480
        /* A GetSecrets PIN dialog overrides the initial unlock dialog */
 
481
        if (devinfo->dialog)
 
482
                unlock_dialog_destroy (devinfo);
 
483
 
 
484
        return TRUE;
 
485
}
 
486
 
 
487
/********************************************************************/
 
488
 
 
489
static guint32
 
490
broadband_state_to_mb_state (BroadbandDeviceInfo *info)
 
491
{
 
492
        MMModemState state;
 
493
 
 
494
        state = mm_modem_get_state (info->mm_modem);
 
495
 
 
496
        switch (state) {
 
497
        case MM_MODEM_STATE_FAILED:
 
498
        case MM_MODEM_STATE_UNKNOWN:
 
499
                g_warn_if_reached ();
 
500
        case MM_MODEM_STATE_INITIALIZING:
 
501
        case MM_MODEM_STATE_LOCKED:
 
502
        case MM_MODEM_STATE_DISABLED:
 
503
        case MM_MODEM_STATE_DISABLING:
 
504
        case MM_MODEM_STATE_ENABLING:
 
505
                return MB_STATE_UNKNOWN;
 
506
 
 
507
        case MM_MODEM_STATE_ENABLED:
 
508
                return MB_STATE_IDLE;
 
509
 
 
510
        case MM_MODEM_STATE_SEARCHING:
 
511
                return MB_STATE_SEARCHING;
 
512
 
 
513
        case MM_MODEM_STATE_REGISTERED:
 
514
        case MM_MODEM_STATE_DISCONNECTING:
 
515
        case MM_MODEM_STATE_CONNECTING:
 
516
        case MM_MODEM_STATE_CONNECTED:
 
517
                break;
 
518
        default:
 
519
                g_warn_if_reached ();
 
520
                return MB_STATE_UNKNOWN;
 
521
        }
 
522
 
 
523
        /* home or roaming? */
 
524
 
 
525
        if (info->mm_modem_3gpp) {
 
526
                switch (mm_modem_3gpp_get_registration_state (info->mm_modem_3gpp)) {
 
527
                case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
 
528
                        return MB_STATE_HOME;
 
529
                case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
 
530
                        return MB_STATE_ROAMING;
 
531
                default:
 
532
                        /* Skip, we may be registered in EVDO/CDMA1x instead... */
 
533
                        break;
 
534
                }
 
535
        }
 
536
 
 
537
        if (info->mm_modem_cdma) {
 
538
                /* EVDO state overrides 1X state for now */
 
539
                switch (mm_modem_cdma_get_evdo_registration_state (info->mm_modem_cdma)) {
 
540
                case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
 
541
                        return MB_STATE_HOME;
 
542
                case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
 
543
                        return MB_STATE_ROAMING;
 
544
                case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
 
545
                        /* Assume home... */
 
546
                        return MB_STATE_HOME;
 
547
                default:
 
548
                        /* Skip, we may be registered in CDMA1x instead... */
 
549
                        break;
 
550
                }
 
551
 
 
552
                switch (mm_modem_cdma_get_cdma1x_registration_state (info->mm_modem_cdma)) {
 
553
                case MM_MODEM_CDMA_REGISTRATION_STATE_HOME:
 
554
                        return MB_STATE_HOME;
 
555
                case MM_MODEM_CDMA_REGISTRATION_STATE_ROAMING:
 
556
                        return MB_STATE_ROAMING;
 
557
                case MM_MODEM_CDMA_REGISTRATION_STATE_REGISTERED:
 
558
                        /* Assume home... */
 
559
                        return MB_STATE_HOME;
 
560
                default:
 
561
                        break;
 
562
                }
 
563
        }
 
564
 
 
565
        return MB_STATE_UNKNOWN;
 
566
}
 
567
 
 
568
static guint32
 
569
broadband_act_to_mb_act (BroadbandDeviceInfo *info)
 
570
{
 
571
        MMModemAccessTechnology act;
 
572
 
 
573
        act = mm_modem_get_access_technologies (info->mm_modem);
 
574
 
 
575
        g_return_val_if_fail (act != MM_MODEM_ACCESS_TECHNOLOGY_ANY, MB_TECH_UNKNOWN);
 
576
 
 
577
        /* We get a MASK of values, but we need to report only ONE.
 
578
         * So just return the 'best' one found */
 
579
 
 
580
        /* Prefer 4G technologies over 3G and 2G */
 
581
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_LTE)
 
582
                return MB_TECH_LTE;
 
583
 
 
584
        /* Prefer 3GPP 3G technologies over 3GPP 2G or 3GPP2 */
 
585
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS)
 
586
                return MB_TECH_HSPA_PLUS;
 
587
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_HSPA)
 
588
                return MB_TECH_HSPA;
 
589
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_HSUPA)
 
590
                return MB_TECH_HSUPA;
 
591
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_HSDPA)
 
592
                return MB_TECH_HSDPA;
 
593
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_UMTS)
 
594
                return MB_TECH_UMTS;
 
595
 
 
596
        /* Prefer 3GPP2 3G technologies over 2G */
 
597
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_EVDO0 ||
 
598
            act & MM_MODEM_ACCESS_TECHNOLOGY_EVDOA ||
 
599
            act & MM_MODEM_ACCESS_TECHNOLOGY_EVDOB)
 
600
                return MB_TECH_EVDO;
 
601
 
 
602
        /* Prefer 3GPP 2G technologies over 3GPP2 2G */
 
603
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_EDGE)
 
604
                return MB_TECH_EDGE;
 
605
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_GPRS)
 
606
                return MB_TECH_GPRS;
 
607
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_GSM ||
 
608
                act & MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT)
 
609
                return MB_TECH_GSM;
 
610
 
 
611
        /* Last, 3GPP2 2G */
 
612
        if (act & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT)
 
613
                return MB_TECH_1XRTT;
 
614
 
 
615
        return MB_TECH_UNKNOWN;
 
616
}
 
617
 
 
618
static GdkPixbuf *
 
619
get_icon (NMDevice *device,
 
620
          NMDeviceState state,
 
621
          NMConnection *connection,
 
622
          char **tip,
 
623
          NMApplet *applet)
 
624
{
 
625
        BroadbandDeviceInfo *info;
 
626
 
 
627
        info = g_object_get_data (G_OBJECT (device), "devinfo");
 
628
        g_assert (info);
 
629
 
 
630
        return mobile_helper_get_icon (device,
 
631
                                       state,
 
632
                                       connection,
 
633
                                       tip,
 
634
                                       applet,
 
635
                                       broadband_state_to_mb_state (info),
 
636
                                       broadband_act_to_mb_act (info),
 
637
                                       mm_modem_get_signal_quality (info->mm_modem, NULL),
 
638
                                       (mm_modem_get_state (info->mm_modem) >= MM_MODEM_STATE_ENABLED));
 
639
}
 
640
 
 
641
/********************************************************************/
 
642
 
 
643
typedef struct {
 
644
        NMApplet *applet;
 
645
        NMDevice *device;
 
646
        NMConnection *connection;
 
647
} BroadbandMenuItemInfo;
 
648
 
 
649
static void
 
650
menu_item_info_destroy (BroadbandMenuItemInfo *info)
 
651
{
 
652
        g_object_unref (G_OBJECT (info->device));
 
653
        if (info->connection)
 
654
                g_object_unref (info->connection);
 
655
        g_slice_free (BroadbandMenuItemInfo, info);
 
656
}
 
657
 
 
658
static void
 
659
menu_item_activate (GtkMenuItem *item,
 
660
                    BroadbandMenuItemInfo *info)
 
661
{
 
662
        applet_menu_item_activate_helper (info->device,
 
663
                                          info->connection,
 
664
                                          "/",
 
665
                                          info->applet,
 
666
                                          info);
 
667
}
 
668
 
 
669
static void
 
670
add_connection_item (NMDevice *device,
 
671
                     NMConnection *connection,
 
672
                     GtkWidget *item,
 
673
                     GtkWidget *menu,
 
674
                     NMApplet *applet)
 
675
{
 
676
        BroadbandMenuItemInfo *info;
 
677
 
 
678
        info = g_slice_new0 (BroadbandMenuItemInfo);
 
679
        info->applet = applet;
 
680
        info->device = g_object_ref (G_OBJECT (device));
 
681
        info->connection = connection ? g_object_ref (connection) : NULL;
 
682
 
 
683
        g_signal_connect_data (item, "activate",
 
684
                               G_CALLBACK (menu_item_activate),
 
685
                               info,
 
686
                               (GClosureNotify) menu_item_info_destroy, 0);
 
687
 
 
688
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
689
}
 
690
 
 
691
static void
 
692
add_menu_item (NMDevice *device,
 
693
               guint32 n_devices,
 
694
               NMConnection *active,
 
695
               GtkWidget *menu,
 
696
               NMApplet *applet)
 
697
{
 
698
        BroadbandDeviceInfo *info;
 
699
        char *text;
 
700
        GtkWidget *item;
 
701
        GSList *connections, *all, *iter;
 
702
 
 
703
        info = g_object_get_data (G_OBJECT (device), "devinfo");
 
704
 
 
705
        all = applet_get_all_connections (applet);
 
706
        connections = nm_device_filter_connections (device, all);
 
707
        g_slist_free (all);
 
708
 
 
709
        if (n_devices > 1) {
 
710
                const char *desc;
 
711
 
 
712
                desc = nma_utils_get_device_description (device);
 
713
                text = g_strdup_printf (_("Mobile Broadband (%s)"), desc);
 
714
        } else {
 
715
                text = g_strdup (_("Mobile Broadband"));
 
716
        }
 
717
 
 
718
        item = applet_menu_item_create_device_item_helper (device, applet, text);
 
719
        gtk_widget_set_sensitive (item, FALSE);
 
720
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
721
        gtk_widget_show (item);
 
722
        g_free (text);
 
723
 
 
724
        /* Add the active connection */
 
725
        if (active) {
 
726
                NMSettingConnection *s_con;
 
727
 
 
728
                s_con = nm_connection_get_setting_connection (active);
 
729
                g_assert (s_con);
 
730
 
 
731
                item = nm_mb_menu_item_new (nm_setting_connection_get_id (s_con),
 
732
                                            mm_modem_get_signal_quality (info->mm_modem, NULL),
 
733
                                            info->operator_name,
 
734
                                            TRUE,
 
735
                                            broadband_act_to_mb_act (info),
 
736
                                            broadband_state_to_mb_state (info),
 
737
                                            mm_modem_get_state (info->mm_modem) >= MM_MODEM_STATE_ENABLED,
 
738
                                            applet);
 
739
                gtk_widget_set_sensitive (GTK_WIDGET (item), TRUE);
 
740
                add_connection_item (device, active, item, menu, applet);
 
741
        }
 
742
 
 
743
        /* Notify user of unmanaged or unavailable device */
 
744
        if (nm_device_get_state (device) > NM_DEVICE_STATE_DISCONNECTED) {
 
745
                item = nma_menu_device_get_menu_item (device, applet, NULL);
 
746
                if (item) {
 
747
                        gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
748
                        gtk_widget_show (item);
 
749
                }
 
750
        } else {
 
751
                /* Otherwise show idle registration state or disabled */
 
752
                item = nm_mb_menu_item_new (NULL,
 
753
                                            mm_modem_get_signal_quality (info->mm_modem, NULL),
 
754
                                            info->operator_name,
 
755
                                            FALSE,
 
756
                                            broadband_act_to_mb_act (info),
 
757
                                            broadband_state_to_mb_state (info),
 
758
                                            mm_modem_get_state (info->mm_modem) >= MM_MODEM_STATE_ENABLED,
 
759
                                            applet);
 
760
                gtk_widget_set_sensitive (GTK_WIDGET (item), FALSE);
 
761
                gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
 
762
        }
 
763
 
 
764
        /* Add the default / inactive connection items */
 
765
        if (!nma_menu_device_check_unusable (device)) {
 
766
                if ((!active && g_slist_length (connections)) || (active && g_slist_length (connections) > 1))
 
767
                        applet_menu_item_add_complex_separator_helper (menu, applet, _("Available"), -1);
 
768
 
 
769
                if (g_slist_length (connections)) {
 
770
                        for (iter = connections; iter; iter = g_slist_next (iter)) {
 
771
                                NMConnection *connection = NM_CONNECTION (iter->data);
 
772
 
 
773
                                if (connection != active) {
 
774
                                        item = applet_new_menu_item_helper (connection, NULL, FALSE);
 
775
                                        add_connection_item (device, connection, item, menu, applet);
 
776
                                }
 
777
                        }
 
778
                } else {
 
779
                        /* Default connection item */
 
780
                        item = gtk_check_menu_item_new_with_label (_("New Mobile Broadband connection..."));
 
781
                        add_connection_item (device, NULL, item, menu, applet);
 
782
                }
 
783
        }
 
784
 
 
785
        g_slist_free (connections);
 
786
}
 
787
 
 
788
/********************************************************************/
 
789
 
 
790
static void
 
791
device_state_changed (NMDevice *device,
 
792
                      NMDeviceState new_state,
 
793
                      NMDeviceState old_state,
 
794
                      NMDeviceStateReason reason,
 
795
                      NMApplet *applet)
 
796
{
 
797
        NMConnection *connection;
 
798
        NMSettingConnection *s_con = NULL;
 
799
        char *str = NULL;
 
800
 
 
801
        if (new_state != NM_DEVICE_STATE_ACTIVATED)
 
802
                return;
 
803
 
 
804
        connection = applet_find_active_connection_for_device (device, applet, NULL);
 
805
        if (connection) {
 
806
                const char *id;
 
807
 
 
808
                s_con = nm_connection_get_setting_connection (connection);
 
809
                id = s_con ? nm_setting_connection_get_id (s_con) : NULL;
 
810
                if (id)
 
811
                        str = g_strdup_printf (_("You are now connected to '%s'."), id);
 
812
        }
 
813
 
 
814
        applet_do_notify_with_pref (applet,
 
815
                                    _("Connection Established"),
 
816
                                    str ? str : _("You are now connected to the Mobile Broadband network."),
 
817
                                    "nm-device-wwan",
 
818
                                    PREF_DISABLE_CONNECTED_NOTIFICATIONS);
 
819
        g_free (str);
 
820
}
 
821
 
 
822
/********************************************************************/
 
823
 
 
824
static void
 
825
signal_quality_updated (GObject *object,
 
826
                        GParamSpec *pspec,
 
827
                        BroadbandDeviceInfo *info)
 
828
{
 
829
        applet_schedule_update_icon (info->applet);
 
830
}
 
831
 
 
832
static void
 
833
access_technologies_updated (GObject *object,
 
834
                             GParamSpec *pspec,
 
835
                             BroadbandDeviceInfo *info)
 
836
{
 
837
        applet_schedule_update_icon (info->applet);
 
838
}
 
839
 
 
840
static void
 
841
operator_info_updated (GObject *object,
 
842
                       GParamSpec *pspec,
 
843
                       BroadbandDeviceInfo *info)
 
844
{
 
845
        g_free (info->operator_name);
 
846
        info->operator_name = NULL;
 
847
 
 
848
        /* Prefer 3GPP info if given */
 
849
 
 
850
        if (info->mm_modem_3gpp) {
 
851
                info->operator_name = (mobile_helper_parse_3gpp_operator_name (
 
852
                                               &(info->mpd),
 
853
                                               mm_modem_3gpp_get_operator_name (info->mm_modem_3gpp),
 
854
                                               mm_modem_3gpp_get_operator_code (info->mm_modem_3gpp)));
 
855
                if (info->operator_name)
 
856
                        return;
 
857
        }
 
858
 
 
859
        if (info->mm_modem_cdma)
 
860
                info->operator_name = (mobile_helper_parse_3gpp2_operator_name (
 
861
                                               &(info->mpd),
 
862
                                               mm_modem_cdma_get_sid (info->mm_modem_cdma)));
 
863
}
 
864
 
 
865
static void
 
866
setup_signals (BroadbandDeviceInfo *info,
 
867
               gboolean enable)
 
868
{
 
869
        if (enable) {
 
870
                g_assert (info->mm_modem_3gpp == NULL);
 
871
                g_assert (info->mm_modem_cdma == NULL);
 
872
                g_assert (info->operator_name_update_id == 0);
 
873
                g_assert (info->operator_code_update_id == 0);
 
874
                g_assert (info->sid_update_id == 0);
 
875
 
 
876
                info->mm_modem_3gpp = mm_object_get_modem_3gpp (info->mm_object);
 
877
                info->mm_modem_cdma = mm_object_get_modem_cdma (info->mm_object);
 
878
 
 
879
                if (info->mm_modem_3gpp) {
 
880
                        info->operator_name_update_id = g_signal_connect (info->mm_modem_3gpp,
 
881
                                                                          "notify::operator-name",
 
882
                                                                          G_CALLBACK (operator_info_updated),
 
883
                                                                          info);
 
884
                        info->operator_code_update_id = g_signal_connect (info->mm_modem_3gpp,
 
885
                                                                          "notify::operator-code",
 
886
                                                                          G_CALLBACK (operator_info_updated),
 
887
                                                                          info);
 
888
                }
 
889
 
 
890
                if (info->mm_modem_cdma) {
 
891
                        info->sid_update_id = g_signal_connect (info->mm_modem_cdma,
 
892
                                                                "notify::sid",
 
893
                                                                G_CALLBACK (operator_info_updated),
 
894
                                                                info);
 
895
                }
 
896
 
 
897
                /* Load initial values */
 
898
                operator_info_updated (NULL, NULL, info);
 
899
        } else {
 
900
                if (info->mm_modem_3gpp) {
 
901
                        if (info->operator_name_update_id) {
 
902
                                if (g_signal_handler_is_connected (info->mm_modem_3gpp, info->operator_name_update_id))
 
903
                                        g_signal_handler_disconnect (info->mm_modem_3gpp, info->operator_name_update_id);
 
904
                                info->operator_name_update_id = 0;
 
905
                        }
 
906
                        if (info->operator_code_update_id) {
 
907
                                if (g_signal_handler_is_connected (info->mm_modem_3gpp, info->operator_code_update_id))
 
908
                                        g_signal_handler_disconnect (info->mm_modem_3gpp, info->operator_code_update_id);
 
909
                                info->operator_code_update_id = 0;
 
910
                        }
 
911
                        g_clear_object (&info->mm_modem_3gpp);
 
912
                }
 
913
 
 
914
                if (info->mm_modem_cdma) {
 
915
                        if (info->sid_update_id) {
 
916
                                if (g_signal_handler_is_connected (info->mm_modem_cdma, info->sid_update_id))
 
917
                                        g_signal_handler_disconnect (info->mm_modem_cdma, info->sid_update_id);
 
918
                                info->sid_update_id = 0;
 
919
                        }
 
920
                        g_clear_object (&info->mm_modem_cdma);
 
921
                }
 
922
        }
 
923
}
 
924
 
 
925
static void
 
926
modem_state_changed (MMModem *object,
 
927
                     gint old,
 
928
                     gint new,
 
929
                     guint reason,
 
930
                     BroadbandDeviceInfo *info)
 
931
{
 
932
        /* Modem just got enabled */
 
933
        if (old < MM_MODEM_STATE_ENABLED &&
 
934
            new >= MM_MODEM_STATE_ENABLED) {
 
935
                setup_signals (info, TRUE);
 
936
        }
 
937
        /* Modem just got disabled */
 
938
        else if (old >= MM_MODEM_STATE_ENABLED &&
 
939
            new < MM_MODEM_STATE_ENABLED) {
 
940
                setup_signals (info, FALSE);
 
941
        }
 
942
 
 
943
        /* Modem just got registered */
 
944
        if ((old < MM_MODEM_STATE_REGISTERED &&
 
945
             new >= MM_MODEM_STATE_REGISTERED)) {
 
946
                guint32 mb_state;
 
947
 
 
948
                /* Notify about new registration info */
 
949
                mb_state = broadband_state_to_mb_state (info);
 
950
                if (mb_state == MB_STATE_HOME) {
 
951
                        applet_do_notify_with_pref (info->applet,
 
952
                                                    _("Mobile Broadband network."),
 
953
                                                    _("You are now registered on the home network."),
 
954
                                                    "nm-signal-100",
 
955
                                                    PREF_DISABLE_CONNECTED_NOTIFICATIONS);
 
956
                } else if (mb_state == MB_STATE_ROAMING) {
 
957
                        applet_do_notify_with_pref (info->applet,
 
958
                                                    _("Mobile Broadband network."),
 
959
                                                    _("You are now registered on a roaming network."),
 
960
                                                    "nm-signal-100",
 
961
                                                    PREF_DISABLE_CONNECTED_NOTIFICATIONS);
 
962
                }
 
963
        }
 
964
}
 
965
 
 
966
/********************************************************************/
 
967
 
 
968
static void
 
969
broadband_device_info_free (BroadbandDeviceInfo *info)
 
970
{
 
971
        setup_signals (info, FALSE);
 
972
 
 
973
        g_free (info->operator_name);
 
974
        if (info->mpd)
 
975
                g_object_unref (info->mpd);
 
976
 
 
977
        if (info->mm_sim)
 
978
                g_object_unref (info->mm_sim);
 
979
        if (info->mm_modem)
 
980
                g_object_unref (info->mm_modem);
 
981
        if (info->mm_object)
 
982
                g_object_unref (info->mm_object);
 
983
 
 
984
        if (info->keyring_id)
 
985
                gnome_keyring_cancel_request (info->keyring_id);
 
986
        if (info->dialog)
 
987
                unlock_dialog_destroy (info);
 
988
 
 
989
        g_slice_free (BroadbandDeviceInfo, info);
 
990
}
 
991
 
 
992
static void
 
993
device_added (NMDevice *device,
 
994
              NMApplet *applet)
 
995
{
 
996
        NMDeviceModem *modem = NM_DEVICE_MODEM (device);
 
997
        BroadbandDeviceInfo *info;
 
998
        const char *udi;
 
999
        GDBusObject *modem_object;
 
1000
 
 
1001
        udi = nm_device_get_udi (device);
 
1002
        if (!udi)
 
1003
                return;
 
1004
 
 
1005
        if (!applet->mm1) {
 
1006
                g_warning ("Cannot grab information for modem at %s: No ModemManager support",
 
1007
                           nm_device_get_udi (device));
 
1008
                return;
 
1009
        }
 
1010
 
 
1011
        modem_object = g_dbus_object_manager_get_object (G_DBUS_OBJECT_MANAGER (applet->mm1),
 
1012
                                                         nm_device_get_udi (device));
 
1013
        if (!modem_object) {
 
1014
                g_warning ("Cannot grab information for modem at %s: Not found",
 
1015
                           nm_device_get_udi (device));
 
1016
                return;
 
1017
        }
 
1018
 
 
1019
        info = g_slice_new0 (BroadbandDeviceInfo);
 
1020
        info->applet = applet;
 
1021
        info->device = device;
 
1022
        info->mm_object = MM_OBJECT (modem_object);
 
1023
        info->mm_modem = mm_object_get_modem (info->mm_object);
 
1024
 
 
1025
        /* Setup signals */
 
1026
 
 
1027
        g_signal_connect (info->mm_modem,
 
1028
                          "state-changed",
 
1029
                          G_CALLBACK (modem_state_changed),
 
1030
                          info);
 
1031
        g_signal_connect (info->mm_modem,
 
1032
                          "notify::signal-quality",
 
1033
                          G_CALLBACK (signal_quality_updated),
 
1034
                          info);
 
1035
        g_signal_connect (info->mm_modem,
 
1036
                          "notify::access-technologies",
 
1037
                          G_CALLBACK (access_technologies_updated),
 
1038
                          info);
 
1039
 
 
1040
        /* Load initial values */
 
1041
        signal_quality_updated (NULL, NULL, info);
 
1042
        access_technologies_updated (NULL, NULL, info);
 
1043
        if (mm_modem_get_state (info->mm_modem) >= MM_MODEM_STATE_ENABLED)
 
1044
                setup_signals (info, TRUE);
 
1045
 
 
1046
        /* Asynchronously get SIM */
 
1047
        mm_modem_get_sim (info->mm_modem,
 
1048
                          NULL, /* cancellable */
 
1049
                          (GAsyncReadyCallback)modem_get_sim_ready,
 
1050
                          info);
 
1051
 
 
1052
        /* Store device info */
 
1053
        g_object_set_data_full (G_OBJECT (modem),
 
1054
                                "devinfo",
 
1055
                                info,
 
1056
                                (GDestroyNotify)broadband_device_info_free);
 
1057
}
 
1058
 
 
1059
/********************************************************************/
 
1060
 
 
1061
NMADeviceClass *
 
1062
applet_device_broadband_get_class (NMApplet *applet)
 
1063
{
 
1064
        NMADeviceClass *dclass;
 
1065
 
 
1066
        dclass = g_slice_new0 (NMADeviceClass);
 
1067
        if (!dclass)
 
1068
                return NULL;
 
1069
 
 
1070
        dclass->new_auto_connection = new_auto_connection;
 
1071
        dclass->add_menu_item = add_menu_item;
 
1072
        dclass->device_added = device_added;
 
1073
        dclass->device_state_changed = device_state_changed;
 
1074
        dclass->get_icon = get_icon;
 
1075
        dclass->get_secrets = get_secrets;
 
1076
        dclass->secrets_request_size = sizeof (MobileHelperSecretsInfo);
 
1077
 
 
1078
        return dclass;
 
1079
}