GCC Code Coverage Report


Directory: ./
File: src/ppd-action-trickle-charge.c
Date: 2025-03-30 20:28:01
Exec Total Coverage
Lines: 73 90 81.1%
Functions: 10 11 90.9%
Branches: 30 43 69.8%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2020 Bastien Nocera <hadess@hadess.net>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3 as published by
6 * the Free Software Foundation.
7 *
8 */
9
10 #define G_LOG_DOMAIN "TrickleChargeAction"
11
12 #include <gudev/gudev.h>
13
14 #include "ppd-action-trickle-charge.h"
15 #include "ppd-profile.h"
16 #include "ppd-utils.h"
17
18 #define CHARGE_TYPE_SYSFS_NAME "charge_type"
19
20 typedef enum {
21 PPD_CHARGE_TYPE_UNKNOWN,
22 PPD_CHARGE_TYPE_STANDARD,
23 PPD_CHARGE_TYPE_FAST,
24 PPD_CHARGE_TYPE_TRICKLE,
25 PPD_CHARGE_TYPE_CUSTOM,
26 PPD_CHARGE_TYPE_ADAPTIVE,
27 } PpdChargeType;
28
29 struct _PpdActionTrickleCharge
30 {
31 PpdAction parent_instance;
32
33 GUdevClient *client;
34 PpdChargeType charge_type;
35 };
36
37
4/5
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 142 times.
✓ Branch 3 taken 142 times.
✗ Branch 4 not taken.
884 G_DEFINE_TYPE (PpdActionTrickleCharge, ppd_action_trickle_charge, PPD_TYPE_ACTION)
38
39 static GObject*
40 158 ppd_action_trickle_charge_constructor (GType type,
41 guint n_construct_params,
42 GObjectConstructParam *construct_params)
43 {
44 158 GObject *object;
45
46 158 object = G_OBJECT_CLASS (ppd_action_trickle_charge_parent_class)->constructor (type,
47 n_construct_params,
48 construct_params);
49 158 g_object_set (object,
50 "action-name", "trickle_charge",
51 "action-description", "Configure power supply to trickle charge",
52 "action-optin", FALSE,
53 NULL);
54
55 158 return object;
56 }
57
58 PpdChargeType
59 18 ppd_string_to_charge_type (const gchar *str)
60 {
61
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 if (g_str_equal (str, "Standard"))
62 return PPD_CHARGE_TYPE_STANDARD;
63
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 2 times.
16 if (g_str_equal (str, "Fast"))
64 return PPD_CHARGE_TYPE_FAST;
65
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
14 if (g_str_equal (str, "Trickle"))
66 return PPD_CHARGE_TYPE_TRICKLE;
67
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
10 if (g_str_equal (str, "Custom"))
68 return PPD_CHARGE_TYPE_CUSTOM;
69
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (g_str_equal (str, "Adaptive"))
70 2 return PPD_CHARGE_TYPE_ADAPTIVE;
71
72 return PPD_CHARGE_TYPE_UNKNOWN;
73 }
74
75 static const char *
76 24 ppd_charge_type_to_string (PpdChargeType charge_type)
77 {
78
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
24 switch (charge_type) {
79 case PPD_CHARGE_TYPE_STANDARD:
80 return "Standard";
81 case PPD_CHARGE_TYPE_FAST:
82 return "Fast";
83 10 case PPD_CHARGE_TYPE_TRICKLE:
84 10 return "Trickle";
85 case PPD_CHARGE_TYPE_CUSTOM:
86 return "Custom";
87 case PPD_CHARGE_TYPE_ADAPTIVE:
88 return "Adaptive";
89 default:
90 return "Unknown";
91 }
92 }
93
94 static void
95 299 set_charge_type (PpdActionTrickleCharge *action,
96 PpdChargeType charge_type)
97 {
98 299 PpdActionTrickleCharge *self = PPD_ACTION_TRICKLE_CHARGE (action);
99 299 g_autolist (GUdevDevice) devices = NULL;
100 299 const char *charge_type_value;
101
102 299 devices = g_udev_client_query_by_subsystem (action->client, "power_supply");
103
2/2
✓ Branch 0 taken 275 times.
✓ Branch 1 taken 24 times.
299 if (devices == NULL)
104 275 return;
105
106 24 charge_type_value = ppd_charge_type_to_string (charge_type);
107
108
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 for (GList *l = devices; l != NULL; l = l->next) {
109 24 GUdevDevice *dev = l->data;
110 24 const char *value;
111
112
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 20 times.
24 if (g_strcmp0 (g_udev_device_get_sysfs_attr (dev, "scope"), "Device") != 0)
113 4 continue;
114
115 20 value = g_udev_device_get_sysfs_attr_uncached (dev, CHARGE_TYPE_SYSFS_NAME);
116
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if (!value)
117 continue;
118
119
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (g_str_equal (value, charge_type_value))
120 2 continue;
121
122
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 8 times.
18 switch (ppd_string_to_charge_type (value)) {
123 10 case PPD_CHARGE_TYPE_CUSTOM:
124 case PPD_CHARGE_TYPE_ADAPTIVE:
125 10 g_debug ("Not setting charge type for '%s' due to '%s'",
126 g_udev_device_get_sysfs_path (dev), value);
127 10 break;
128
129 8 default:
130 8 ppd_utils_write_sysfs (dev, CHARGE_TYPE_SYSFS_NAME, charge_type_value, NULL);
131 8 break;
132 }
133 }
134
135 24 self->charge_type = charge_type;
136 }
137
138 static gboolean
139 299 ppd_action_trickle_charge_activate_profile (PpdAction *action,
140 PpdProfile profile,
141 GError **error)
142 {
143 299 PpdActionTrickleCharge *self = PPD_ACTION_TRICKLE_CHARGE (action);
144 299 PpdChargeType charge_type;
145
146
3/4
✓ Branch 0 taken 183 times.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 60 times.
299 switch (profile) {
147 case PPD_PROFILE_POWER_SAVER:
148 charge_type = PPD_CHARGE_TYPE_TRICKLE;
149 break;
150 183 case PPD_PROFILE_BALANCED:
151 183 charge_type = PPD_CHARGE_TYPE_STANDARD;
152 183 break;
153 56 case PPD_PROFILE_PERFORMANCE:
154 56 charge_type = PPD_CHARGE_TYPE_FAST;
155 56 break;
156 default:
157 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
158 "Unknown profile %d", profile);
159 return FALSE;
160 }
161
162 299 set_charge_type (self, charge_type);
163
164 299 return TRUE;
165 }
166
167 static void
168 uevent_cb (GUdevClient *client,
169 gchar *action,
170 GUdevDevice *device,
171 gpointer user_data)
172 {
173 PpdActionTrickleCharge *self = user_data;
174
175 if (g_strcmp0 (action, "add") != 0)
176 return;
177
178 if (!g_udev_device_has_sysfs_attr (device, CHARGE_TYPE_SYSFS_NAME))
179 return;
180
181 set_charge_type (self, self->charge_type);
182 }
183
184 static void
185 158 ppd_action_trickle_charge_finalize (GObject *object)
186 {
187 158 PpdActionTrickleCharge *driver;
188
189 158 driver = PPD_ACTION_TRICKLE_CHARGE (object);
190
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 g_clear_object (&driver->client);
191 158 G_OBJECT_CLASS (ppd_action_trickle_charge_parent_class)->finalize (object);
192 158 }
193
194 static void
195 142 ppd_action_trickle_charge_class_init (PpdActionTrickleChargeClass *klass)
196 {
197 142 GObjectClass *object_class;
198 142 PpdActionClass *driver_class;
199
200 142 object_class = G_OBJECT_CLASS (klass);
201 142 object_class->constructor = ppd_action_trickle_charge_constructor;
202 142 object_class->finalize = ppd_action_trickle_charge_finalize;
203
204 142 driver_class = PPD_ACTION_CLASS (klass);
205 142 driver_class->activate_profile = ppd_action_trickle_charge_activate_profile;
206 }
207
208 static void
209 158 ppd_action_trickle_charge_init (PpdActionTrickleCharge *self)
210 {
211 158 const gchar * const subsystem[] = { "power_supply", NULL };
212
213 158 self->client = g_udev_client_new (subsystem);
214 158 g_signal_connect (G_OBJECT (self->client), "uevent",
215 G_CALLBACK (uevent_cb), self);
216 158 }
217