LCOV - code coverage report
Current view: top level - src/plugins/connectivity_report - valent-telephony.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 87.5 % 160 140
Test Date: 2024-03-22 06:22:29 Functions: 100.0 % 17 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 51.2 % 121 62

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-telephony"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <gio/gio.h>
       9                 :             : #include <json-glib/json-glib.h>
      10                 :             : #include <valent.h>
      11                 :             : 
      12                 :             : #include "valent-telephony.h"
      13                 :             : 
      14                 :             : 
      15                 :             : /**
      16                 :             :  * ValentTelephony:
      17                 :             :  *
      18                 :             :  * A class for controlling pointer and keyboard devices.
      19                 :             :  *
      20                 :             :  * `ValentTelephony` is an abstraction of telephony support, intended for use by
      21                 :             :  * [class@Valent.DevicePlugin] implementations.
      22                 :             :  */
      23                 :             : 
      24                 :             : struct _ValentTelephony
      25                 :             : {
      26                 :             :   ValentObject        parent_instance;
      27                 :             : 
      28                 :             :   GDBusObjectManager *manager;
      29                 :             :   GDBusProxy         *modem;
      30                 :             :   GHashTable         *modems;
      31                 :             : };
      32                 :             : 
      33   [ +  +  +  - ]:          25 : G_DEFINE_FINAL_TYPE (ValentTelephony, valent_telephony, VALENT_TYPE_OBJECT)
      34                 :             : 
      35                 :             : enum {
      36                 :             :   CHANGED,
      37                 :             :   N_SIGNALS
      38                 :             : };
      39                 :             : 
      40                 :             : static guint signals[N_SIGNALS] = { 0, };
      41                 :             : 
      42                 :             : 
      43                 :             : static ValentTelephony *default_telephony = NULL;
      44                 :             : 
      45                 :             : /*
      46                 :             :  * ModemManager-enums.h
      47                 :             :  */
      48                 :             : typedef enum { /*< underscore_name=mm_modem_access_technology >*/
      49                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN     = 0,
      50                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_POTS        = 1 << 0,
      51                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_GSM         = 1 << 1,
      52                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT = 1 << 2,
      53                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_GPRS        = 1 << 3,
      54                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_EDGE        = 1 << 4,
      55                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_UMTS        = 1 << 5,
      56                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_HSDPA       = 1 << 6,
      57                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_HSUPA       = 1 << 7,
      58                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_HSPA        = 1 << 8,
      59                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS   = 1 << 9,
      60                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_1XRTT       = 1 << 10,
      61                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_EVDO0       = 1 << 11,
      62                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_EVDOA       = 1 << 12,
      63                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_EVDOB       = 1 << 13,
      64                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_LTE         = 1 << 14,
      65                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_5GNR        = 1 << 15,
      66                 :             :   MM_MODEM_ACCESS_TECHNOLOGY_ANY         = 0xFFFFFFFF,
      67                 :             : } ValentModemAccessTechnology;
      68                 :             : 
      69                 :             : typedef enum { /*< underscore_name=mm_modem_state >*/
      70                 :             :   MM_MODEM_STATE_FAILED        = -1,
      71                 :             :   MM_MODEM_STATE_UNKNOWN       = 0,
      72                 :             :   MM_MODEM_STATE_INITIALIZING  = 1,
      73                 :             :   MM_MODEM_STATE_LOCKED        = 2,
      74                 :             :   MM_MODEM_STATE_DISABLED      = 3,
      75                 :             :   MM_MODEM_STATE_DISABLING     = 4,
      76                 :             :   MM_MODEM_STATE_ENABLING      = 5,
      77                 :             :   MM_MODEM_STATE_ENABLED       = 6,
      78                 :             :   MM_MODEM_STATE_SEARCHING     = 7,
      79                 :             :   MM_MODEM_STATE_REGISTERED    = 8,
      80                 :             :   MM_MODEM_STATE_DISCONNECTING = 9,
      81                 :             :   MM_MODEM_STATE_CONNECTING    = 10,
      82                 :             :   MM_MODEM_STATE_CONNECTED     = 11,
      83                 :             : } ValentModemState;
      84                 :             : 
      85                 :             : 
      86                 :             : static inline const char *
      87                 :           6 : get_telephony_type_string (unsigned int flags)
      88                 :             : {
      89   [ -  -  -  -  :           6 :   switch (flags)
             -  -  +  -  
                      + ]
      90                 :             :     {
      91                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN:
      92                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_POTS:
      93                 :             :       return "Unknown";
      94                 :             : 
      95                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_GSM:
      96                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT:
      97                 :           0 :       return "GSM";
      98                 :             : 
      99                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_GPRS:
     100                 :           0 :       return "GPRS";
     101                 :             : 
     102                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_EDGE:
     103                 :           0 :       return "EDGE";
     104                 :             : 
     105                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_UMTS:
     106                 :           0 :       return "UMTS";
     107                 :             : 
     108                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_HSDPA:
     109                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_HSUPA:
     110                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_HSUPA | MM_MODEM_ACCESS_TECHNOLOGY_HSDPA:
     111                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_HSPA:
     112                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS:
     113                 :           0 :       return "HSPA";
     114                 :             : 
     115                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_1XRTT:
     116                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_EVDO0:
     117                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_EVDOA:
     118                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_EVDOB:
     119                 :           0 :       return "CDMA2000";
     120                 :             : 
     121                 :           2 :     case MM_MODEM_ACCESS_TECHNOLOGY_LTE:
     122                 :           2 :       return "LTE";
     123                 :             : 
     124                 :           0 :     case MM_MODEM_ACCESS_TECHNOLOGY_5GNR:
     125                 :           0 :       return "5G";
     126                 :             : 
     127                 :             :     case MM_MODEM_ACCESS_TECHNOLOGY_ANY:
     128                 :             :       return "Unknown";
     129                 :             : 
     130                 :             :     default:
     131                 :             :       return "Unknown";
     132                 :             :     }
     133                 :             : }
     134                 :             : 
     135                 :             : static void
     136                 :           4 : on_properties_changed (GDBusProxy      *proxy,
     137                 :             :                        GVariant        *changed_properties,
     138                 :             :                        GStrv            invalidated,
     139                 :             :                        ValentTelephony *self)
     140                 :             : {
     141                 :           4 :   GVariantIter iter;
     142                 :           4 :   const char *property;
     143                 :           4 :   GVariant *value;
     144                 :           4 :   gboolean changed = FALSE;
     145                 :             : 
     146                 :           4 :   g_variant_iter_init (&iter, changed_properties);
     147                 :             : 
     148         [ +  + ]:          44 :   while (g_variant_iter_loop (&iter, "{sv}", &property, &value))
     149                 :             :     {
     150         [ +  + ]:          40 :       if (g_str_equal (property, "AccessTechnologies"))
     151                 :             :         changed = TRUE;
     152         [ +  + ]:          36 :       else if (g_str_equal (property, "SignalQuality"))
     153                 :             :         changed = TRUE;
     154         [ +  + ]:          32 :       else if (g_str_equal (property, "State"))
     155                 :          12 :         changed = TRUE;
     156                 :             :     }
     157                 :             : 
     158         [ +  - ]:           4 :   if (changed)
     159                 :           4 :     g_signal_emit (G_OBJECT (self), signals [CHANGED], 0);
     160                 :           4 : }
     161                 :             : 
     162                 :             : static void
     163                 :           2 : g_dbus_proxy_new_for_bus_cb (GObject      *object,
     164                 :             :                              GAsyncResult *result,
     165                 :             :                              gpointer      user_data)
     166                 :             : {
     167                 :           2 :   g_autoptr (ValentTelephony) self = VALENT_TELEPHONY (user_data);
     168         [ -  - ]:           2 :   g_autoptr (GDBusProxy) proxy = NULL;
     169         [ -  - ]:           2 :   g_autoptr (GError) error = NULL;
     170                 :           2 :   const char *object_path;
     171                 :             : 
     172                 :           2 :   proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
     173                 :             : 
     174         [ -  + ]:           2 :   if (proxy == NULL)
     175                 :             :     {
     176                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, error->message);
     177         [ #  # ]:           0 :       return;
     178                 :             :     }
     179                 :             : 
     180                 :           2 :   g_signal_connect_object (proxy,
     181                 :             :                            "g-properties-changed",
     182                 :             :                            G_CALLBACK (on_properties_changed),
     183                 :             :                            self, 0);
     184                 :             : 
     185                 :           2 :   object_path = g_dbus_proxy_get_object_path (proxy);
     186         [ -  + ]:           2 :   g_hash_table_replace (self->modems,
     187                 :           2 :                         g_strdup (object_path),
     188                 :             :                         g_steal_pointer (&proxy));
     189                 :             : 
     190         [ -  + ]:           2 :   g_signal_emit (G_OBJECT (self), signals [CHANGED], 0);
     191                 :             : }
     192                 :             : 
     193                 :             : static void
     194                 :           2 : on_modem_added (GDBusObjectManager *manager,
     195                 :             :                 GDBusObject        *object,
     196                 :             :                 ValentTelephony    *self)
     197                 :             : {
     198                 :           2 :   const char *object_path;
     199                 :             : 
     200   [ +  -  +  -  :           2 :   g_assert (G_IS_DBUS_OBJECT_MANAGER (manager));
             +  -  -  + ]
     201   [ +  -  +  -  :           2 :   g_assert (G_IS_DBUS_OBJECT (object));
             +  -  -  + ]
     202         [ -  + ]:           2 :   g_assert (VALENT_IS_TELEPHONY (self));
     203                 :             : 
     204                 :           2 :   object_path = g_dbus_object_get_object_path (object);
     205                 :             : 
     206   [ +  -  +  -  :           2 :   if (!g_str_has_prefix (object_path, "/org/freedesktop/ModemManager1/Modem"))
                   -  + ]
     207                 :           0 :     return;
     208                 :             : 
     209                 :           2 :   g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
     210                 :             :                             G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
     211                 :             :                             NULL,
     212                 :             :                             "org.freedesktop.ModemManager1",
     213                 :             :                             object_path,
     214                 :             :                             "org.freedesktop.ModemManager1.Modem",
     215                 :             :                             NULL,
     216                 :             :                             (GAsyncReadyCallback)g_dbus_proxy_new_for_bus_cb,
     217                 :             :                             g_object_ref (self));
     218                 :             : }
     219                 :             : 
     220                 :             : static void
     221                 :           2 : on_modem_removed (GDBusObjectManager *manager,
     222                 :             :                   GDBusObject        *object,
     223                 :             :                   ValentTelephony    *self)
     224                 :             : {
     225                 :           2 :   const char *object_path;
     226                 :             : 
     227   [ +  -  +  -  :           2 :   g_assert (G_IS_DBUS_OBJECT_MANAGER (manager));
             +  -  -  + ]
     228   [ +  -  +  -  :           2 :   g_assert (G_IS_DBUS_OBJECT (object));
             +  -  -  + ]
     229         [ -  + ]:           2 :   g_assert (VALENT_IS_TELEPHONY (self));
     230                 :             : 
     231                 :           2 :   object_path = g_dbus_object_get_object_path (object);
     232                 :             : 
     233   [ +  -  +  -  :           2 :   if (!g_str_has_prefix (object_path, "/org/freedesktop/ModemManager1/Modem"))
                   -  + ]
     234                 :           0 :     return;
     235                 :             : 
     236         [ +  - ]:           2 :   if (g_hash_table_remove (self->modems, object_path))
     237                 :           2 :     g_signal_emit (G_OBJECT (self), signals [CHANGED], 0);
     238                 :             : }
     239                 :             : 
     240                 :             : static void
     241                 :           3 : g_dbus_object_manager_client_new_for_bus_cb (GObject      *object,
     242                 :             :                                              GAsyncResult *result,
     243                 :             :                                              gpointer      user_data)
     244                 :             : {
     245                 :           3 :   g_autoptr (ValentTelephony) self = VALENT_TELEPHONY (user_data);
     246                 :           3 :   g_autolist (GDBusObject) modems = NULL;
     247                 :           3 :   g_autoptr (GError) error = NULL;
     248                 :             : 
     249                 :           3 :   self->manager = g_dbus_object_manager_client_new_for_bus_finish (result,
     250                 :             :                                                                    &error);
     251                 :             : 
     252         [ -  + ]:           3 :   if (self->manager == NULL)
     253                 :             :     {
     254                 :           0 :       g_warning ("%s(): %s", G_STRFUNC, error->message);
     255         [ #  # ]:           0 :       return;
     256                 :             :     }
     257                 :             : 
     258                 :           3 :   modems = g_dbus_object_manager_get_objects (self->manager);
     259                 :             : 
     260         [ +  + ]:           4 :   for (const GList *iter = modems; iter; iter = iter->next)
     261                 :           1 :     on_modem_added (self->manager, iter->data, self);
     262                 :             : 
     263                 :           3 :   g_signal_connect_object (self->manager,
     264                 :             :                            "object-added",
     265                 :             :                            G_CALLBACK (on_modem_added),
     266                 :             :                            self, 0);
     267         [ -  + ]:           3 :   g_signal_connect_object (self->manager,
     268                 :             :                            "object-removed",
     269                 :             :                            G_CALLBACK (on_modem_removed),
     270                 :             :                            self, 0);
     271                 :             : }
     272                 :             : 
     273                 :             : /*
     274                 :             :  * ValentObject
     275                 :             :  */
     276                 :             : static void
     277                 :           1 : valent_telephony_destroy (ValentObject *object)
     278                 :             : {
     279                 :           1 :   ValentTelephony *self = VALENT_TELEPHONY (object);
     280                 :             : 
     281                 :           1 :   g_signal_handlers_disconnect_by_data (self->manager, self);
     282         [ +  - ]:           1 :   g_clear_object (&self->manager);
     283                 :             : 
     284                 :           1 :   VALENT_OBJECT_CLASS (valent_telephony_parent_class)->destroy (object);
     285                 :           1 : }
     286                 :             : 
     287                 :             : /*
     288                 :             :  * GObject
     289                 :             :  */
     290                 :             : static void
     291                 :           3 : valent_telephony_constructed (GObject *object)
     292                 :             : {
     293                 :           3 :   ValentTelephony *self = VALENT_TELEPHONY (object);
     294                 :             : 
     295                 :           3 :   g_dbus_object_manager_client_new_for_bus (G_BUS_TYPE_SYSTEM,
     296                 :             :                                             G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START,
     297                 :             :                                             "org.freedesktop.ModemManager1",
     298                 :             :                                             "/org/freedesktop/ModemManager1",
     299                 :             :                                             NULL, NULL, NULL,
     300                 :             :                                             NULL,
     301                 :             :                                             (GAsyncReadyCallback)g_dbus_object_manager_client_new_for_bus_cb,
     302                 :             :                                             g_object_ref (self));
     303                 :             : 
     304                 :           3 :   G_OBJECT_CLASS (valent_telephony_parent_class)->constructed (object);
     305                 :           3 : }
     306                 :             : 
     307                 :             : static void
     308                 :           1 : valent_telephony_finalize (GObject *object)
     309                 :             : {
     310                 :           1 :   ValentTelephony *self = VALENT_TELEPHONY (object);
     311                 :             : 
     312         [ +  - ]:           1 :   g_clear_pointer (&self->modems, g_hash_table_unref);
     313                 :             : 
     314                 :           1 :   G_OBJECT_CLASS (valent_telephony_parent_class)->finalize (object);
     315                 :           1 : }
     316                 :             : 
     317                 :             : static void
     318                 :           3 : valent_telephony_class_init (ValentTelephonyClass *klass)
     319                 :             : {
     320                 :           3 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     321                 :           3 :   ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
     322                 :             : 
     323                 :           3 :   object_class->constructed = valent_telephony_constructed;
     324                 :           3 :   object_class->finalize = valent_telephony_finalize;
     325                 :             : 
     326                 :           3 :   vobject_class->destroy = valent_telephony_destroy;
     327                 :             : 
     328                 :             :   /**
     329                 :             :    * ValentTelephony::changed:
     330                 :             :    * @self: a `ValentTelephony`
     331                 :             :    *
     332                 :             :    * `ValentTelephony`::changed is emitted whenever a relevant property changes.
     333                 :             :    */
     334                 :           6 :   signals [CHANGED] =
     335                 :           3 :     g_signal_new ("changed",
     336                 :             :                   G_TYPE_FROM_CLASS (klass),
     337                 :             :                   G_SIGNAL_RUN_LAST,
     338                 :             :                   0,
     339                 :             :                   NULL, NULL, NULL,
     340                 :             :                   G_TYPE_NONE, 0);
     341                 :           3 : }
     342                 :             : 
     343                 :             : static void
     344                 :           3 : valent_telephony_init (ValentTelephony *self)
     345                 :             : {
     346                 :           3 :   self->modems = g_hash_table_new_full (g_str_hash,
     347                 :             :                                         g_str_equal,
     348                 :             :                                         g_free,
     349                 :             :                                         g_object_unref);
     350                 :           3 : }
     351                 :             : 
     352                 :             : /**
     353                 :             :  * valent_telephony_get_default:
     354                 :             :  *
     355                 :             :  * Get the default [class@Valent.Network].
     356                 :             :  *
     357                 :             :  * Returns: (transfer none) (not nullable): a `ValentTelephony`
     358                 :             :  *
     359                 :             :  * Since: 1.0
     360                 :             :  */
     361                 :             : ValentTelephony *
     362                 :           4 : valent_telephony_get_default (void)
     363                 :             : {
     364         [ +  + ]:           4 :   if (default_telephony == NULL)
     365                 :             :     {
     366                 :           3 :       default_telephony = g_object_new (VALENT_TYPE_TELEPHONY, NULL);
     367                 :             : 
     368                 :           3 :       g_object_add_weak_pointer (G_OBJECT (default_telephony),
     369                 :             :                                  (gpointer)&default_telephony);
     370                 :             :     }
     371                 :             : 
     372                 :           4 :   return default_telephony;
     373                 :             : }
     374                 :             : 
     375                 :             : static JsonNode *
     376                 :           6 : valent_telephony_serialize_modem (GDBusProxy *proxy)
     377                 :             : {
     378                 :          12 :   g_autoptr (JsonBuilder) builder = NULL;
     379                 :           6 :   GVariant *value;
     380                 :           6 :   unsigned int access_technologies;
     381                 :           6 :   uint32_t signal_quality;
     382                 :           6 :   gboolean signal_recent;
     383                 :           6 :   int32_t state;
     384                 :           6 :   const char *telephony_type;
     385                 :           6 :   int64_t signal_strength = -1;
     386                 :             : 
     387   [ +  -  +  -  :           6 :   g_assert (G_IS_DBUS_PROXY (proxy));
             -  +  -  - ]
     388                 :             : 
     389                 :             :   /* Extract the relevant properties */
     390                 :           6 :   value = g_dbus_proxy_get_cached_property (proxy, "AccessTechnologies");
     391                 :           6 :   g_variant_get (value, "u", &access_technologies);
     392         [ +  - ]:           6 :   g_clear_pointer (&value, g_variant_unref);
     393                 :             : 
     394                 :           6 :   value = g_dbus_proxy_get_cached_property (proxy, "SignalQuality");
     395                 :           6 :   g_variant_get (value, "(ub)", &signal_quality, &signal_recent);
     396         [ +  - ]:           6 :   g_clear_pointer (&value, g_variant_unref);
     397                 :             : 
     398                 :           6 :   value = g_dbus_proxy_get_cached_property (proxy, "State");
     399                 :           6 :   g_variant_get (value, "i", &state);
     400         [ +  - ]:           6 :   g_clear_pointer (&value, g_variant_unref);
     401                 :             : 
     402                 :             :   /* Convert to KDE Connect values (`networkType`, `signalStrength`) */
     403                 :           6 :   telephony_type = get_telephony_type_string (access_technologies);
     404                 :             : 
     405         [ +  + ]:           6 :   if (state >= MM_MODEM_STATE_ENABLED)
     406                 :           2 :     signal_strength = (int64_t)(signal_quality / 20);
     407                 :             : 
     408                 :             :   /* Serialize to a JsonNode */
     409                 :           6 :   builder = json_builder_new ();
     410                 :           6 :   json_builder_begin_object (builder);
     411                 :           6 :   json_builder_set_member_name (builder, "networkType");
     412                 :           6 :   json_builder_add_string_value (builder, telephony_type);
     413                 :           6 :   json_builder_set_member_name (builder, "signalStrength");
     414                 :           6 :   json_builder_add_int_value (builder, signal_strength);
     415                 :           6 :   json_builder_end_object (builder);
     416                 :             : 
     417         [ +  - ]:           6 :   return json_builder_get_root (builder);
     418                 :             : }
     419                 :             : 
     420                 :             : /**
     421                 :             :  * valent_telephony_get_signal_strengths:
     422                 :             :  * @telephony: a `ValentTelephony`
     423                 :             :  *
     424                 :             :  * Get a serialized dictionary of the known modems' status.
     425                 :             :  *
     426                 :             :  * Returns: (transfer full) (nullable): a `JsonNode`
     427                 :             :  *
     428                 :             :  * Since: 1.0
     429                 :             :  */
     430                 :             : JsonNode *
     431                 :           8 : valent_telephony_get_signal_strengths (ValentTelephony *telephony)
     432                 :             : {
     433                 :          16 :   g_autoptr (JsonBuilder) builder = NULL;
     434                 :           8 :   GHashTableIter iter;
     435                 :           8 :   gpointer key, value;
     436                 :           8 :   unsigned int m = 0;
     437                 :             : 
     438         [ +  - ]:           8 :   g_return_val_if_fail (VALENT_IS_TELEPHONY (telephony), NULL);
     439                 :             : 
     440                 :           8 :   builder = json_builder_new ();
     441                 :           8 :   json_builder_begin_object (builder);
     442                 :             : 
     443                 :           8 :   g_hash_table_iter_init (&iter, telephony->modems);
     444                 :             : 
     445         [ +  + ]:          14 :   while (g_hash_table_iter_next (&iter, &key, &value))
     446                 :             :     {
     447                 :           6 :       g_autoptr (JsonNode) modem = NULL;
     448                 :           6 :       g_autofree char *id = NULL;
     449                 :             : 
     450                 :           6 :       id = g_strdup_printf ("%u", m++);
     451                 :           6 :       modem = valent_telephony_serialize_modem (G_DBUS_PROXY (value));
     452                 :             : 
     453                 :           6 :       json_builder_set_member_name (builder, id);
     454                 :           6 :       json_builder_add_value (builder, g_steal_pointer (&modem));
     455                 :             :     }
     456                 :             : 
     457                 :           8 :   json_builder_end_object (builder);
     458                 :             : 
     459                 :           8 :   return json_builder_get_root (builder);
     460                 :             : }
     461                 :             : 
        

Generated by: LCOV version 2.0-1