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.6 % 161 141
Test Date: 2025-10-31 23:35:41 Functions: 100.0 % 17 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 51.2 % 123 63

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

Generated by: LCOV version 2.0-1