Coverage Report

Created: 2026-07-30 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-device.c
Line
Count
Source
1
/*
2
 * Copyright 2015 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <gio/gio.h>
10
#include <string.h>
11
12
#include "fwupd-codec.h"
13
#include "fwupd-common-private.h"
14
#include "fwupd-device-private.h"
15
#include "fwupd-enums-private.h"
16
#include "fwupd-error.h"
17
#include "fwupd-json-array.h"
18
#include "fwupd-json-object.h"
19
#include "fwupd-variant.h"
20
21
/**
22
 * FwupdDevice:
23
 *
24
 * A physical device on the host with optionally updatable firmware.
25
 *
26
 * See also: [class@FwupdRelease]
27
 */
28
29
static void
30
fwupd_device_finalize(GObject *object);
31
32
typedef struct {
33
  gchar *id;
34
  gchar *parent_id;
35
  gchar *composite_id;
36
  guint64 created;
37
  guint64 modified;
38
  guint64 flags;
39
  guint64 request_flags;
40
  guint64 problems;
41
  GPtrArray *guids;  /* (nullable) (element-type utf-8) */
42
  GPtrArray *vendor_ids;   /* (nullable) (element-type utf-8) */
43
  GPtrArray *protocols;  /* (nullable) (element-type utf-8) */
44
  GPtrArray *instance_ids; /* (nullable) (element-type utf-8) */
45
  GPtrArray *icons;  /* (nullable) (element-type utf-8) */
46
  GPtrArray *issues;   /* (nullable) (element-type utf-8) */
47
  gchar *name;
48
  gchar *serial;
49
  gchar *summary;
50
  gchar *branch;
51
  gchar *vendor;
52
  gchar *details_url;
53
  gchar *plugin;
54
  gchar *version;
55
  gchar *version_lowest;
56
  gchar *version_highest;
57
  gchar *version_bootloader;
58
  FwupdVersionFormat version_format;
59
  guint64 version_raw;
60
  guint64 version_build_date;
61
  guint64 version_lowest_raw;
62
  guint64 version_highest_raw;
63
  guint64 version_bootloader_raw;
64
  GPtrArray *checksums; /* (nullable) (element-type utf-8) */
65
  GPtrArray *children;  /* (nullable) (element-type FuDevice) */
66
  guint32 flashes_left;
67
  guint32 battery_level;
68
  guint32 battery_threshold;
69
  guint32 install_duration;
70
  FwupdUpdateState update_state;
71
  gchar *update_error;
72
  FwupdStatus status;
73
  guint percentage;
74
  GPtrArray *releases; /* (nullable) (element-type FwupdRelease) */
75
  FwupdDevice *parent; /* noref */
76
} FwupdDevicePrivate;
77
78
enum {
79
  PROP_0,
80
  PROP_ID,
81
  PROP_VERSION,
82
  PROP_VERSION_FORMAT,
83
  PROP_FLAGS,
84
  PROP_REQUEST_FLAGS,
85
  PROP_STATUS,
86
  PROP_PERCENTAGE,
87
  PROP_PARENT,
88
  PROP_UPDATE_STATE,
89
  PROP_UPDATE_ERROR,
90
  PROP_BATTERY_LEVEL,
91
  PROP_BATTERY_THRESHOLD,
92
  PROP_PROBLEMS,
93
  PROP_VENDOR,
94
  PROP_LAST
95
};
96
97
static void
98
fwupd_device_codec_iface_init(FwupdCodecInterface *iface);
99
100
18.2k
G_DEFINE_TYPE_EXTENDED(FwupdDevice,
101
18.2k
           fwupd_device,
102
18.2k
           G_TYPE_OBJECT,
103
18.2k
           0,
104
18.2k
           G_ADD_PRIVATE(FwupdDevice)
105
18.2k
         G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC, fwupd_device_codec_iface_init));
106
18.2k
107
18.2k
#define GET_PRIVATE(o) (fwupd_device_get_instance_private(o))
108
109
0
#define FWUPD_BATTERY_THRESHOLD_DEFAULT 10 /* % */
110
111
static void
112
fwupd_device_ensure_checksums(FwupdDevice *self)
113
0
{
114
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
115
0
  if (priv->checksums == NULL)
116
0
    priv->checksums = g_ptr_array_new_with_free_func(g_free);
117
0
}
118
119
/**
120
 * fwupd_device_get_checksums:
121
 * @self: a #FwupdDevice
122
 *
123
 * Gets the device checksums.
124
 *
125
 * Returns: (element-type utf8) (transfer none): the checksums, which may be empty
126
 *
127
 * Since: 0.9.3
128
 **/
129
GPtrArray *
130
fwupd_device_get_checksums(FwupdDevice *self)
131
0
{
132
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
133
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
134
0
  fwupd_device_ensure_checksums(self);
135
0
  return priv->checksums;
136
0
}
137
138
/**
139
 * fwupd_device_has_checksum:
140
 * @self: a #FwupdDevice
141
 * @checksum: (not nullable): the device checksum
142
 *
143
 * Finds out if the device has this specific checksum.
144
 *
145
 * Returns: %TRUE if the checksum name is found
146
 *
147
 * Since: 1.8.7
148
 **/
149
gboolean
150
fwupd_device_has_checksum(FwupdDevice *self, const gchar *checksum)
151
0
{
152
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
153
154
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
155
0
  g_return_val_if_fail(checksum != NULL, FALSE);
156
157
0
  if (priv->checksums == NULL)
158
0
    return FALSE;
159
0
  for (guint i = 0; i < priv->checksums->len; i++) {
160
0
    const gchar *checksum_tmp = g_ptr_array_index(priv->checksums, i);
161
0
    if (g_strcmp0(checksum, checksum_tmp) == 0)
162
0
      return TRUE;
163
0
  }
164
0
  return FALSE;
165
0
}
166
167
/**
168
 * fwupd_device_add_checksum:
169
 * @self: a #FwupdDevice
170
 * @checksum: (not nullable): the device checksum
171
 *
172
 * Adds a device checksum.
173
 *
174
 * Since: 0.9.3
175
 **/
176
void
177
fwupd_device_add_checksum(FwupdDevice *self, const gchar *checksum)
178
0
{
179
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
180
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
181
0
  g_return_if_fail(checksum != NULL);
182
183
0
  if (fwupd_device_has_checksum(self, checksum))
184
0
    return;
185
0
  fwupd_device_ensure_checksums(self);
186
0
  g_ptr_array_add(priv->checksums, g_strdup(checksum));
187
0
}
188
189
static void
190
fwupd_device_ensure_issues(FwupdDevice *self)
191
0
{
192
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
193
0
  if (priv->issues == NULL)
194
0
    priv->issues = g_ptr_array_new_with_free_func(g_free);
195
0
}
196
197
/**
198
 * fwupd_device_get_issues:
199
 * @self: a #FwupdDevice
200
 *
201
 * Gets the list of issues currently affecting this device.
202
 *
203
 * Returns: (element-type utf8) (transfer none): the issues, which may be empty
204
 *
205
 * Since: 1.7.6
206
 **/
207
GPtrArray *
208
fwupd_device_get_issues(FwupdDevice *self)
209
0
{
210
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
211
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
212
0
  fwupd_device_ensure_issues(self);
213
0
  return priv->issues;
214
0
}
215
216
/**
217
 * fwupd_device_add_issue:
218
 * @self: a #FwupdDevice
219
 * @issue: (not nullable): the update issue, e.g. `CVE-2019-12345`
220
 *
221
 * Adds an current issue to this device.
222
 *
223
 * Since: 1.7.6
224
 **/
225
void
226
fwupd_device_add_issue(FwupdDevice *self, const gchar *issue)
227
0
{
228
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
229
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
230
0
  g_return_if_fail(issue != NULL);
231
232
0
  fwupd_device_ensure_issues(self);
233
0
  for (guint i = 0; i < priv->issues->len; i++) {
234
0
    const gchar *issue_tmp = g_ptr_array_index(priv->issues, i);
235
0
    if (g_strcmp0(issue_tmp, issue) == 0)
236
0
      return;
237
0
  }
238
0
  g_ptr_array_add(priv->issues, g_strdup(issue));
239
0
}
240
241
static void
242
fwupd_device_ensure_children(FwupdDevice *self)
243
0
{
244
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
245
0
  if (priv->children == NULL)
246
0
    priv->children = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
247
0
}
248
249
/**
250
 * fwupd_device_get_children:
251
 * @self: a #FwupdDevice
252
 *
253
 * Gets the device children. These can only be assigned using fwupd_device_set_parent().
254
 *
255
 * Returns: (element-type FwupdDevice) (transfer none): the children, which may be empty
256
 *
257
 * Since: 1.3.7
258
 **/
259
GPtrArray *
260
fwupd_device_get_children(FwupdDevice *self)
261
0
{
262
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
263
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
264
0
  fwupd_device_ensure_children(self);
265
0
  return priv->children;
266
0
}
267
268
/**
269
 * fwupd_device_get_summary:
270
 * @self: a #FwupdDevice
271
 *
272
 * Gets the device summary.
273
 *
274
 * Returns: the device summary, or %NULL if unset
275
 *
276
 * Since: 0.9.3
277
 **/
278
const gchar *
279
fwupd_device_get_summary(FwupdDevice *self)
280
0
{
281
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
282
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
283
0
  return priv->summary;
284
0
}
285
286
/**
287
 * fwupd_device_set_summary:
288
 * @self: a #FwupdDevice
289
 * @summary: (nullable): the device one line summary
290
 *
291
 * Sets the device summary.
292
 *
293
 * Since: 0.9.3
294
 **/
295
void
296
fwupd_device_set_summary(FwupdDevice *self, const gchar *summary)
297
0
{
298
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
299
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
300
301
  /* not changed */
302
0
  if (g_strcmp0(priv->summary, summary) == 0)
303
0
    return;
304
305
0
  g_free(priv->summary);
306
0
  priv->summary = g_strdup(summary);
307
0
}
308
309
/**
310
 * fwupd_device_get_details_url:
311
 * @self: a #FwupdDevice
312
 *
313
 * Gets the device URL.
314
 *
315
 * Returns: a URL, or %NULL if unset
316
 *
317
 * Since: 2.1.2
318
 **/
319
const gchar *
320
fwupd_device_get_details_url(FwupdDevice *self)
321
0
{
322
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
323
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
324
0
  return priv->details_url;
325
0
}
326
327
/**
328
 * fwupd_device_set_details_url:
329
 * @self: a #FwupdDevice
330
 * @details_url: (nullable): a URL, or %NULL
331
 *
332
 * Sets the device URL.
333
 *
334
 * Since: 2.1.2
335
 **/
336
void
337
fwupd_device_set_details_url(FwupdDevice *self, const gchar *details_url)
338
0
{
339
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
340
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
341
342
  /* not changed */
343
0
  if (g_strcmp0(priv->details_url, details_url) == 0)
344
0
    return;
345
346
0
  g_free(priv->details_url);
347
0
  priv->details_url = g_strdup(details_url);
348
0
}
349
350
/**
351
 * fwupd_device_get_branch:
352
 * @self: a #FwupdDevice
353
 *
354
 * Gets the current device branch.
355
 *
356
 * Returns: the device branch, or %NULL if unset
357
 *
358
 * Since: 1.5.0
359
 **/
360
const gchar *
361
fwupd_device_get_branch(FwupdDevice *self)
362
0
{
363
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
364
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
365
0
  return priv->branch;
366
0
}
367
368
/**
369
 * fwupd_device_set_branch:
370
 * @self: a #FwupdDevice
371
 * @branch: (nullable): the device one line branch
372
 *
373
 * Sets the current device branch.
374
 *
375
 * Since: 1.5.0
376
 **/
377
void
378
fwupd_device_set_branch(FwupdDevice *self, const gchar *branch)
379
0
{
380
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
381
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
382
383
  /* not changed */
384
0
  if (g_strcmp0(priv->branch, branch) == 0)
385
0
    return;
386
387
0
  g_free(priv->branch);
388
0
  priv->branch = g_strdup(branch);
389
0
}
390
391
/**
392
 * fwupd_device_get_serial:
393
 * @self: a #FwupdDevice
394
 *
395
 * Gets the serial number for the device.
396
 *
397
 * Returns: a string value, or %NULL if never set.
398
 *
399
 * Since: 1.1.2
400
 **/
401
const gchar *
402
fwupd_device_get_serial(FwupdDevice *self)
403
0
{
404
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
405
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
406
0
  return priv->serial;
407
0
}
408
409
/**
410
 * fwupd_device_set_serial:
411
 * @self: a #FwupdDevice
412
 * @serial: (nullable): the device serial number
413
 *
414
 * Sets the serial number for the device.
415
 *
416
 * Since: 1.1.2
417
 **/
418
void
419
fwupd_device_set_serial(FwupdDevice *self, const gchar *serial)
420
0
{
421
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
422
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
423
424
  /* not changed */
425
0
  if (g_strcmp0(priv->serial, serial) == 0)
426
0
    return;
427
428
0
  g_free(priv->serial);
429
0
  priv->serial = g_strdup(serial);
430
0
}
431
432
/**
433
 * fwupd_device_get_id:
434
 * @self: a #FwupdDevice
435
 *
436
 * Gets the ID.
437
 *
438
 * Returns: the ID, or %NULL if unset
439
 *
440
 * Since: 0.9.3
441
 **/
442
const gchar *
443
fwupd_device_get_id(FwupdDevice *self)
444
0
{
445
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
446
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
447
0
  return priv->id;
448
0
}
449
450
/**
451
 * fwupd_device_get_id_display:
452
 * @self: a #FuDevice
453
 *
454
 * Gets the device ID suffixed with the display name if set.
455
 *
456
 * Returns: a string value, or %NULL if invalid.
457
 *
458
 * Since: 2.1.7
459
 **/
460
gchar *
461
fwupd_device_get_id_display(FwupdDevice *self)
462
0
{
463
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
464
0
  g_autoptr(GString) str = g_string_new(NULL);
465
466
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
467
468
0
  if (priv->id != NULL)
469
0
    g_string_append(str, priv->id);
470
0
  if (priv->name != NULL) {
471
0
    if (str->len > 0)
472
0
      g_string_append(str, " ");
473
0
    g_string_append_printf(str, "[%s]", priv->name);
474
0
  } else if (priv->plugin != NULL) {
475
0
    if (str->len > 0)
476
0
      g_string_append(str, " ");
477
0
    g_string_append_printf(str, "{%s}", priv->plugin);
478
0
  }
479
0
  if (str->len == 0)
480
0
    return NULL;
481
0
  return g_string_free(g_steal_pointer(&str), FALSE);
482
0
}
483
484
/**
485
 * fwupd_device_set_id:
486
 * @self: a #FwupdDevice
487
 * @id: (nullable): the device ID, usually a SHA1 hash
488
 *
489
 * Sets the ID.
490
 *
491
 * Since: 0.9.3
492
 **/
493
void
494
fwupd_device_set_id(FwupdDevice *self, const gchar *id)
495
0
{
496
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
497
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
498
499
  /* not changed */
500
0
  if (g_strcmp0(priv->id, id) == 0)
501
0
    return;
502
503
  /* sanity check */
504
0
  if (!fwupd_device_id_is_valid(id)) {
505
0
    g_critical("%s is not a valid device ID", id);
506
0
    return;
507
0
  }
508
509
0
  g_free(priv->id);
510
0
  priv->id = g_strdup(id);
511
0
  g_object_notify(G_OBJECT(self), "id");
512
0
}
513
514
/**
515
 * fwupd_device_get_parent_id:
516
 * @self: a #FwupdDevice
517
 *
518
 * Gets the parent ID.
519
 *
520
 * Returns: the parent ID, or %NULL if unset
521
 *
522
 * Since: 1.0.8
523
 **/
524
const gchar *
525
fwupd_device_get_parent_id(FwupdDevice *self)
526
0
{
527
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
528
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
529
0
  return priv->parent_id;
530
0
}
531
532
/**
533
 * fwupd_device_set_parent_id:
534
 * @self: a #FwupdDevice
535
 * @parent_id: (nullable): the device ID, usually a SHA1 hash
536
 *
537
 * Sets the parent ID.
538
 *
539
 * Since: 1.0.8
540
 **/
541
void
542
fwupd_device_set_parent_id(FwupdDevice *self, const gchar *parent_id)
543
1.02k
{
544
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
545
1.02k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
546
547
  /* not changed */
548
1.02k
  if (g_strcmp0(priv->parent_id, parent_id) == 0)
549
1.02k
    return;
550
551
  /* sanity check */
552
0
  if (parent_id != NULL && !fwupd_device_id_is_valid(parent_id)) {
553
0
    g_critical("%s is not a valid device ID", parent_id);
554
0
    return;
555
0
  }
556
557
0
  g_free(priv->parent_id);
558
0
  priv->parent_id = g_strdup(parent_id);
559
0
}
560
561
/**
562
 * fwupd_device_get_composite_id:
563
 * @self: a #FwupdDevice
564
 *
565
 * Gets the composite ID, falling back to the device ID if unset.
566
 *
567
 * The composite ID will be the same value for all parent, child and sibling
568
 * devices.
569
 *
570
 * Returns: (nullable): the composite ID
571
 *
572
 * Since: 1.6.0
573
 **/
574
const gchar *
575
fwupd_device_get_composite_id(FwupdDevice *self)
576
0
{
577
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
578
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
579
0
  if (priv->composite_id != NULL)
580
0
    return priv->composite_id;
581
0
  return priv->id;
582
0
}
583
584
/**
585
 * fwupd_device_set_composite_id:
586
 * @self: a #FwupdDevice
587
 * @composite_id: (nullable): a device ID
588
 *
589
 * Sets the composite ID, which is usually a SHA1 hash of a grandparent or
590
 * parent device.
591
 *
592
 * Since: 1.6.0
593
 **/
594
void
595
fwupd_device_set_composite_id(FwupdDevice *self, const gchar *composite_id)
596
0
{
597
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
598
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
599
600
  /* not changed */
601
0
  if (g_strcmp0(priv->composite_id, composite_id) == 0)
602
0
    return;
603
604
  /* sanity check */
605
0
  if (!fwupd_device_id_is_valid(composite_id)) {
606
0
    g_critical("%s is not a valid device ID", composite_id);
607
0
    return;
608
0
  }
609
610
0
  g_free(priv->composite_id);
611
0
  priv->composite_id = g_strdup(composite_id);
612
0
}
613
614
/**
615
 * fwupd_device_get_parent:
616
 * @self: a #FwupdDevice
617
 *
618
 * Gets the parent.
619
 *
620
 * Returns: (transfer none): the parent device, or %NULL if unset
621
 *
622
 * Since: 1.0.8
623
 **/
624
FwupdDevice *
625
fwupd_device_get_parent(FwupdDevice *self)
626
1.02k
{
627
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
628
1.02k
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
629
1.02k
  return priv->parent;
630
1.02k
}
631
632
/**
633
 * fwupd_device_get_root:
634
 * @self: a #FwupdDevice
635
 *
636
 * Gets the device root.
637
 *
638
 * Returns: (transfer none): the root device, or %NULL if unset
639
 *
640
 * Since: 1.7.4
641
 **/
642
FwupdDevice *
643
fwupd_device_get_root(FwupdDevice *self)
644
0
{
645
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
646
0
  while (1) {
647
0
    FwupdDevicePrivate *priv = GET_PRIVATE(self);
648
0
    if (priv->parent == NULL)
649
0
      break;
650
0
    self = priv->parent;
651
0
  }
652
0
  return self;
653
0
}
654
655
/**
656
 * fwupd_device_set_parent:
657
 * @self: a #FwupdDevice
658
 * @parent: (nullable): another #FwupdDevice
659
 *
660
 * Sets the parent. Only used internally.
661
 *
662
 * Since: 1.0.8
663
 **/
664
void
665
fwupd_device_set_parent(FwupdDevice *self, FwupdDevice *parent)
666
1.02k
{
667
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
668
1.02k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
669
1.02k
  g_return_if_fail(self != parent);
670
671
1.02k
  if (priv->parent != NULL)
672
0
    g_object_remove_weak_pointer(G_OBJECT(priv->parent), (gpointer *)&priv->parent);
673
1.02k
  if (parent != NULL)
674
0
    g_object_add_weak_pointer(G_OBJECT(parent), (gpointer *)&priv->parent);
675
1.02k
  priv->parent = parent;
676
677
  /* this is what goes over D-Bus */
678
1.02k
  fwupd_device_set_parent_id(self, parent != NULL ? fwupd_device_get_id(parent) : NULL);
679
1.02k
}
680
681
static void
682
fwupd_device_child_finalized_cb(gpointer data, GObject *where_the_object_was)
683
0
{
684
0
  FwupdDevice *self = FWUPD_DEVICE(data);
685
0
  g_critical("FuDevice child %p was finalized while still having parent %s [%s]!",
686
0
       where_the_object_was,
687
0
       fwupd_device_get_name(self),
688
0
       fwupd_device_get_id(self));
689
0
}
690
691
/**
692
 * fwupd_device_add_child:
693
 * @self: a #FwupdDevice
694
 * @child: (not nullable): Another #FwupdDevice
695
 *
696
 * Adds a child device. An child device is logically linked to the primary
697
 * device in some way.
698
 *
699
 * NOTE: You should never call this function from user code, it is for daemon
700
 * use only. Only use fwupd_device_set_parent() to set up a logical tree.
701
 *
702
 * Since: 1.5.1
703
 **/
704
void
705
fwupd_device_add_child(FwupdDevice *self, FwupdDevice *child)
706
0
{
707
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
708
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
709
0
  g_return_if_fail(FWUPD_IS_DEVICE(child));
710
0
  g_return_if_fail(self != child);
711
712
  /* add if the child does not already exist */
713
0
  fwupd_device_ensure_children(self);
714
0
  for (guint i = 0; i < priv->children->len; i++) {
715
0
    FwupdDevice *devtmp = g_ptr_array_index(priv->children, i);
716
0
    if (devtmp == child)
717
0
      return;
718
0
  }
719
0
  g_object_weak_ref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
720
0
  g_ptr_array_add(priv->children, g_object_ref(child));
721
0
}
722
723
/**
724
 * fwupd_device_remove_child:
725
 * @self: a #FwupdDevice
726
 * @child: Another #FwupdDevice
727
 *
728
 * Removes a child device.
729
 *
730
 * NOTE: You should never call this function from user code, it is for daemon
731
 * use only.
732
 *
733
 * Since: 1.6.2
734
 **/
735
void
736
fwupd_device_remove_child(FwupdDevice *self, FwupdDevice *child)
737
0
{
738
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
739
740
  /* remove if the child exists */
741
0
  if (priv->children == NULL)
742
0
    return;
743
0
  for (guint i = 0; i < priv->children->len; i++) {
744
0
    FwupdDevice *child_tmp = g_ptr_array_index(priv->children, i);
745
0
    if (child_tmp == child) {
746
0
      g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
747
0
      g_ptr_array_remove_index(priv->children, i);
748
0
      return;
749
0
    }
750
0
  }
751
0
}
752
753
/**
754
 * fwupd_device_remove_children:
755
 * @self: a #FwupdDevice
756
 *
757
 * Removes all child devices.
758
 *
759
 * NOTE: You should never call this function from user code, it is for daemon
760
 * use only.
761
 *
762
 * Since: 2.0.0
763
 **/
764
void
765
fwupd_device_remove_children(FwupdDevice *self)
766
0
{
767
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
768
769
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
770
771
0
  if (priv->children == NULL)
772
0
    return;
773
0
  for (guint i = 0; i < priv->children->len; i++) {
774
0
    FwupdDevice *child = g_ptr_array_index(priv->children, i);
775
0
    g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
776
0
  }
777
0
  g_ptr_array_set_size(priv->children, 0);
778
0
}
779
780
static void
781
fwupd_device_ensure_guids(FwupdDevice *self)
782
0
{
783
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
784
0
  if (priv->guids == NULL)
785
0
    priv->guids = g_ptr_array_new_with_free_func(g_free);
786
0
}
787
788
/**
789
 * fwupd_device_get_guids:
790
 * @self: a #FwupdDevice
791
 *
792
 * Gets the GUIDs.
793
 *
794
 * Returns: (element-type utf8) (transfer none): the GUIDs
795
 *
796
 * Since: 0.9.3
797
 **/
798
GPtrArray *
799
fwupd_device_get_guids(FwupdDevice *self)
800
0
{
801
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
802
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
803
0
  fwupd_device_ensure_guids(self);
804
0
  return priv->guids;
805
0
}
806
807
/**
808
 * fwupd_device_has_guid:
809
 * @self: a #FwupdDevice
810
 * @guid: (not nullable): the GUID, e.g. `2082b5e0-7a64-478a-b1b2-e3404fab6dad`
811
 *
812
 * Finds out if the device has this specific GUID.
813
 *
814
 * Returns: %TRUE if the GUID is found
815
 *
816
 * Since: 0.9.3
817
 **/
818
gboolean
819
fwupd_device_has_guid(FwupdDevice *self, const gchar *guid)
820
0
{
821
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
822
823
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
824
0
  g_return_val_if_fail(guid != NULL, FALSE);
825
826
0
  if (priv->guids == NULL)
827
0
    return FALSE;
828
0
  for (guint i = 0; i < priv->guids->len; i++) {
829
0
    const gchar *guid_tmp = g_ptr_array_index(priv->guids, i);
830
0
    if (g_strcmp0(guid, guid_tmp) == 0)
831
0
      return TRUE;
832
0
  }
833
0
  return FALSE;
834
0
}
835
836
/**
837
 * fwupd_device_add_guid:
838
 * @self: a #FwupdDevice
839
 * @guid: the GUID, e.g. `2082b5e0-7a64-478a-b1b2-e3404fab6dad`
840
 *
841
 * Adds the GUID if it does not already exist.
842
 *
843
 * Since: 0.9.3
844
 **/
845
void
846
fwupd_device_add_guid(FwupdDevice *self, const gchar *guid)
847
0
{
848
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
849
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
850
0
  g_return_if_fail(guid != NULL);
851
0
  if (fwupd_device_has_guid(self, guid))
852
0
    return;
853
0
  fwupd_device_ensure_guids(self);
854
0
  g_ptr_array_add(priv->guids, g_strdup(guid));
855
0
}
856
857
/**
858
 * fwupd_device_get_guid_default:
859
 * @self: a #FwupdDevice
860
 *
861
 * Gets the default GUID.
862
 *
863
 * Returns: the GUID, or %NULL if unset
864
 *
865
 * Since: 0.9.3
866
 **/
867
const gchar *
868
fwupd_device_get_guid_default(FwupdDevice *self)
869
0
{
870
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
871
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
872
0
  if (priv->guids == NULL || priv->guids->len == 0)
873
0
    return NULL;
874
0
  return g_ptr_array_index(priv->guids, 0);
875
0
}
876
877
static void
878
fwupd_device_ensure_instance_ids(FwupdDevice *self)
879
0
{
880
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
881
0
  if (priv->instance_ids == NULL)
882
0
    priv->instance_ids = g_ptr_array_new_with_free_func(g_free);
883
0
}
884
885
/**
886
 * fwupd_device_get_instance_ids:
887
 * @self: a #FwupdDevice
888
 *
889
 * Gets the instance IDs.
890
 *
891
 * Returns: (element-type utf8) (transfer none): the instance IDs
892
 *
893
 * Since: 1.2.5
894
 **/
895
GPtrArray *
896
fwupd_device_get_instance_ids(FwupdDevice *self)
897
0
{
898
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
899
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
900
0
  fwupd_device_ensure_instance_ids(self);
901
0
  return priv->instance_ids;
902
0
}
903
904
/**
905
 * fwupd_device_has_instance_id:
906
 * @self: a #FwupdDevice
907
 * @instance_id: (not nullable): the instance ID, e.g. `PCI\VEN_10EC&DEV_525A`
908
 *
909
 * Finds out if the device has this specific instance ID.
910
 *
911
 * Returns: %TRUE if the instance ID is found
912
 *
913
 * Since: 1.2.5
914
 **/
915
gboolean
916
fwupd_device_has_instance_id(FwupdDevice *self, const gchar *instance_id)
917
0
{
918
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
919
920
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
921
0
  g_return_val_if_fail(instance_id != NULL, FALSE);
922
923
0
  if (priv->instance_ids == NULL)
924
0
    return FALSE;
925
0
  for (guint i = 0; i < priv->instance_ids->len; i++) {
926
0
    const gchar *instance_id_tmp = g_ptr_array_index(priv->instance_ids, i);
927
0
    if (g_strcmp0(instance_id, instance_id_tmp) == 0)
928
0
      return TRUE;
929
0
  }
930
0
  return FALSE;
931
0
}
932
933
/**
934
 * fwupd_device_add_instance_id:
935
 * @self: a #FwupdDevice
936
 * @instance_id: (not nullable): the instance ID, e.g. `PCI\VEN_10EC&DEV_525A`
937
 *
938
 * Adds the instance ID if it does not already exist.
939
 *
940
 * Since: 1.2.5
941
 **/
942
void
943
fwupd_device_add_instance_id(FwupdDevice *self, const gchar *instance_id)
944
0
{
945
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
946
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
947
0
  g_return_if_fail(instance_id != NULL);
948
0
  if (fwupd_device_has_instance_id(self, instance_id))
949
0
    return;
950
0
  fwupd_device_ensure_instance_ids(self);
951
0
  g_ptr_array_add(priv->instance_ids, g_strdup(instance_id));
952
0
}
953
954
static void
955
fwupd_device_ensure_icons(FwupdDevice *self)
956
0
{
957
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
958
0
  if (priv->icons == NULL)
959
0
    priv->icons = g_ptr_array_new_with_free_func(g_free);
960
0
}
961
962
/**
963
 * fwupd_device_get_icons:
964
 * @self: a #FwupdDevice
965
 *
966
 * Gets the icon names to use for the device.
967
 *
968
 * NOTE: Icons specified without a full path are stock icons and should
969
 * be loaded from the users icon theme.
970
 *
971
 * Returns: (element-type utf8) (transfer none): an array of icon names
972
 *
973
 * Since: 0.9.8
974
 **/
975
GPtrArray *
976
fwupd_device_get_icons(FwupdDevice *self)
977
0
{
978
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
979
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
980
0
  fwupd_device_ensure_icons(self);
981
0
  return priv->icons;
982
0
}
983
984
/**
985
 * fwupd_device_has_icon:
986
 * @self: a #FwupdDevice
987
 * @icon: the icon name, e.g. `input-mouse` or `/usr/share/icons/foo.png`
988
 *
989
 * Finds out if the device has this specific icon.
990
 *
991
 * Returns: %TRUE if the icon name is found
992
 *
993
 * Since: 1.6.2
994
 **/
995
gboolean
996
fwupd_device_has_icon(FwupdDevice *self, const gchar *icon)
997
0
{
998
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
999
0
  if (priv->icons == NULL)
1000
0
    return FALSE;
1001
0
  for (guint i = 0; i < priv->icons->len; i++) {
1002
0
    const gchar *icon_tmp = g_ptr_array_index(priv->icons, i);
1003
0
    if (g_strcmp0(icon, icon_tmp) == 0)
1004
0
      return TRUE;
1005
0
  }
1006
0
  return FALSE;
1007
0
}
1008
1009
/**
1010
 * fwupd_device_add_icon:
1011
 * @self: a #FwupdDevice
1012
 * @icon: (not nullable): the icon name, e.g. `input-mouse` or `/usr/share/icons/foo.png`
1013
 *
1014
 * Adds the icon name if it does not already exist.
1015
 *
1016
 * Since: 0.9.8
1017
 **/
1018
void
1019
fwupd_device_add_icon(FwupdDevice *self, const gchar *icon)
1020
0
{
1021
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1022
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1023
0
  g_return_if_fail(icon != NULL);
1024
0
  if (fwupd_device_has_icon(self, icon))
1025
0
    return;
1026
0
  fwupd_device_ensure_icons(self);
1027
0
  g_ptr_array_add(priv->icons, g_strdup(icon));
1028
0
}
1029
1030
/**
1031
 * fwupd_device_get_name:
1032
 * @self: a #FwupdDevice
1033
 *
1034
 * Gets the device name.
1035
 *
1036
 * Returns: the device name, or %NULL if unset
1037
 *
1038
 * Since: 0.9.3
1039
 **/
1040
const gchar *
1041
fwupd_device_get_name(FwupdDevice *self)
1042
0
{
1043
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1044
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1045
0
  return priv->name;
1046
0
}
1047
1048
/**
1049
 * fwupd_device_set_name:
1050
 * @self: a #FwupdDevice
1051
 * @name: (nullable): the device name, e.g. `ColorHug2`
1052
 *
1053
 * Sets the device name.
1054
 *
1055
 * Since: 0.9.3
1056
 **/
1057
void
1058
fwupd_device_set_name(FwupdDevice *self, const gchar *name)
1059
1.02k
{
1060
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1061
1.02k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1062
1063
  /* not changed */
1064
1.02k
  if (g_strcmp0(priv->name, name) == 0)
1065
1.02k
    return;
1066
1067
0
  g_free(priv->name);
1068
0
  priv->name = g_strdup(name);
1069
0
}
1070
1071
/**
1072
 * fwupd_device_get_vendor:
1073
 * @self: a #FwupdDevice
1074
 *
1075
 * Gets the device vendor.
1076
 *
1077
 * Returns: the device vendor, or %NULL if unset
1078
 *
1079
 * Since: 0.9.3
1080
 **/
1081
const gchar *
1082
fwupd_device_get_vendor(FwupdDevice *self)
1083
0
{
1084
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1085
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1086
0
  return priv->vendor;
1087
0
}
1088
1089
/**
1090
 * fwupd_device_set_vendor:
1091
 * @self: a #FwupdDevice
1092
 * @vendor: (nullable): the vendor
1093
 *
1094
 * Sets the device vendor.
1095
 *
1096
 * Since: 0.9.3
1097
 **/
1098
void
1099
fwupd_device_set_vendor(FwupdDevice *self, const gchar *vendor)
1100
0
{
1101
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1102
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1103
1104
  /* not changed */
1105
0
  if (g_strcmp0(priv->vendor, vendor) == 0)
1106
0
    return;
1107
1108
0
  g_free(priv->vendor);
1109
0
  priv->vendor = g_strdup(vendor);
1110
0
  g_object_notify(G_OBJECT(self), "vendor");
1111
0
}
1112
1113
static void
1114
fwupd_device_ensure_vendor_ids(FwupdDevice *self)
1115
0
{
1116
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1117
0
  if (priv->vendor_ids == NULL)
1118
0
    priv->vendor_ids = g_ptr_array_new_with_free_func(g_free);
1119
0
}
1120
1121
/**
1122
 * fwupd_device_get_vendor_ids:
1123
 * @self: a #FwupdDevice
1124
 *
1125
 * Gets the device vendor ID.
1126
 *
1127
 * Returns: (element-type utf8) (transfer none): the device vendor ID
1128
 *
1129
 * Since: 1.5.5
1130
 **/
1131
GPtrArray *
1132
fwupd_device_get_vendor_ids(FwupdDevice *self)
1133
0
{
1134
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1135
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1136
0
  fwupd_device_ensure_vendor_ids(self);
1137
0
  return priv->vendor_ids;
1138
0
}
1139
1140
/**
1141
 * fwupd_device_has_vendor_id:
1142
 * @self: a #FwupdDevice
1143
 * @vendor_id: (not nullable): the vendor ID, e.g. 'USB:0x1234'
1144
 *
1145
 * Finds out if the device has this specific vendor ID.
1146
 *
1147
 * Returns: %TRUE if the vendor ID is found
1148
 *
1149
 * Since: 1.5.5
1150
 **/
1151
gboolean
1152
fwupd_device_has_vendor_id(FwupdDevice *self, const gchar *vendor_id)
1153
0
{
1154
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1155
1156
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1157
0
  g_return_val_if_fail(vendor_id != NULL, FALSE);
1158
1159
0
  if (priv->vendor_ids == NULL)
1160
0
    return FALSE;
1161
0
  for (guint i = 0; i < priv->vendor_ids->len; i++) {
1162
0
    const gchar *vendor_id_tmp = g_ptr_array_index(priv->vendor_ids, i);
1163
0
    if (g_strcmp0(vendor_id, vendor_id_tmp) == 0)
1164
0
      return TRUE;
1165
0
  }
1166
0
  return FALSE;
1167
0
}
1168
1169
/**
1170
 * fwupd_device_add_vendor_id:
1171
 * @self: a #FwupdDevice
1172
 * @vendor_id: (not nullable): the ID, e.g. 'USB:0x1234'
1173
 *
1174
 * Adds a device vendor ID.
1175
 *
1176
 * Since: 1.5.5
1177
 **/
1178
void
1179
fwupd_device_add_vendor_id(FwupdDevice *self, const gchar *vendor_id)
1180
0
{
1181
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1182
1183
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1184
0
  g_return_if_fail(vendor_id != NULL);
1185
1186
0
  if (fwupd_device_has_vendor_id(self, vendor_id))
1187
0
    return;
1188
0
  fwupd_device_ensure_vendor_ids(self);
1189
0
  g_ptr_array_add(priv->vendor_ids, g_strdup(vendor_id));
1190
0
}
1191
1192
/**
1193
 * fwupd_device_get_version:
1194
 * @self: a #FwupdDevice
1195
 *
1196
 * Gets the device version.
1197
 *
1198
 * Returns: the device version, or %NULL if unset
1199
 *
1200
 * Since: 0.9.3
1201
 **/
1202
const gchar *
1203
fwupd_device_get_version(FwupdDevice *self)
1204
0
{
1205
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1206
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1207
0
  return priv->version;
1208
0
}
1209
1210
/**
1211
 * fwupd_device_set_version:
1212
 * @self: a #FwupdDevice
1213
 * @version: (nullable): the device version, e.g. `1.2.3`
1214
 *
1215
 * Sets the device version.
1216
 *
1217
 * Since: 0.9.3
1218
 **/
1219
void
1220
fwupd_device_set_version(FwupdDevice *self, const gchar *version)
1221
0
{
1222
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1223
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1224
1225
  /* not changed */
1226
0
  if (g_strcmp0(priv->version, version) == 0)
1227
0
    return;
1228
1229
0
  g_free(priv->version);
1230
0
  priv->version = g_strdup(version);
1231
0
  g_object_notify(G_OBJECT(self), "version");
1232
0
}
1233
1234
/**
1235
 * fwupd_device_get_version_lowest:
1236
 * @self: a #FwupdDevice
1237
 *
1238
 * Gets the lowest version of firmware the device will accept.
1239
 *
1240
 * Returns: the device version_lowest, or %NULL if unset
1241
 *
1242
 * Since: 0.9.3
1243
 **/
1244
const gchar *
1245
fwupd_device_get_version_lowest(FwupdDevice *self)
1246
0
{
1247
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1248
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1249
0
  return priv->version_lowest;
1250
0
}
1251
1252
/**
1253
 * fwupd_device_set_version_lowest:
1254
 * @self: a #FwupdDevice
1255
 * @version_lowest: (nullable): the version
1256
 *
1257
 * Sets the lowest version of firmware the device will accept.
1258
 *
1259
 * Since: 0.9.3
1260
 **/
1261
void
1262
fwupd_device_set_version_lowest(FwupdDevice *self, const gchar *version_lowest)
1263
0
{
1264
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1265
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1266
1267
  /* not changed */
1268
0
  if (g_strcmp0(priv->version_lowest, version_lowest) == 0)
1269
0
    return;
1270
1271
0
  g_free(priv->version_lowest);
1272
0
  priv->version_lowest = g_strdup(version_lowest);
1273
0
}
1274
1275
/**
1276
 * fwupd_device_get_version_lowest_raw:
1277
 * @self: a #FwupdDevice
1278
 *
1279
 * Gets the lowest version of firmware the device will accept in raw format.
1280
 *
1281
 * Returns: integer version number, or %0 if unset
1282
 *
1283
 * Since: 1.4.0
1284
 **/
1285
guint64
1286
fwupd_device_get_version_lowest_raw(FwupdDevice *self)
1287
0
{
1288
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1289
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1290
0
  return priv->version_lowest_raw;
1291
0
}
1292
1293
/**
1294
 * fwupd_device_set_version_lowest_raw:
1295
 * @self: a #FwupdDevice
1296
 * @version_lowest_raw: the raw hardware version
1297
 *
1298
 * Sets the raw lowest version number from the hardware before converted to a string.
1299
 *
1300
 * Since: 1.4.0
1301
 **/
1302
void
1303
fwupd_device_set_version_lowest_raw(FwupdDevice *self, guint64 version_lowest_raw)
1304
0
{
1305
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1306
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1307
0
  priv->version_lowest_raw = version_lowest_raw;
1308
0
}
1309
1310
/**
1311
 * fwupd_device_get_version_highest:
1312
 * @self: a #FwupdDevice
1313
 *
1314
 * Gets the highest version of firmware the device will accept.
1315
 *
1316
 * Returns: the device version_highest, or %NULL if unset
1317
 *
1318
 * Since: 2.1.2
1319
 **/
1320
const gchar *
1321
fwupd_device_get_version_highest(FwupdDevice *self)
1322
0
{
1323
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1324
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1325
0
  return priv->version_highest;
1326
0
}
1327
1328
/**
1329
 * fwupd_device_set_version_highest:
1330
 * @self: a #FwupdDevice
1331
 * @version_highest: (nullable): the version
1332
 *
1333
 * Sets the highest version of firmware the device will accept.
1334
 *
1335
 * Since: 2.1.2
1336
 **/
1337
void
1338
fwupd_device_set_version_highest(FwupdDevice *self, const gchar *version_highest)
1339
0
{
1340
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1341
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1342
1343
  /* not changed */
1344
0
  if (g_strcmp0(priv->version_highest, version_highest) == 0)
1345
0
    return;
1346
1347
0
  g_free(priv->version_highest);
1348
0
  priv->version_highest = g_strdup(version_highest);
1349
0
}
1350
1351
/**
1352
 * fwupd_device_get_version_highest_raw:
1353
 * @self: a #FwupdDevice
1354
 *
1355
 * Gets the highest version of firmware the device will accept in raw format.
1356
 *
1357
 * Returns: integer version number, or %0 if unset
1358
 *
1359
 * Since: 2.1.2
1360
 **/
1361
guint64
1362
fwupd_device_get_version_highest_raw(FwupdDevice *self)
1363
0
{
1364
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1365
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1366
0
  return priv->version_highest_raw;
1367
0
}
1368
1369
/**
1370
 * fwupd_device_set_version_highest_raw:
1371
 * @self: a #FwupdDevice
1372
 * @version_highest_raw: the raw highest version
1373
 *
1374
 * Sets the raw highest version number from the hardware before being converted to a string.
1375
 *
1376
 * Since: 2.1.2
1377
 **/
1378
void
1379
fwupd_device_set_version_highest_raw(FwupdDevice *self, guint64 version_highest_raw)
1380
0
{
1381
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1382
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1383
0
  priv->version_highest_raw = version_highest_raw;
1384
0
}
1385
1386
/**
1387
 * fwupd_device_get_version_bootloader:
1388
 * @self: a #FwupdDevice
1389
 *
1390
 * Gets the version of the bootloader.
1391
 *
1392
 * Returns: the device version_bootloader, or %NULL if unset
1393
 *
1394
 * Since: 0.9.3
1395
 **/
1396
const gchar *
1397
fwupd_device_get_version_bootloader(FwupdDevice *self)
1398
0
{
1399
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1400
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1401
0
  return priv->version_bootloader;
1402
0
}
1403
1404
/**
1405
 * fwupd_device_set_version_bootloader:
1406
 * @self: a #FwupdDevice
1407
 * @version_bootloader: (nullable): the version
1408
 *
1409
 * Sets the bootloader version.
1410
 *
1411
 * Since: 0.9.3
1412
 **/
1413
void
1414
fwupd_device_set_version_bootloader(FwupdDevice *self, const gchar *version_bootloader)
1415
0
{
1416
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1417
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1418
1419
  /* not changed */
1420
0
  if (g_strcmp0(priv->version_bootloader, version_bootloader) == 0)
1421
0
    return;
1422
1423
0
  g_free(priv->version_bootloader);
1424
0
  priv->version_bootloader = g_strdup(version_bootloader);
1425
0
}
1426
1427
/**
1428
 * fwupd_device_get_version_bootloader_raw:
1429
 * @self: a #FwupdDevice
1430
 *
1431
 * Gets the bootloader version of firmware the device will accept in raw format.
1432
 *
1433
 * Returns: integer version number, or %0 if unset
1434
 *
1435
 * Since: 1.4.0
1436
 **/
1437
guint64
1438
fwupd_device_get_version_bootloader_raw(FwupdDevice *self)
1439
0
{
1440
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1441
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1442
0
  return priv->version_bootloader_raw;
1443
0
}
1444
1445
/**
1446
 * fwupd_device_set_version_bootloader_raw:
1447
 * @self: a #FwupdDevice
1448
 * @version_bootloader_raw: the raw hardware version
1449
 *
1450
 * Sets the raw bootloader version number from the hardware before converted to a string.
1451
 *
1452
 * Since: 1.4.0
1453
 **/
1454
void
1455
fwupd_device_set_version_bootloader_raw(FwupdDevice *self, guint64 version_bootloader_raw)
1456
0
{
1457
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1458
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1459
0
  priv->version_bootloader_raw = version_bootloader_raw;
1460
0
}
1461
1462
/**
1463
 * fwupd_device_get_flashes_left:
1464
 * @self: a #FwupdDevice
1465
 *
1466
 * Gets the number of flash cycles left on the device
1467
 *
1468
 * Returns: the flash cycles left, or %NULL if unset
1469
 *
1470
 * Since: 0.9.3
1471
 **/
1472
guint32
1473
fwupd_device_get_flashes_left(FwupdDevice *self)
1474
0
{
1475
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1476
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1477
0
  return priv->flashes_left;
1478
0
}
1479
1480
/**
1481
 * fwupd_device_set_flashes_left:
1482
 * @self: a #FwupdDevice
1483
 * @flashes_left: the description
1484
 *
1485
 * Sets the number of flash cycles left on the device
1486
 *
1487
 * Since: 0.9.3
1488
 **/
1489
void
1490
fwupd_device_set_flashes_left(FwupdDevice *self, guint32 flashes_left)
1491
0
{
1492
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1493
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1494
0
  priv->flashes_left = flashes_left;
1495
0
}
1496
1497
/**
1498
 * fwupd_device_get_battery_level:
1499
 * @self: a #FwupdDevice
1500
 *
1501
 * Returns the battery level.
1502
 *
1503
 * Returns: value in percent
1504
 *
1505
 * Since: 1.8.1
1506
 **/
1507
guint32
1508
fwupd_device_get_battery_level(FwupdDevice *self)
1509
0
{
1510
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1511
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), G_MAXUINT32);
1512
0
  return priv->battery_level;
1513
0
}
1514
1515
/**
1516
 * fwupd_device_set_battery_level:
1517
 * @self: a #FwupdDevice
1518
 * @battery_level: the percentage value
1519
 *
1520
 * Sets the battery level, or %FWUPD_BATTERY_LEVEL_INVALID.
1521
 *
1522
 * Setting this allows fwupd to show a warning if the device change is too low
1523
 * to perform the update.
1524
 *
1525
 * Since: 1.8.1
1526
 **/
1527
void
1528
fwupd_device_set_battery_level(FwupdDevice *self, guint32 battery_level)
1529
0
{
1530
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1531
1532
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1533
0
  g_return_if_fail(battery_level <= FWUPD_BATTERY_LEVEL_INVALID);
1534
1535
0
  if (priv->battery_level == battery_level)
1536
0
    return;
1537
0
  priv->battery_level = battery_level;
1538
0
  g_object_notify(G_OBJECT(self), "battery-level");
1539
0
}
1540
1541
/**
1542
 * fwupd_device_get_battery_threshold:
1543
 * @self: a #FwupdDevice
1544
 *
1545
 * Returns the battery threshold under which a firmware update cannot be
1546
 * performed.
1547
 *
1548
 * If fwupd_device_set_battery_threshold() has not been used, a default value is
1549
 * used instead.
1550
 *
1551
 * Returns: value in percent
1552
 *
1553
 * Since: 1.8.1
1554
 **/
1555
guint32
1556
fwupd_device_get_battery_threshold(FwupdDevice *self)
1557
0
{
1558
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1559
1560
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), G_MAXUINT32);
1561
1562
  /* default value */
1563
0
  if (priv->battery_threshold == FWUPD_BATTERY_LEVEL_INVALID)
1564
0
    return FWUPD_BATTERY_THRESHOLD_DEFAULT;
1565
1566
0
  return priv->battery_threshold;
1567
0
}
1568
1569
/**
1570
 * fwupd_device_set_battery_threshold:
1571
 * @self: a #FwupdDevice
1572
 * @battery_threshold: the percentage value
1573
 *
1574
 * Sets the battery level, or %FWUPD_BATTERY_LEVEL_INVALID for the default.
1575
 *
1576
 * Setting this allows fwupd to show a warning if the device change is too low
1577
 * to perform the update.
1578
 *
1579
 * Since: 1.8.1
1580
 **/
1581
void
1582
fwupd_device_set_battery_threshold(FwupdDevice *self, guint32 battery_threshold)
1583
0
{
1584
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1585
1586
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1587
0
  g_return_if_fail(battery_threshold <= FWUPD_BATTERY_LEVEL_INVALID);
1588
1589
0
  if (priv->battery_threshold == battery_threshold)
1590
0
    return;
1591
0
  priv->battery_threshold = battery_threshold;
1592
0
  g_object_notify(G_OBJECT(self), "battery-threshold");
1593
0
}
1594
1595
/**
1596
 * fwupd_device_get_install_duration:
1597
 * @self: a #FwupdDevice
1598
 *
1599
 * Gets the time estimate for firmware installation (in seconds)
1600
 *
1601
 * Returns: the estimated time to flash this device (or 0 if unset)
1602
 *
1603
 * Since: 1.1.3
1604
 **/
1605
guint32
1606
fwupd_device_get_install_duration(FwupdDevice *self)
1607
0
{
1608
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1609
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1610
0
  return priv->install_duration;
1611
0
}
1612
1613
/**
1614
 * fwupd_device_set_install_duration:
1615
 * @self: a #FwupdDevice
1616
 * @duration: the amount of time
1617
 *
1618
 * Sets the time estimate for firmware installation (in seconds)
1619
 *
1620
 * Since: 1.1.3
1621
 **/
1622
void
1623
fwupd_device_set_install_duration(FwupdDevice *self, guint32 duration)
1624
0
{
1625
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1626
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1627
0
  priv->install_duration = duration;
1628
0
}
1629
1630
/**
1631
 * fwupd_device_get_plugin:
1632
 * @self: a #FwupdDevice
1633
 *
1634
 * Gets the plugin that created the device.
1635
 *
1636
 * Returns: the plugin name, or %NULL if unset
1637
 *
1638
 * Since: 1.0.0
1639
 **/
1640
const gchar *
1641
fwupd_device_get_plugin(FwupdDevice *self)
1642
0
{
1643
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1644
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1645
0
  return priv->plugin;
1646
0
}
1647
1648
/**
1649
 * fwupd_device_set_plugin:
1650
 * @self: a #FwupdDevice
1651
 * @plugin: (nullable): the plugin name, e.g. `hughski_colorhug`
1652
 *
1653
 * Sets the plugin that created the device.
1654
 *
1655
 * Since: 1.0.0
1656
 **/
1657
void
1658
fwupd_device_set_plugin(FwupdDevice *self, const gchar *plugin)
1659
0
{
1660
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1661
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1662
1663
  /* not changed */
1664
0
  if (g_strcmp0(priv->plugin, plugin) == 0)
1665
0
    return;
1666
1667
0
  g_free(priv->plugin);
1668
0
  priv->plugin = g_strdup(plugin);
1669
0
}
1670
1671
static void
1672
fwupd_device_ensure_protocols(FwupdDevice *self)
1673
263
{
1674
263
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1675
263
  if (priv->protocols == NULL)
1676
263
    priv->protocols = g_ptr_array_new_with_free_func(g_free);
1677
263
}
1678
1679
/**
1680
 * fwupd_device_get_protocols:
1681
 * @self: a #FwupdDevice
1682
 *
1683
 * Gets the device protocol names.
1684
 *
1685
 * Returns: (element-type utf8) (transfer none): the device protocol names
1686
 *
1687
 * Since: 1.5.8
1688
 **/
1689
GPtrArray *
1690
fwupd_device_get_protocols(FwupdDevice *self)
1691
0
{
1692
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1693
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1694
0
  fwupd_device_ensure_protocols(self);
1695
0
  return priv->protocols;
1696
0
}
1697
1698
/**
1699
 * fwupd_device_has_protocol:
1700
 * @self: a #FwupdDevice
1701
 * @protocol: (not nullable): the protocol name, e.g. `com.hughski.colorhug`
1702
 *
1703
 * Finds out if the device has this specific protocol name.
1704
 *
1705
 * Returns: %TRUE if the protocol name is found
1706
 *
1707
 * Since: 1.5.8
1708
 **/
1709
gboolean
1710
fwupd_device_has_protocol(FwupdDevice *self, const gchar *protocol)
1711
263
{
1712
263
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1713
1714
263
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1715
263
  g_return_val_if_fail(protocol != NULL, FALSE);
1716
1717
263
  if (priv->protocols == NULL)
1718
263
    return FALSE;
1719
0
  for (guint i = 0; i < priv->protocols->len; i++) {
1720
0
    const gchar *protocol_tmp = g_ptr_array_index(priv->protocols, i);
1721
0
    if (g_strcmp0(protocol, protocol_tmp) == 0)
1722
0
      return TRUE;
1723
0
  }
1724
0
  return FALSE;
1725
0
}
1726
1727
/**
1728
 * fwupd_device_add_protocol:
1729
 * @self: a #FwupdDevice
1730
 * @protocol: (not nullable): the protocol name, e.g. `com.hughski.colorhug`
1731
 *
1732
 * Adds a device protocol name.
1733
 *
1734
 * Since: 1.5.8
1735
 **/
1736
void
1737
fwupd_device_add_protocol(FwupdDevice *self, const gchar *protocol)
1738
263
{
1739
263
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1740
1741
263
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1742
263
  g_return_if_fail(protocol != NULL);
1743
1744
263
  if (fwupd_device_has_protocol(self, protocol))
1745
0
    return;
1746
263
  fwupd_device_ensure_protocols(self);
1747
263
  g_ptr_array_add(priv->protocols, g_strdup(protocol));
1748
263
}
1749
1750
/**
1751
 * fwupd_device_get_flags:
1752
 * @self: a #FwupdDevice
1753
 *
1754
 * Gets device flags.
1755
 *
1756
 * Returns: device flags, or 0 if unset
1757
 *
1758
 * Since: 0.9.3
1759
 **/
1760
guint64
1761
fwupd_device_get_flags(FwupdDevice *self)
1762
0
{
1763
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1764
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1765
0
  return priv->flags;
1766
0
}
1767
1768
/**
1769
 * fwupd_device_set_flags:
1770
 * @self: a #FwupdDevice
1771
 * @flags: device flags, e.g. %FWUPD_DEVICE_FLAG_REQUIRE_AC
1772
 *
1773
 * Sets device flags.
1774
 *
1775
 * Since: 0.9.3
1776
 **/
1777
void
1778
fwupd_device_set_flags(FwupdDevice *self, guint64 flags)
1779
0
{
1780
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1781
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1782
0
  if (priv->flags == flags)
1783
0
    return;
1784
0
  priv->flags = flags;
1785
0
  g_object_notify(G_OBJECT(self), "flags");
1786
0
}
1787
1788
/**
1789
 * fwupd_device_add_flag:
1790
 * @self: a #FwupdDevice
1791
 * @flag: the #FwupdDeviceFlags
1792
 *
1793
 * Adds a specific device flag to the device.
1794
 *
1795
 * Since: 0.9.3
1796
 **/
1797
void
1798
fwupd_device_add_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1799
1.54k
{
1800
1.54k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1801
1.54k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1802
1.54k
  if (flag == 0)
1803
0
    return;
1804
1.54k
  if ((priv->flags | flag) == priv->flags)
1805
0
    return;
1806
1.54k
  priv->flags |= flag;
1807
1.54k
  g_object_notify(G_OBJECT(self), "flags");
1808
1.54k
}
1809
1810
/**
1811
 * fwupd_device_remove_flag:
1812
 * @self: a #FwupdDevice
1813
 * @flag: the #FwupdDeviceFlags
1814
 *
1815
 * Removes a specific device flag from the device.
1816
 *
1817
 * Since: 0.9.3
1818
 **/
1819
void
1820
fwupd_device_remove_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1821
526
{
1822
526
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1823
526
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1824
526
  if (flag == 0)
1825
0
    return;
1826
526
  if ((priv->flags & flag) == 0)
1827
263
    return;
1828
263
  priv->flags &= ~flag;
1829
263
  g_object_notify(G_OBJECT(self), "flags");
1830
263
}
1831
1832
/**
1833
 * fwupd_device_has_flag:
1834
 * @self: a #FwupdDevice
1835
 * @flag: the #FwupdDeviceFlags
1836
 *
1837
 * Finds if the device has a specific device flag.
1838
 *
1839
 * Returns: %TRUE if the flag is set
1840
 *
1841
 * Since: 0.9.3
1842
 **/
1843
gboolean
1844
fwupd_device_has_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1845
2.07k
{
1846
2.07k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1847
2.07k
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1848
2.07k
  return (priv->flags & flag) > 0;
1849
2.07k
}
1850
1851
/**
1852
 * fwupd_device_get_problems:
1853
 * @self: a #FwupdDevice
1854
 *
1855
 * Gets device problems.
1856
 *
1857
 * Returns: device problems, or 0 if unset
1858
 *
1859
 * Since: 1.8.1
1860
 **/
1861
guint64
1862
fwupd_device_get_problems(FwupdDevice *self)
1863
0
{
1864
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1865
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1866
0
  return priv->problems;
1867
0
}
1868
1869
/**
1870
 * fwupd_device_set_problems:
1871
 * @self: a #FwupdDevice
1872
 * @problems: device problems, e.g. %FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1873
 *
1874
 * Sets device problems.
1875
 *
1876
 * Since: 1.8.1
1877
 **/
1878
void
1879
fwupd_device_set_problems(FwupdDevice *self, guint64 problems)
1880
0
{
1881
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1882
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1883
0
  if (priv->problems == problems)
1884
0
    return;
1885
0
  priv->problems = problems;
1886
0
  g_object_notify(G_OBJECT(self), "problems");
1887
0
}
1888
1889
/**
1890
 * fwupd_device_add_problem:
1891
 * @self: a #FwupdDevice
1892
 * @problem: the #FwupdDeviceProblem, e.g. #FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1893
 *
1894
 * Adds a specific device problem kind to the device.
1895
 *
1896
 * Since: 1.8.1
1897
 **/
1898
void
1899
fwupd_device_add_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1900
0
{
1901
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1902
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1903
0
  if (problem == FWUPD_DEVICE_PROBLEM_NONE)
1904
0
    return;
1905
0
  if (fwupd_device_has_problem(self, problem))
1906
0
    return;
1907
0
  priv->problems |= problem;
1908
0
  g_object_notify(G_OBJECT(self), "problems");
1909
0
}
1910
1911
/**
1912
 * fwupd_device_remove_problem:
1913
 * @self: a #FwupdDevice
1914
 * @problem: the #FwupdDeviceProblem, e.g. #FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1915
 *
1916
 * Removes a specific device problem kind from the device.
1917
 *
1918
 * Since: 1.8.1
1919
 **/
1920
void
1921
fwupd_device_remove_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1922
0
{
1923
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1924
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1925
0
  if (problem == FWUPD_DEVICE_PROBLEM_NONE)
1926
0
    return;
1927
0
  if (!fwupd_device_has_problem(self, problem))
1928
0
    return;
1929
0
  priv->problems &= ~problem;
1930
0
  g_object_notify(G_OBJECT(self), "problems");
1931
0
}
1932
1933
/**
1934
 * fwupd_device_has_problem:
1935
 * @self: a #FwupdDevice
1936
 * @problem: the #FwupdDeviceProblem
1937
 *
1938
 * Finds if the device has a specific device problem kind.
1939
 *
1940
 * Returns: %TRUE if the problem is set
1941
 *
1942
 * Since: 1.8.1
1943
 **/
1944
gboolean
1945
fwupd_device_has_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1946
0
{
1947
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1948
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1949
0
  return (priv->problems & problem) > 0;
1950
0
}
1951
1952
/**
1953
 * fwupd_device_get_request_flags:
1954
 * @self: a #FwupdDevice
1955
 *
1956
 * Gets device request flags.
1957
 *
1958
 * Returns: device request flags, or 0 if unset
1959
 *
1960
 * Since: 1.9.10
1961
 **/
1962
guint64
1963
fwupd_device_get_request_flags(FwupdDevice *self)
1964
0
{
1965
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1966
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1967
0
  return priv->request_flags;
1968
0
}
1969
1970
/**
1971
 * fwupd_device_set_request_flags:
1972
 * @self: a #FwupdDevice
1973
 * @request_flags: device request flags, e.g. %FWUPD_DEVICE_REQUEST_FLAG_REQUIRE_AC
1974
 *
1975
 * Sets device request flags.
1976
 *
1977
 * Since: 1.9.10
1978
 **/
1979
void
1980
fwupd_device_set_request_flags(FwupdDevice *self, guint64 request_flags)
1981
0
{
1982
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1983
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1984
0
  if (priv->request_flags == request_flags)
1985
0
    return;
1986
0
  priv->request_flags = request_flags;
1987
0
  g_object_notify(G_OBJECT(self), "request-flags");
1988
0
}
1989
1990
/**
1991
 * fwupd_device_add_request_flag:
1992
 * @self: a #FwupdDevice
1993
 * @request_flag: the #FwupdRequestFlags
1994
 *
1995
 * Adds a specific device request flag to the device.
1996
 *
1997
 * Since: 1.9.10
1998
 **/
1999
void
2000
fwupd_device_add_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
2001
0
{
2002
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2003
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2004
0
  if (request_flag == 0)
2005
0
    return;
2006
0
  if ((priv->request_flags | request_flag) == priv->request_flags)
2007
0
    return;
2008
0
  priv->request_flags |= request_flag;
2009
0
  g_object_notify(G_OBJECT(self), "request-flags");
2010
0
}
2011
2012
/**
2013
 * fwupd_device_remove_request_flag:
2014
 * @self: a #FwupdDevice
2015
 * @request_flag: the #FwupdRequestFlags
2016
 *
2017
 * Removes a specific device request flag from the device.
2018
 *
2019
 * Since: 1.9.10
2020
 **/
2021
void
2022
fwupd_device_remove_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
2023
0
{
2024
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2025
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2026
0
  if (request_flag == 0)
2027
0
    return;
2028
0
  if ((priv->request_flags & request_flag) == 0)
2029
0
    return;
2030
0
  priv->request_flags &= ~request_flag;
2031
0
  g_object_notify(G_OBJECT(self), "request-flags");
2032
0
}
2033
2034
/**
2035
 * fwupd_device_has_request_flag:
2036
 * @self: a #FwupdDevice
2037
 * @request_flag: the #FwupdRequestFlags
2038
 *
2039
 * Finds if the device has a specific device request flag.
2040
 *
2041
 * Returns: %TRUE if the request_flag is set
2042
 *
2043
 * Since: 1.9.10
2044
 **/
2045
gboolean
2046
fwupd_device_has_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
2047
0
{
2048
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2049
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
2050
0
  return (priv->request_flags & request_flag) > 0;
2051
0
}
2052
2053
/**
2054
 * fwupd_device_get_created:
2055
 * @self: a #FwupdDevice
2056
 *
2057
 * Gets when the device was created.
2058
 *
2059
 * Returns: the UNIX time, or 0 if unset
2060
 *
2061
 * Since: 0.9.3
2062
 **/
2063
guint64
2064
fwupd_device_get_created(FwupdDevice *self)
2065
0
{
2066
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2067
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2068
0
  return priv->created;
2069
0
}
2070
2071
/**
2072
 * fwupd_device_set_created:
2073
 * @self: a #FwupdDevice
2074
 * @created: the UNIX time
2075
 *
2076
 * Sets when the device was created.
2077
 *
2078
 * Since: 0.9.3
2079
 **/
2080
void
2081
fwupd_device_set_created(FwupdDevice *self, guint64 created)
2082
0
{
2083
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2084
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2085
0
  priv->created = created;
2086
0
}
2087
2088
/**
2089
 * fwupd_device_get_modified:
2090
 * @self: a #FwupdDevice
2091
 *
2092
 * Gets when the device was modified.
2093
 *
2094
 * Returns: the UNIX time, or 0 if unset
2095
 *
2096
 * Since: 0.9.3
2097
 **/
2098
guint64
2099
fwupd_device_get_modified(FwupdDevice *self)
2100
0
{
2101
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2102
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2103
0
  return priv->modified;
2104
0
}
2105
2106
/**
2107
 * fwupd_device_set_modified:
2108
 * @self: a #FwupdDevice
2109
 * @modified: the UNIX time
2110
 *
2111
 * Sets when the device was modified.
2112
 *
2113
 * Since: 0.9.3
2114
 **/
2115
void
2116
fwupd_device_set_modified(FwupdDevice *self, guint64 modified)
2117
0
{
2118
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2119
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2120
0
  priv->modified = modified;
2121
0
}
2122
2123
/**
2124
 * fwupd_device_incorporate:
2125
 * @self: a #FwupdDevice
2126
 * @donor: Another #FwupdDevice
2127
 *
2128
 * Copy all properties from the donor object if they have not already been set.
2129
 *
2130
 * Since: 1.1.0
2131
 **/
2132
void
2133
fwupd_device_incorporate(FwupdDevice *self, FwupdDevice *donor)
2134
0
{
2135
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2136
0
  FwupdDevicePrivate *priv_donor = GET_PRIVATE(donor);
2137
2138
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2139
0
  g_return_if_fail(FWUPD_IS_DEVICE(donor));
2140
2141
0
  fwupd_device_add_flag(self, priv_donor->flags);
2142
0
  fwupd_device_add_request_flag(self, priv_donor->request_flags);
2143
0
  fwupd_device_add_problem(self, priv_donor->problems);
2144
0
  if (priv->created == 0)
2145
0
    fwupd_device_set_created(self, priv_donor->created);
2146
0
  if (priv->modified == 0)
2147
0
    fwupd_device_set_modified(self, priv_donor->modified);
2148
0
  if (priv->version_build_date == 0)
2149
0
    fwupd_device_set_version_build_date(self, priv_donor->version_build_date);
2150
0
  if (priv->flashes_left == 0)
2151
0
    fwupd_device_set_flashes_left(self, priv_donor->flashes_left);
2152
0
  if (priv->battery_level == FWUPD_BATTERY_LEVEL_INVALID)
2153
0
    fwupd_device_set_battery_level(self, priv_donor->battery_level);
2154
0
  if (priv->battery_threshold == FWUPD_BATTERY_LEVEL_INVALID)
2155
0
    fwupd_device_set_battery_threshold(self, priv_donor->battery_threshold);
2156
0
  if (priv->install_duration == 0)
2157
0
    fwupd_device_set_install_duration(self, priv_donor->install_duration);
2158
0
  if (priv->update_state == FWUPD_UPDATE_STATE_UNKNOWN)
2159
0
    fwupd_device_set_update_state(self, priv_donor->update_state);
2160
0
  if (priv->id == NULL)
2161
0
    fwupd_device_set_id(self, priv_donor->id);
2162
0
  if (priv->parent_id == NULL)
2163
0
    fwupd_device_set_parent_id(self, priv_donor->parent_id);
2164
0
  if (priv->composite_id == NULL)
2165
0
    fwupd_device_set_composite_id(self, priv_donor->composite_id);
2166
0
  if (priv->name == NULL)
2167
0
    fwupd_device_set_name(self, priv_donor->name);
2168
0
  if (priv->serial == NULL)
2169
0
    fwupd_device_set_serial(self, priv_donor->serial);
2170
0
  if (priv->summary == NULL)
2171
0
    fwupd_device_set_summary(self, priv_donor->summary);
2172
0
  if (priv->details_url == NULL)
2173
0
    fwupd_device_set_details_url(self, priv_donor->details_url);
2174
0
  if (priv->branch == NULL)
2175
0
    fwupd_device_set_branch(self, priv_donor->branch);
2176
0
  if (priv->vendor == NULL)
2177
0
    fwupd_device_set_vendor(self, priv_donor->vendor);
2178
0
  if (priv_donor->vendor_ids != NULL) {
2179
0
    for (guint i = 0; i < priv_donor->vendor_ids->len; i++) {
2180
0
      const gchar *tmp = g_ptr_array_index(priv_donor->vendor_ids, i);
2181
0
      fwupd_device_add_vendor_id(self, tmp);
2182
0
    }
2183
0
  }
2184
0
  if (priv->plugin == NULL)
2185
0
    fwupd_device_set_plugin(self, priv_donor->plugin);
2186
0
  if (priv_donor->protocols != NULL) {
2187
0
    for (guint i = 0; i < priv_donor->protocols->len; i++) {
2188
0
      const gchar *tmp = g_ptr_array_index(priv_donor->protocols, i);
2189
0
      fwupd_device_add_protocol(self, tmp);
2190
0
    }
2191
0
  }
2192
0
  if (priv->update_error == NULL)
2193
0
    fwupd_device_set_update_error(self, priv_donor->update_error);
2194
0
  if (priv->version == NULL)
2195
0
    fwupd_device_set_version(self, priv_donor->version);
2196
0
  if (priv->version_lowest == NULL)
2197
0
    fwupd_device_set_version_lowest(self, priv_donor->version_lowest);
2198
0
  if (priv->version_highest == NULL)
2199
0
    fwupd_device_set_version_highest(self, priv_donor->version_highest);
2200
0
  if (priv->version_bootloader == NULL)
2201
0
    fwupd_device_set_version_bootloader(self, priv_donor->version_bootloader);
2202
0
  if (priv->version_format == FWUPD_VERSION_FORMAT_UNKNOWN)
2203
0
    fwupd_device_set_version_format(self, priv_donor->version_format);
2204
0
  if (priv->version_raw == 0)
2205
0
    fwupd_device_set_version_raw(self, priv_donor->version_raw);
2206
0
  if (priv->version_lowest_raw == 0)
2207
0
    fwupd_device_set_version_lowest_raw(self, priv_donor->version_lowest_raw);
2208
0
  if (priv->version_highest_raw == 0)
2209
0
    fwupd_device_set_version_highest_raw(self, priv_donor->version_highest_raw);
2210
0
  if (priv->version_bootloader_raw == 0)
2211
0
    fwupd_device_set_version_bootloader_raw(self, priv_donor->version_bootloader_raw);
2212
0
  if (priv_donor->guids != NULL) {
2213
0
    for (guint i = 0; i < priv_donor->guids->len; i++) {
2214
0
      const gchar *tmp = g_ptr_array_index(priv_donor->guids, i);
2215
0
      fwupd_device_add_guid(self, tmp);
2216
0
    }
2217
0
  }
2218
0
  if (priv_donor->instance_ids != NULL) {
2219
0
    for (guint i = 0; i < priv_donor->instance_ids->len; i++) {
2220
0
      const gchar *tmp = g_ptr_array_index(priv_donor->instance_ids, i);
2221
0
      fwupd_device_add_instance_id(self, tmp);
2222
0
    }
2223
0
  }
2224
0
  if (priv_donor->icons != NULL) {
2225
0
    for (guint i = 0; i < priv_donor->icons->len; i++) {
2226
0
      const gchar *tmp = g_ptr_array_index(priv_donor->icons, i);
2227
0
      fwupd_device_add_icon(self, tmp);
2228
0
    }
2229
0
  }
2230
0
  if (priv_donor->checksums != NULL) {
2231
0
    for (guint i = 0; i < priv_donor->checksums->len; i++) {
2232
0
      const gchar *tmp = g_ptr_array_index(priv_donor->checksums, i);
2233
0
      fwupd_device_add_checksum(self, tmp);
2234
0
    }
2235
0
  }
2236
0
  if (priv_donor->releases != NULL) {
2237
0
    for (guint i = 0; i < priv_donor->releases->len; i++) {
2238
0
      FwupdRelease *tmp = g_ptr_array_index(priv_donor->releases, i);
2239
0
      fwupd_device_add_release(self, tmp);
2240
0
    }
2241
0
  }
2242
0
}
2243
2244
static void
2245
fwupd_device_add_variant(FwupdCodec *codec, GVariantBuilder *builder, FwupdCodecFlags flags)
2246
0
{
2247
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
2248
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2249
2250
0
  if (priv->id != NULL) {
2251
0
    g_variant_builder_add(builder,
2252
0
              "{sv}",
2253
0
              FWUPD_RESULT_KEY_DEVICE_ID,
2254
0
              g_variant_new_string(priv->id));
2255
0
  }
2256
0
  if (priv->parent_id != NULL) {
2257
0
    g_variant_builder_add(builder,
2258
0
              "{sv}",
2259
0
              FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
2260
0
              g_variant_new_string(priv->parent_id));
2261
0
  }
2262
0
  if (priv->composite_id != NULL) {
2263
0
    g_variant_builder_add(builder,
2264
0
              "{sv}",
2265
0
              FWUPD_RESULT_KEY_COMPOSITE_ID,
2266
0
              g_variant_new_string(priv->composite_id));
2267
0
  }
2268
0
  if (priv->guids != NULL && priv->guids->len > 0) {
2269
0
    const gchar *const *tmp = (const gchar *const *)priv->guids->pdata;
2270
0
    g_variant_builder_add(builder,
2271
0
              "{sv}",
2272
0
              FWUPD_RESULT_KEY_GUID,
2273
0
              g_variant_new_strv(tmp, priv->guids->len));
2274
0
  }
2275
0
  if (priv->icons != NULL && priv->icons->len > 0) {
2276
0
    const gchar *const *tmp = (const gchar *const *)priv->icons->pdata;
2277
0
    g_variant_builder_add(builder,
2278
0
              "{sv}",
2279
0
              FWUPD_RESULT_KEY_ICON,
2280
0
              g_variant_new_strv(tmp, priv->icons->len));
2281
0
  }
2282
0
  if (priv->name != NULL) {
2283
0
    g_variant_builder_add(builder,
2284
0
              "{sv}",
2285
0
              FWUPD_RESULT_KEY_NAME,
2286
0
              g_variant_new_string(priv->name));
2287
0
  }
2288
0
  if (priv->vendor != NULL) {
2289
0
    g_variant_builder_add(builder,
2290
0
              "{sv}",
2291
0
              FWUPD_RESULT_KEY_VENDOR,
2292
0
              g_variant_new_string(priv->vendor));
2293
0
  }
2294
0
  if (priv->vendor_ids != NULL && priv->vendor_ids->len > 0) {
2295
0
    g_autoptr(GString) str = g_string_new(NULL);
2296
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
2297
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
2298
0
      g_string_append_printf(str, "%s|", tmp);
2299
0
    }
2300
0
    if (str->len > 0)
2301
0
      g_string_truncate(str, str->len - 1);
2302
0
    g_variant_builder_add(builder,
2303
0
              "{sv}",
2304
0
              FWUPD_RESULT_KEY_VENDOR_ID,
2305
0
              g_variant_new_string(str->str));
2306
0
  }
2307
0
  if (priv->flags > 0) {
2308
0
    g_variant_builder_add(builder,
2309
0
              "{sv}",
2310
0
              FWUPD_RESULT_KEY_FLAGS,
2311
0
              g_variant_new_uint64(priv->flags));
2312
0
  }
2313
0
  if (priv->request_flags > 0) {
2314
0
    g_variant_builder_add(builder,
2315
0
              "{sv}",
2316
0
              FWUPD_RESULT_KEY_REQUEST_FLAGS,
2317
0
              g_variant_new_uint64(priv->request_flags));
2318
0
  }
2319
0
  if (priv->problems > 0) {
2320
0
    g_variant_builder_add(builder,
2321
0
              "{sv}",
2322
0
              FWUPD_RESULT_KEY_PROBLEMS,
2323
0
              g_variant_new_uint64(priv->problems));
2324
0
  }
2325
0
  if (priv->created > 0) {
2326
0
    g_variant_builder_add(builder,
2327
0
              "{sv}",
2328
0
              FWUPD_RESULT_KEY_CREATED,
2329
0
              g_variant_new_uint64(priv->created));
2330
0
  }
2331
0
  if (priv->modified > 0) {
2332
0
    g_variant_builder_add(builder,
2333
0
              "{sv}",
2334
0
              FWUPD_RESULT_KEY_MODIFIED,
2335
0
              g_variant_new_uint64(priv->modified));
2336
0
  }
2337
0
  if (priv->version_build_date > 0) {
2338
0
    g_variant_builder_add(builder,
2339
0
              "{sv}",
2340
0
              FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
2341
0
              g_variant_new_uint64(priv->version_build_date));
2342
0
  }
2343
2344
0
  if (priv->summary != NULL) {
2345
0
    g_variant_builder_add(builder,
2346
0
              "{sv}",
2347
0
              FWUPD_RESULT_KEY_SUMMARY,
2348
0
              g_variant_new_string(priv->summary));
2349
0
  }
2350
0
  if (priv->details_url != NULL) {
2351
0
    g_variant_builder_add(builder,
2352
0
              "{sv}",
2353
0
              FWUPD_RESULT_KEY_DETAILS_URL,
2354
0
              g_variant_new_string(priv->details_url));
2355
0
  }
2356
0
  if (priv->branch != NULL) {
2357
0
    g_variant_builder_add(builder,
2358
0
              "{sv}",
2359
0
              FWUPD_RESULT_KEY_BRANCH,
2360
0
              g_variant_new_string(priv->branch));
2361
0
  }
2362
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
2363
0
    g_autoptr(GString) str = g_string_new("");
2364
0
    for (guint i = 0; i < priv->checksums->len; i++) {
2365
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
2366
0
      g_string_append_printf(str, "%s,", checksum);
2367
0
    }
2368
0
    if (str->len > 0)
2369
0
      g_string_truncate(str, str->len - 1);
2370
0
    g_variant_builder_add(builder,
2371
0
              "{sv}",
2372
0
              FWUPD_RESULT_KEY_CHECKSUM,
2373
0
              g_variant_new_string(str->str));
2374
0
  }
2375
0
  if (priv->plugin != NULL) {
2376
0
    g_variant_builder_add(builder,
2377
0
              "{sv}",
2378
0
              FWUPD_RESULT_KEY_PLUGIN,
2379
0
              g_variant_new_string(priv->plugin));
2380
0
  }
2381
0
  if (priv->protocols != NULL && priv->protocols->len > 0) {
2382
0
    g_autoptr(GString) str = g_string_new(NULL);
2383
0
    for (guint i = 0; i < priv->protocols->len; i++) {
2384
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
2385
0
      g_string_append_printf(str, "%s|", tmp);
2386
0
    }
2387
0
    if (str->len > 0)
2388
0
      g_string_truncate(str, str->len - 1);
2389
0
    g_variant_builder_add(builder,
2390
0
              "{sv}",
2391
0
              FWUPD_RESULT_KEY_PROTOCOL,
2392
0
              g_variant_new_string(str->str));
2393
0
  }
2394
0
  if (priv->issues != NULL && priv->issues->len > 0) {
2395
0
    g_autofree const gchar **strv = g_new0(const gchar *, priv->issues->len + 1);
2396
0
    for (guint i = 0; i < priv->issues->len; i++)
2397
0
      strv[i] = (const gchar *)g_ptr_array_index(priv->issues, i);
2398
0
    g_variant_builder_add(builder,
2399
0
              "{sv}",
2400
0
              FWUPD_RESULT_KEY_ISSUES,
2401
0
              g_variant_new_strv(strv, -1));
2402
0
  }
2403
0
  if (priv->version != NULL) {
2404
0
    g_variant_builder_add(builder,
2405
0
              "{sv}",
2406
0
              FWUPD_RESULT_KEY_VERSION,
2407
0
              g_variant_new_string(priv->version));
2408
0
  }
2409
0
  if (priv->version_lowest != NULL) {
2410
0
    g_variant_builder_add(builder,
2411
0
              "{sv}",
2412
0
              FWUPD_RESULT_KEY_VERSION_LOWEST,
2413
0
              g_variant_new_string(priv->version_lowest));
2414
0
  }
2415
0
  if (priv->version_highest != NULL) {
2416
0
    g_variant_builder_add(builder,
2417
0
              "{sv}",
2418
0
              FWUPD_RESULT_KEY_VERSION_HIGHEST,
2419
0
              g_variant_new_string(priv->version_highest));
2420
0
  }
2421
0
  if (priv->version_bootloader != NULL) {
2422
0
    g_variant_builder_add(builder,
2423
0
              "{sv}",
2424
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
2425
0
              g_variant_new_string(priv->version_bootloader));
2426
0
  }
2427
0
  if (priv->version_raw > 0) {
2428
0
    g_variant_builder_add(builder,
2429
0
              "{sv}",
2430
0
              FWUPD_RESULT_KEY_VERSION_RAW,
2431
0
              g_variant_new_uint64(priv->version_raw));
2432
0
  }
2433
0
  if (priv->version_lowest_raw > 0) {
2434
0
    g_variant_builder_add(builder,
2435
0
              "{sv}",
2436
0
              FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
2437
0
              g_variant_new_uint64(priv->version_lowest_raw));
2438
0
  }
2439
0
  if (priv->version_highest_raw > 0) {
2440
0
    g_variant_builder_add(builder,
2441
0
              "{sv}",
2442
0
              FWUPD_RESULT_KEY_VERSION_HIGHEST_RAW,
2443
0
              g_variant_new_uint64(priv->version_highest_raw));
2444
0
  }
2445
0
  if (priv->version_bootloader_raw > 0) {
2446
0
    g_variant_builder_add(builder,
2447
0
              "{sv}",
2448
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
2449
0
              g_variant_new_uint64(priv->version_bootloader_raw));
2450
0
  }
2451
0
  if (priv->flashes_left > 0) {
2452
0
    g_variant_builder_add(builder,
2453
0
              "{sv}",
2454
0
              FWUPD_RESULT_KEY_FLASHES_LEFT,
2455
0
              g_variant_new_uint32(priv->flashes_left));
2456
0
  }
2457
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
2458
0
    g_variant_builder_add(builder,
2459
0
              "{sv}",
2460
0
              FWUPD_RESULT_KEY_BATTERY_LEVEL,
2461
0
              g_variant_new_uint32(priv->battery_level));
2462
0
  }
2463
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
2464
0
    g_variant_builder_add(builder,
2465
0
              "{sv}",
2466
0
              FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
2467
0
              g_variant_new_uint32(priv->battery_threshold));
2468
0
  }
2469
0
  if (priv->install_duration > 0) {
2470
0
    g_variant_builder_add(builder,
2471
0
              "{sv}",
2472
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
2473
0
              g_variant_new_uint32(priv->install_duration));
2474
0
  }
2475
0
  if (priv->update_error != NULL) {
2476
0
    g_variant_builder_add(builder,
2477
0
              "{sv}",
2478
0
              FWUPD_RESULT_KEY_UPDATE_ERROR,
2479
0
              g_variant_new_string(priv->update_error));
2480
0
  }
2481
0
  if (priv->update_state != FWUPD_UPDATE_STATE_UNKNOWN) {
2482
0
    g_variant_builder_add(builder,
2483
0
              "{sv}",
2484
0
              FWUPD_RESULT_KEY_UPDATE_STATE,
2485
0
              g_variant_new_uint32(priv->update_state));
2486
0
  }
2487
0
  if (priv->status != FWUPD_STATUS_UNKNOWN) {
2488
0
    g_variant_builder_add(builder,
2489
0
              "{sv}",
2490
0
              FWUPD_RESULT_KEY_STATUS,
2491
0
              g_variant_new_uint32(priv->status));
2492
0
  }
2493
0
  if (priv->percentage != 0) {
2494
0
    g_variant_builder_add(builder,
2495
0
              "{sv}",
2496
0
              FWUPD_RESULT_KEY_PERCENTAGE,
2497
0
              g_variant_new_uint32(priv->percentage));
2498
0
  }
2499
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
2500
0
    g_variant_builder_add(builder,
2501
0
              "{sv}",
2502
0
              FWUPD_RESULT_KEY_VERSION_FORMAT,
2503
0
              g_variant_new_uint32(priv->version_format));
2504
0
  }
2505
0
  if (priv->instance_ids != NULL && (flags & FWUPD_CODEC_FLAG_TRUSTED) > 0) {
2506
0
    if (priv->serial != NULL) {
2507
0
      g_variant_builder_add(builder,
2508
0
                "{sv}",
2509
0
                FWUPD_RESULT_KEY_SERIAL,
2510
0
                g_variant_new_string(priv->serial));
2511
0
    }
2512
0
    if (priv->instance_ids->len > 0) {
2513
0
      const gchar *const *tmp = (const gchar *const *)priv->instance_ids->pdata;
2514
0
      g_variant_builder_add(builder,
2515
0
                "{sv}",
2516
0
                FWUPD_RESULT_KEY_INSTANCE_IDS,
2517
0
                g_variant_new_strv(tmp, priv->instance_ids->len));
2518
0
    }
2519
0
  }
2520
2521
  /* create an array with all the metadata in */
2522
0
  if (priv->releases != NULL && priv->releases->len > 0) {
2523
0
    g_autofree GVariant **children = NULL;
2524
0
    children = g_new0(GVariant *, priv->releases->len);
2525
0
    for (guint i = 0; i < priv->releases->len; i++) {
2526
0
      FwupdRelease *release = g_ptr_array_index(priv->releases, i);
2527
0
      children[i] =
2528
0
          fwupd_codec_to_variant(FWUPD_CODEC(release), FWUPD_CODEC_FLAG_NONE);
2529
0
    }
2530
0
    g_variant_builder_add(
2531
0
        builder,
2532
0
        "{sv}",
2533
0
        FWUPD_RESULT_KEY_RELEASE,
2534
0
        g_variant_new_array(G_VARIANT_TYPE("a{sv}"), children, priv->releases->len));
2535
0
  }
2536
0
}
2537
2538
static void
2539
fwupd_device_from_key_value(FwupdDevice *self, const gchar *key, GVariant *value)
2540
0
{
2541
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_RELEASE) == 0) {
2542
0
    GVariantIter iter;
2543
0
    GVariant *child;
2544
0
    g_variant_iter_init(&iter, value);
2545
0
    while ((child = g_variant_iter_next_value(&iter))) {
2546
0
      g_autoptr(FwupdRelease) release = fwupd_release_new();
2547
0
      if (fwupd_codec_from_variant(FWUPD_CODEC(release), child, NULL))
2548
0
        fwupd_device_add_release(self, release);
2549
0
      g_variant_unref(child);
2550
0
    }
2551
0
    return;
2552
0
  }
2553
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DEVICE_ID) == 0) {
2554
0
    fwupd_device_set_id(self, fwupd_variant_get_string(value));
2555
0
    return;
2556
0
  }
2557
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PARENT_DEVICE_ID) == 0) {
2558
0
    fwupd_device_set_parent_id(self, fwupd_variant_get_string(value));
2559
0
    return;
2560
0
  }
2561
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_COMPOSITE_ID) == 0) {
2562
0
    fwupd_device_set_composite_id(self, fwupd_variant_get_string(value));
2563
0
    return;
2564
0
  }
2565
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FLAGS) == 0) {
2566
0
    fwupd_device_set_flags(self, fwupd_variant_get_uint64(value));
2567
0
    return;
2568
0
  }
2569
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PROBLEMS) == 0) {
2570
0
    fwupd_device_set_problems(self, fwupd_variant_get_uint64(value));
2571
0
    return;
2572
0
  }
2573
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_REQUEST_FLAGS) == 0) {
2574
0
    fwupd_device_set_request_flags(self, fwupd_variant_get_uint64(value));
2575
0
    return;
2576
0
  }
2577
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CREATED) == 0) {
2578
0
    fwupd_device_set_created(self, fwupd_variant_get_uint64(value));
2579
0
    return;
2580
0
  }
2581
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_MODIFIED) == 0) {
2582
0
    fwupd_device_set_modified(self, fwupd_variant_get_uint64(value));
2583
0
    return;
2584
0
  }
2585
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BUILD_DATE) == 0) {
2586
0
    fwupd_device_set_version_build_date(self, fwupd_variant_get_uint64(value));
2587
0
    return;
2588
0
  }
2589
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_GUID) == 0) {
2590
0
    g_autofree const gchar **strv = fwupd_variant_get_strv(value);
2591
0
    for (guint i = 0; strv != NULL && strv[i] != NULL; i++)
2592
0
      fwupd_device_add_guid(self, strv[i]);
2593
0
    return;
2594
0
  }
2595
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_INSTANCE_IDS) == 0) {
2596
0
    g_autofree const gchar **strv = fwupd_variant_get_strv(value);
2597
0
    for (guint i = 0; strv != NULL && strv[i] != NULL; i++)
2598
0
      fwupd_device_add_instance_id(self, strv[i]);
2599
0
    return;
2600
0
  }
2601
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_ICON) == 0) {
2602
0
    g_autofree const gchar **strv = fwupd_variant_get_strv(value);
2603
0
    for (guint i = 0; strv != NULL && strv[i] != NULL; i++)
2604
0
      fwupd_device_add_icon(self, strv[i]);
2605
0
    return;
2606
0
  }
2607
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
2608
0
    fwupd_device_set_name(self, fwupd_variant_get_string(value));
2609
0
    return;
2610
0
  }
2611
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR) == 0) {
2612
0
    fwupd_device_set_vendor(self, fwupd_variant_get_string(value));
2613
0
    return;
2614
0
  }
2615
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR_ID) == 0) {
2616
0
    const gchar *str = fwupd_variant_get_string(value);
2617
0
    if (str != NULL) {
2618
0
      g_auto(GStrv) strv = g_strsplit(str, "|", -1);
2619
0
      for (guint i = 0; strv[i] != NULL; i++)
2620
0
        fwupd_device_add_vendor_id(self, strv[i]);
2621
0
    }
2622
0
    return;
2623
0
  }
2624
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SERIAL) == 0) {
2625
0
    fwupd_device_set_serial(self, fwupd_variant_get_string(value));
2626
0
    return;
2627
0
  }
2628
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SUMMARY) == 0) {
2629
0
    fwupd_device_set_summary(self, fwupd_variant_get_string(value));
2630
0
    return;
2631
0
  }
2632
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DETAILS_URL) == 0) {
2633
0
    fwupd_device_set_details_url(self, fwupd_variant_get_string(value));
2634
0
    return;
2635
0
  }
2636
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BRANCH) == 0) {
2637
0
    fwupd_device_set_branch(self, fwupd_variant_get_string(value));
2638
0
    return;
2639
0
  }
2640
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CHECKSUM) == 0) {
2641
0
    const gchar *str = fwupd_variant_get_string(value);
2642
0
    if (str != NULL) {
2643
0
      g_auto(GStrv) split = g_strsplit(str, ",", -1);
2644
0
      for (guint i = 0; split[i] != NULL; i++)
2645
0
        fwupd_device_add_checksum(self, split[i]);
2646
0
    }
2647
0
    return;
2648
0
  }
2649
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PLUGIN) == 0) {
2650
0
    fwupd_device_set_plugin(self, fwupd_variant_get_string(value));
2651
0
    return;
2652
0
  }
2653
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PROTOCOL) == 0) {
2654
0
    const gchar *str = fwupd_variant_get_string(value);
2655
0
    if (str != NULL) {
2656
0
      g_auto(GStrv) strv = g_strsplit(str, "|", -1);
2657
0
      for (guint i = 0; strv[i] != NULL; i++)
2658
0
        fwupd_device_add_protocol(self, strv[i]);
2659
0
    }
2660
0
    return;
2661
0
  }
2662
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_ISSUES) == 0) {
2663
0
    g_autofree const gchar **strv = fwupd_variant_get_strv(value);
2664
0
    for (guint i = 0; strv != NULL && strv[i] != NULL; i++)
2665
0
      fwupd_device_add_issue(self, strv[i]);
2666
0
    return;
2667
0
  }
2668
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION) == 0) {
2669
0
    fwupd_device_set_version(self, fwupd_variant_get_string(value));
2670
0
    return;
2671
0
  }
2672
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_LOWEST) == 0) {
2673
0
    fwupd_device_set_version_lowest(self, fwupd_variant_get_string(value));
2674
0
    return;
2675
0
  }
2676
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_HIGHEST) == 0) {
2677
0
    fwupd_device_set_version_highest(self, fwupd_variant_get_string(value));
2678
0
    return;
2679
0
  }
2680
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BOOTLOADER) == 0) {
2681
0
    fwupd_device_set_version_bootloader(self, fwupd_variant_get_string(value));
2682
0
    return;
2683
0
  }
2684
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FLASHES_LEFT) == 0) {
2685
0
    fwupd_device_set_flashes_left(self, fwupd_variant_get_uint32(value));
2686
0
    return;
2687
0
  }
2688
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BATTERY_LEVEL) == 0) {
2689
0
    fwupd_device_set_battery_level(self, fwupd_variant_get_uint32(value));
2690
0
    return;
2691
0
  }
2692
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BATTERY_THRESHOLD) == 0) {
2693
0
    fwupd_device_set_battery_threshold(self, fwupd_variant_get_uint32(value));
2694
0
    return;
2695
0
  }
2696
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_INSTALL_DURATION) == 0) {
2697
0
    fwupd_device_set_install_duration(self, fwupd_variant_get_uint32(value));
2698
0
    return;
2699
0
  }
2700
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_ERROR) == 0) {
2701
0
    fwupd_device_set_update_error(self, fwupd_variant_get_string(value));
2702
0
    return;
2703
0
  }
2704
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_STATE) == 0) {
2705
0
    fwupd_device_set_update_state(self, fwupd_variant_get_uint32(value));
2706
0
    return;
2707
0
  }
2708
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_STATUS) == 0) {
2709
0
    fwupd_device_set_status(self, fwupd_variant_get_uint32(value));
2710
0
    return;
2711
0
  }
2712
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PERCENTAGE) == 0) {
2713
0
    fwupd_device_set_percentage(self, fwupd_variant_get_uint32(value));
2714
0
    return;
2715
0
  }
2716
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_FORMAT) == 0) {
2717
0
    fwupd_device_set_version_format(self, fwupd_variant_get_uint32(value));
2718
0
    return;
2719
0
  }
2720
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_RAW) == 0) {
2721
0
    fwupd_device_set_version_raw(self, fwupd_variant_get_uint64(value));
2722
0
    return;
2723
0
  }
2724
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_LOWEST_RAW) == 0) {
2725
0
    fwupd_device_set_version_lowest_raw(self, fwupd_variant_get_uint64(value));
2726
0
    return;
2727
0
  }
2728
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_HIGHEST_RAW) == 0) {
2729
0
    fwupd_device_set_version_highest_raw(self, fwupd_variant_get_uint64(value));
2730
0
    return;
2731
0
  }
2732
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW) == 0) {
2733
0
    fwupd_device_set_version_bootloader_raw(self, fwupd_variant_get_uint64(value));
2734
0
    return;
2735
0
  }
2736
0
}
2737
2738
static void
2739
fwupd_device_string_append_flags(GString *str, guint idt, const gchar *key, guint64 device_flags)
2740
0
{
2741
0
  g_autoptr(GString) tmp = g_string_new("");
2742
0
  for (guint i = 0; i < 64; i++) {
2743
0
    if ((device_flags & ((guint64)1 << i)) == 0)
2744
0
      continue;
2745
0
    g_string_append_printf(tmp, "%s|", fwupd_device_flag_to_string((guint64)1 << i));
2746
0
  }
2747
0
  if (tmp->len == 0) {
2748
0
    g_string_append(tmp, fwupd_device_flag_to_string(0));
2749
0
  } else {
2750
0
    g_string_truncate(tmp, tmp->len - 1);
2751
0
  }
2752
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2753
0
}
2754
2755
static void
2756
fwupd_device_string_append_request_flags(GString *str,
2757
           guint idt,
2758
           const gchar *key,
2759
           guint64 request_flags)
2760
0
{
2761
0
  g_autoptr(GString) tmp = g_string_new("");
2762
0
  for (guint i = 0; i < 64; i++) {
2763
0
    if ((request_flags & ((guint64)1 << i)) == 0)
2764
0
      continue;
2765
0
    g_string_append_printf(tmp, "%s|", fwupd_request_flag_to_string((guint64)1 << i));
2766
0
  }
2767
0
  if (tmp->len == 0) {
2768
0
    g_string_append(tmp, fwupd_request_flag_to_string(0));
2769
0
  } else {
2770
0
    g_string_truncate(tmp, tmp->len - 1);
2771
0
  }
2772
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2773
0
}
2774
2775
static void
2776
fwupd_device_string_append_problems(GString *str,
2777
            guint idt,
2778
            const gchar *key,
2779
            guint64 device_problems)
2780
0
{
2781
0
  g_autoptr(GString) tmp = g_string_new("");
2782
0
  for (guint i = 0; i < 64; i++) {
2783
0
    if ((device_problems & ((guint64)1 << i)) == 0)
2784
0
      continue;
2785
0
    g_string_append_printf(tmp, "%s|", fwupd_device_problem_to_string((guint64)1 << i));
2786
0
  }
2787
0
  if (tmp->len == 0) {
2788
0
    g_string_append(tmp, fwupd_device_problem_to_string(0));
2789
0
  } else {
2790
0
    g_string_truncate(tmp, tmp->len - 1);
2791
0
  }
2792
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2793
0
}
2794
2795
/**
2796
 * fwupd_device_get_update_state:
2797
 * @self: a #FwupdDevice
2798
 *
2799
 * Gets the update state.
2800
 *
2801
 * Returns: the update state, or %FWUPD_UPDATE_STATE_UNKNOWN if unset
2802
 *
2803
 * Since: 0.9.8
2804
 **/
2805
FwupdUpdateState
2806
fwupd_device_get_update_state(FwupdDevice *self)
2807
0
{
2808
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2809
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FWUPD_UPDATE_STATE_UNKNOWN);
2810
0
  return priv->update_state;
2811
0
}
2812
2813
/**
2814
 * fwupd_device_set_update_state:
2815
 * @self: a #FwupdDevice
2816
 * @update_state: the state, e.g. %FWUPD_UPDATE_STATE_PENDING
2817
 *
2818
 * Sets the update state.
2819
 *
2820
 * Since: 0.9.8
2821
 **/
2822
void
2823
fwupd_device_set_update_state(FwupdDevice *self, FwupdUpdateState update_state)
2824
0
{
2825
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2826
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2827
0
  if (priv->update_state == update_state)
2828
0
    return;
2829
0
  priv->update_state = update_state;
2830
0
  g_object_notify(G_OBJECT(self), "update-state");
2831
0
}
2832
2833
/**
2834
 * fwupd_device_get_version_format:
2835
 * @self: a #FwupdDevice
2836
 *
2837
 * Gets the version format.
2838
 *
2839
 * Returns: the version format, or %FWUPD_VERSION_FORMAT_UNKNOWN if unset
2840
 *
2841
 * Since: 1.2.9
2842
 **/
2843
FwupdVersionFormat
2844
fwupd_device_get_version_format(FwupdDevice *self)
2845
0
{
2846
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2847
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FWUPD_VERSION_FORMAT_UNKNOWN);
2848
0
  return priv->version_format;
2849
0
}
2850
2851
/**
2852
 * fwupd_device_set_version_format:
2853
 * @self: a #FwupdDevice
2854
 * @version_format: the version format, e.g. %FWUPD_VERSION_FORMAT_NUMBER
2855
 *
2856
 * Sets the version format.
2857
 *
2858
 * Since: 1.2.9
2859
 **/
2860
void
2861
fwupd_device_set_version_format(FwupdDevice *self, FwupdVersionFormat version_format)
2862
0
{
2863
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2864
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2865
0
  priv->version_format = version_format;
2866
0
}
2867
2868
/**
2869
 * fwupd_device_get_version_raw:
2870
 * @self: a #FwupdDevice
2871
 *
2872
 * Gets the raw version number from the hardware before converted to a string.
2873
 *
2874
 * Returns: the hardware version, or 0 if unset
2875
 *
2876
 * Since: 1.3.6
2877
 **/
2878
guint64
2879
fwupd_device_get_version_raw(FwupdDevice *self)
2880
0
{
2881
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2882
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2883
0
  return priv->version_raw;
2884
0
}
2885
2886
/**
2887
 * fwupd_device_set_version_raw:
2888
 * @self: a #FwupdDevice
2889
 * @version_raw: the raw hardware version
2890
 *
2891
 * Sets the raw version number from the hardware before converted to a string.
2892
 *
2893
 * Since: 1.3.6
2894
 **/
2895
void
2896
fwupd_device_set_version_raw(FwupdDevice *self, guint64 version_raw)
2897
0
{
2898
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2899
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2900
0
  priv->version_raw = version_raw;
2901
0
}
2902
2903
/**
2904
 * fwupd_device_get_version_build_date:
2905
 * @self: a #FwupdDevice
2906
 *
2907
 * Gets the date when the firmware was built.
2908
 *
2909
 * Returns: the UNIX time, or 0 if unset
2910
 *
2911
 * Since: 1.6.2
2912
 **/
2913
guint64
2914
fwupd_device_get_version_build_date(FwupdDevice *self)
2915
0
{
2916
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2917
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2918
0
  return priv->version_build_date;
2919
0
}
2920
2921
/**
2922
 * fwupd_device_set_version_build_date:
2923
 * @self: a #FwupdDevice
2924
 * @version_build_date: the UNIX time
2925
 *
2926
 * Sets the date when the firmware was built.
2927
 *
2928
 * Since: 1.6.2
2929
 **/
2930
void
2931
fwupd_device_set_version_build_date(FwupdDevice *self, guint64 version_build_date)
2932
0
{
2933
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2934
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2935
0
  priv->version_build_date = version_build_date;
2936
0
}
2937
2938
/**
2939
 * fwupd_device_get_update_error:
2940
 * @self: a #FwupdDevice
2941
 *
2942
 * Gets the update error string.
2943
 *
2944
 * Returns: the update error string, or %NULL if unset
2945
 *
2946
 * Since: 0.9.8
2947
 **/
2948
const gchar *
2949
fwupd_device_get_update_error(FwupdDevice *self)
2950
0
{
2951
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2952
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
2953
0
  return priv->update_error;
2954
0
}
2955
2956
/**
2957
 * fwupd_device_set_update_error:
2958
 * @self: a #FwupdDevice
2959
 * @update_error: (nullable): the update error string
2960
 *
2961
 * Sets the update error string.
2962
 *
2963
 * Since: 0.9.8
2964
 **/
2965
void
2966
fwupd_device_set_update_error(FwupdDevice *self, const gchar *update_error)
2967
0
{
2968
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2969
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2970
2971
  /* not changed */
2972
0
  if (g_strcmp0(priv->update_error, update_error) == 0)
2973
0
    return;
2974
2975
0
  g_free(priv->update_error);
2976
0
  priv->update_error = g_strdup(update_error);
2977
0
  g_object_notify(G_OBJECT(self), "update-error");
2978
0
}
2979
2980
/**
2981
 * fwupd_device_get_release_default:
2982
 * @self: a #FwupdDevice
2983
 *
2984
 * Gets the default release for this device.
2985
 *
2986
 * Returns: (transfer none): the #FwupdRelease, or %NULL if not set
2987
 *
2988
 * Since: 0.9.8
2989
 **/
2990
FwupdRelease *
2991
fwupd_device_get_release_default(FwupdDevice *self)
2992
0
{
2993
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2994
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
2995
0
  if (priv->releases == NULL || priv->releases->len == 0)
2996
0
    return NULL;
2997
0
  return FWUPD_RELEASE(g_ptr_array_index(priv->releases, 0));
2998
0
}
2999
3000
static void
3001
fwupd_device_ensure_releases(FwupdDevice *self)
3002
0
{
3003
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3004
0
  if (priv->releases == NULL)
3005
0
    priv->releases = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
3006
0
}
3007
3008
/**
3009
 * fwupd_device_get_releases:
3010
 * @self: a #FwupdDevice
3011
 *
3012
 * Gets all the releases for this device.
3013
 *
3014
 * Returns: (transfer none) (element-type FwupdRelease): array of releases
3015
 *
3016
 * Since: 0.9.8
3017
 **/
3018
GPtrArray *
3019
fwupd_device_get_releases(FwupdDevice *self)
3020
0
{
3021
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3022
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
3023
0
  fwupd_device_ensure_releases(self);
3024
0
  return priv->releases;
3025
0
}
3026
3027
/**
3028
 * fwupd_device_add_release:
3029
 * @self: a #FwupdDevice
3030
 * @release: (not nullable): a release
3031
 *
3032
 * Adds a release for this device.
3033
 *
3034
 * Since: 0.9.8
3035
 **/
3036
void
3037
fwupd_device_add_release(FwupdDevice *self, FwupdRelease *release)
3038
0
{
3039
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3040
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
3041
0
  g_return_if_fail(FWUPD_IS_RELEASE(release));
3042
0
  fwupd_device_ensure_releases(self);
3043
0
  g_ptr_array_add(priv->releases, g_object_ref(release));
3044
0
}
3045
3046
/**
3047
 * fwupd_device_get_status:
3048
 * @self: a #FwupdDevice
3049
 *
3050
 * Returns what the device is currently doing.
3051
 *
3052
 * Returns: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE
3053
 *
3054
 * Since: 1.4.0
3055
 **/
3056
FwupdStatus
3057
fwupd_device_get_status(FwupdDevice *self)
3058
0
{
3059
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3060
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
3061
0
  return priv->status;
3062
0
}
3063
3064
/**
3065
 * fwupd_device_set_status:
3066
 * @self: a #FwupdDevice
3067
 * @status: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE
3068
 *
3069
 * Sets what the device is currently doing.
3070
 *
3071
 * Since: 1.4.0
3072
 **/
3073
void
3074
fwupd_device_set_status(FwupdDevice *self, FwupdStatus status)
3075
0
{
3076
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3077
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
3078
0
  if (priv->status == status)
3079
0
    return;
3080
0
  priv->status = status;
3081
0
  g_object_notify(G_OBJECT(self), "status");
3082
0
}
3083
3084
/**
3085
 * fwupd_device_get_percentage:
3086
 * @self: a #FwupdDevice
3087
 *
3088
 * Returns the percentage completion of the device.
3089
 *
3090
 * Returns: the percentage value
3091
 *
3092
 * Since: 1.8.11
3093
 **/
3094
guint
3095
fwupd_device_get_percentage(FwupdDevice *self)
3096
0
{
3097
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3098
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
3099
0
  return priv->percentage;
3100
0
}
3101
3102
/**
3103
 * fwupd_device_set_percentage:
3104
 * @self: a #FwupdDevice
3105
 * @percentage: the percentage value
3106
 *
3107
 * Sets the percentage completion of the device.
3108
 *
3109
 * Since: 1.8.11
3110
 **/
3111
void
3112
fwupd_device_set_percentage(FwupdDevice *self, guint percentage)
3113
0
{
3114
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3115
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
3116
0
  if (priv->percentage == percentage)
3117
0
    return;
3118
0
  priv->percentage = percentage;
3119
0
  g_object_notify(G_OBJECT(self), "percentage");
3120
0
}
3121
3122
static void
3123
fwupd_device_string_append_update_state(GString *str,
3124
          guint idt,
3125
          const gchar *key,
3126
          FwupdUpdateState value)
3127
0
{
3128
0
  if (value == FWUPD_UPDATE_STATE_UNKNOWN)
3129
0
    return;
3130
0
  fwupd_codec_string_append(str, idt, key, fwupd_update_state_to_string(value));
3131
0
}
3132
3133
static void
3134
fwupd_device_add_json(FwupdCodec *codec, FwupdJsonObject *json_obj, FwupdCodecFlags flags)
3135
0
{
3136
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3137
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3138
3139
0
  if (priv->name != NULL)
3140
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_NAME, priv->name);
3141
0
  if (priv->id != NULL)
3142
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_DEVICE_ID, priv->id);
3143
0
  if (priv->parent_id != NULL) {
3144
0
    fwupd_json_object_add_string(json_obj,
3145
0
               FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
3146
0
               priv->parent_id);
3147
0
  }
3148
0
  if (priv->composite_id != NULL) {
3149
0
    fwupd_json_object_add_string(json_obj,
3150
0
               FWUPD_RESULT_KEY_COMPOSITE_ID,
3151
0
               priv->composite_id);
3152
0
  }
3153
0
  if ((flags & FWUPD_CODEC_FLAG_TRUSTED) > 0 && priv->instance_ids != NULL &&
3154
0
      priv->instance_ids->len > 0) {
3155
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3156
0
    for (guint i = 0; i < priv->instance_ids->len; i++) {
3157
0
      const gchar *instance_id = g_ptr_array_index(priv->instance_ids, i);
3158
0
      fwupd_json_array_add_string(json_arr, instance_id);
3159
0
    }
3160
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_INSTANCE_IDS, json_arr);
3161
0
  }
3162
0
  if (priv->guids != NULL && priv->guids->len > 0) {
3163
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3164
0
    for (guint i = 0; i < priv->guids->len; i++) {
3165
0
      const gchar *guid = g_ptr_array_index(priv->guids, i);
3166
0
      fwupd_json_array_add_string(json_arr, guid);
3167
0
    }
3168
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_GUID, json_arr);
3169
0
  }
3170
0
  if (priv->serial != NULL && (flags & FWUPD_CODEC_FLAG_TRUSTED) > 0)
3171
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SERIAL, priv->serial);
3172
0
  if (priv->summary != NULL)
3173
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
3174
0
  if (priv->details_url != NULL)
3175
0
    fwupd_json_object_add_string(json_obj,
3176
0
               FWUPD_RESULT_KEY_DETAILS_URL,
3177
0
               priv->details_url);
3178
0
  if (priv->branch != NULL)
3179
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_BRANCH, priv->branch);
3180
0
  if (priv->plugin != NULL)
3181
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
3182
0
  if (priv->protocols != NULL && priv->protocols->len > 0) {
3183
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3184
0
    for (guint i = 0; i < priv->protocols->len; i++) {
3185
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
3186
0
      fwupd_json_array_add_string(json_arr, tmp);
3187
0
    }
3188
0
    fwupd_json_object_add_array(json_obj, "Protocols", json_arr);
3189
0
  }
3190
0
  if (priv->issues != NULL && priv->issues->len > 0) {
3191
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3192
0
    for (guint i = 0; i < priv->issues->len; i++) {
3193
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
3194
0
      fwupd_json_array_add_string(json_arr, tmp);
3195
0
    }
3196
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_ISSUES, json_arr);
3197
0
  }
3198
0
  if (priv->flags != FWUPD_DEVICE_FLAG_NONE) {
3199
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3200
0
    for (guint i = 0; i < 64; i++) {
3201
0
      const gchar *tmp;
3202
0
      if ((priv->flags & ((guint64)1 << i)) == 0)
3203
0
        continue;
3204
0
      tmp = fwupd_device_flag_to_string((guint64)1 << i);
3205
0
      fwupd_json_array_add_string(json_arr, tmp);
3206
0
    }
3207
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_FLAGS, json_arr);
3208
0
  }
3209
0
  if (priv->request_flags != FWUPD_REQUEST_FLAG_NONE) {
3210
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3211
0
    for (guint i = 0; i < 64; i++) {
3212
0
      const gchar *tmp;
3213
0
      if ((priv->request_flags & ((guint64)1 << i)) == 0)
3214
0
        continue;
3215
0
      tmp = fwupd_request_flag_to_string((guint64)1 << i);
3216
0
      fwupd_json_array_add_string(json_arr, tmp);
3217
0
    }
3218
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_REQUEST_FLAGS, json_arr);
3219
0
  }
3220
0
  if (priv->problems != FWUPD_DEVICE_PROBLEM_NONE) {
3221
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3222
0
    for (guint i = 0; i < 64; i++) {
3223
0
      const gchar *tmp;
3224
0
      if ((priv->problems & ((guint64)1 << i)) == 0)
3225
0
        continue;
3226
0
      tmp = fwupd_device_problem_to_string((guint64)1 << i);
3227
0
      fwupd_json_array_add_string(json_arr, tmp);
3228
0
    }
3229
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_PROBLEMS, json_arr);
3230
0
  }
3231
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
3232
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3233
0
    for (guint i = 0; i < priv->checksums->len; i++) {
3234
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
3235
0
      fwupd_json_array_add_string(json_arr, checksum);
3236
0
    }
3237
0
    fwupd_json_object_add_array(json_obj, "Checksums", json_arr);
3238
0
  }
3239
0
  if (priv->vendor != NULL)
3240
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
3241
0
  if (priv->vendor_ids != NULL && priv->vendor_ids->len > 0) {
3242
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3243
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
3244
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
3245
0
      fwupd_json_array_add_string(json_arr, tmp);
3246
0
    }
3247
0
    fwupd_json_object_add_array(json_obj, "VendorIds", json_arr);
3248
0
  }
3249
0
  if (priv->version != NULL)
3250
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VERSION, priv->version);
3251
0
  if (priv->version_lowest != NULL) {
3252
0
    fwupd_json_object_add_string(json_obj,
3253
0
               FWUPD_RESULT_KEY_VERSION_LOWEST,
3254
0
               priv->version_lowest);
3255
0
  }
3256
0
  if (priv->version_highest != NULL) {
3257
0
    fwupd_json_object_add_string(json_obj,
3258
0
               FWUPD_RESULT_KEY_VERSION_HIGHEST,
3259
0
               priv->version_highest);
3260
0
  }
3261
0
  if (priv->version_bootloader != NULL) {
3262
0
    fwupd_json_object_add_string(json_obj,
3263
0
               FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
3264
0
               priv->version_bootloader);
3265
0
  }
3266
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
3267
0
    fwupd_json_object_add_string(json_obj,
3268
0
               FWUPD_RESULT_KEY_VERSION_FORMAT,
3269
0
               fwupd_version_format_to_string(priv->version_format));
3270
0
  }
3271
0
  if (priv->flashes_left > 0) {
3272
0
    fwupd_json_object_add_integer(json_obj,
3273
0
                FWUPD_RESULT_KEY_FLASHES_LEFT,
3274
0
                priv->flashes_left);
3275
0
  }
3276
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
3277
0
    fwupd_json_object_add_integer(json_obj,
3278
0
                FWUPD_RESULT_KEY_BATTERY_LEVEL,
3279
0
                priv->battery_level);
3280
0
  }
3281
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
3282
0
    fwupd_json_object_add_integer(json_obj,
3283
0
                FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3284
0
                priv->battery_threshold);
3285
0
  }
3286
0
  if (priv->version_raw > 0) {
3287
0
    fwupd_json_object_add_integer(json_obj,
3288
0
                FWUPD_RESULT_KEY_VERSION_RAW,
3289
0
                priv->version_raw);
3290
0
  }
3291
0
  if (priv->version_lowest_raw > 0)
3292
0
    fwupd_json_object_add_integer(json_obj,
3293
0
                FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
3294
0
                priv->version_lowest_raw);
3295
0
  if (priv->version_highest_raw > 0)
3296
0
    fwupd_json_object_add_integer(json_obj,
3297
0
                FWUPD_RESULT_KEY_VERSION_HIGHEST_RAW,
3298
0
                priv->version_highest_raw);
3299
0
  if (priv->version_bootloader_raw > 0)
3300
0
    fwupd_json_object_add_integer(json_obj,
3301
0
                FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
3302
0
                priv->version_bootloader_raw);
3303
0
  if (priv->version_build_date > 0) {
3304
0
    fwupd_json_object_add_integer(json_obj,
3305
0
                FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3306
0
                priv->version_build_date);
3307
0
  }
3308
0
  if (priv->icons != NULL && priv->icons->len > 0) {
3309
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3310
0
    for (guint i = 0; i < priv->icons->len; i++) {
3311
0
      const gchar *icon = g_ptr_array_index(priv->icons, i);
3312
0
      fwupd_json_array_add_string(json_arr, icon);
3313
0
    }
3314
0
    fwupd_json_object_add_array(json_obj, "Icons", json_arr);
3315
0
  }
3316
0
  if (priv->install_duration > 0) {
3317
0
    fwupd_json_object_add_integer(json_obj,
3318
0
                FWUPD_RESULT_KEY_INSTALL_DURATION,
3319
0
                priv->install_duration);
3320
0
  }
3321
0
  if (priv->created > 0)
3322
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_CREATED, priv->created);
3323
0
  if (priv->modified > 0)
3324
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_MODIFIED, priv->modified);
3325
0
  if (priv->update_state > 0) {
3326
0
    fwupd_json_object_add_integer(json_obj,
3327
0
                FWUPD_RESULT_KEY_UPDATE_STATE,
3328
0
                priv->update_state);
3329
0
  }
3330
0
  if (priv->status > 0)
3331
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_STATUS, priv->status);
3332
0
  if (priv->percentage > 0) {
3333
0
    fwupd_json_object_add_integer(json_obj,
3334
0
                FWUPD_RESULT_KEY_PERCENTAGE,
3335
0
                priv->percentage);
3336
0
  }
3337
0
  if (priv->update_error != NULL) {
3338
0
    fwupd_json_object_add_string(json_obj,
3339
0
               FWUPD_RESULT_KEY_UPDATE_ERROR,
3340
0
               priv->update_error);
3341
0
  }
3342
0
  if (priv->releases != NULL && priv->releases->len > 0)
3343
0
    fwupd_codec_array_to_json(priv->releases, "Releases", json_obj, flags);
3344
0
}
3345
3346
static gboolean
3347
fwupd_device_from_json(FwupdCodec *codec, FwupdJsonObject *json_obj, GError **error)
3348
0
{
3349
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3350
0
  const gchar *tmp;
3351
0
  gint64 tmp64;
3352
0
  g_autoptr(FwupdJsonArray) json_array_checksums = NULL;
3353
0
  g_autoptr(FwupdJsonArray) json_array_flags = NULL;
3354
0
  g_autoptr(FwupdJsonArray) json_array_guids = NULL;
3355
0
  g_autoptr(FwupdJsonArray) json_array_icons = NULL;
3356
0
  g_autoptr(FwupdJsonArray) json_array_instance_ids = NULL;
3357
0
  g_autoptr(FwupdJsonArray) json_array_issues = NULL;
3358
0
  g_autoptr(FwupdJsonArray) json_array_problems = NULL;
3359
0
  g_autoptr(FwupdJsonArray) json_array_protocols = NULL;
3360
0
  g_autoptr(FwupdJsonArray) json_array_requests = NULL;
3361
0
  g_autoptr(FwupdJsonArray) json_array_vendor_ids = NULL;
3362
3363
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
3364
0
  g_return_val_if_fail(json_obj != NULL, FALSE);
3365
0
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
3366
3367
  /* this has to exist */
3368
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_DEVICE_ID, error);
3369
0
  if (tmp == NULL)
3370
0
    return FALSE;
3371
0
  fwupd_device_set_id(self, tmp);
3372
3373
  /* also optional */
3374
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_NAME, NULL);
3375
0
  if (tmp != NULL)
3376
0
    fwupd_device_set_name(self, tmp);
3377
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PARENT_DEVICE_ID, NULL);
3378
0
  if (tmp != NULL)
3379
0
    fwupd_device_set_parent_id(self, tmp);
3380
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_COMPOSITE_ID, NULL);
3381
0
  if (tmp != NULL)
3382
0
    fwupd_device_set_composite_id(self, tmp);
3383
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PROTOCOL, NULL);
3384
0
  if (tmp != NULL)
3385
0
    fwupd_device_add_protocol(self, tmp);
3386
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_SERIAL, NULL);
3387
0
  if (tmp != NULL)
3388
0
    fwupd_device_set_serial(self, tmp);
3389
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_SUMMARY, NULL);
3390
0
  if (tmp != NULL)
3391
0
    fwupd_device_set_summary(self, tmp);
3392
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_DETAILS_URL, NULL);
3393
0
  if (tmp != NULL)
3394
0
    fwupd_device_set_details_url(self, tmp);
3395
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_BRANCH, NULL);
3396
0
  if (tmp != NULL)
3397
0
    fwupd_device_set_branch(self, tmp);
3398
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PLUGIN, NULL);
3399
0
  if (tmp != NULL)
3400
0
    fwupd_device_set_plugin(self, tmp);
3401
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VENDOR, NULL);
3402
0
  if (tmp != NULL)
3403
0
    fwupd_device_set_vendor(self, tmp);
3404
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VENDOR_ID, NULL);
3405
0
  if (tmp != NULL) {
3406
0
    g_auto(GStrv) split = g_strsplit(tmp, "|", -1);
3407
0
    for (guint i = 0; split[i] != NULL; i++)
3408
0
      fwupd_device_add_vendor_id(self, split[i]);
3409
0
  }
3410
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION, NULL);
3411
0
  if (tmp != NULL)
3412
0
    fwupd_device_set_version(self, tmp);
3413
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_LOWEST, NULL);
3414
0
  if (tmp != NULL)
3415
0
    fwupd_device_set_version_lowest(self, tmp);
3416
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_HIGHEST, NULL);
3417
0
  if (tmp != NULL)
3418
0
    fwupd_device_set_version_highest(self, tmp);
3419
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_BOOTLOADER, NULL);
3420
0
  if (tmp != NULL)
3421
0
    fwupd_device_set_version_bootloader(self, tmp);
3422
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_FORMAT, NULL);
3423
0
  if (tmp != NULL)
3424
0
    fwupd_device_set_version_format(self, fwupd_version_format_from_string(tmp));
3425
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3426
0
              FWUPD_RESULT_KEY_FLASHES_LEFT,
3427
0
              &tmp64,
3428
0
              0,
3429
0
              error))
3430
0
    return FALSE;
3431
0
  fwupd_device_set_flashes_left(self, tmp64);
3432
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3433
0
              FWUPD_RESULT_KEY_BATTERY_LEVEL,
3434
0
              &tmp64,
3435
0
              0,
3436
0
              error))
3437
0
    return FALSE;
3438
0
  fwupd_device_set_battery_level(self, tmp64);
3439
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3440
0
              FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3441
0
              &tmp64,
3442
0
              0,
3443
0
              error))
3444
0
    return FALSE;
3445
0
  fwupd_device_set_battery_threshold(self, tmp64);
3446
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3447
0
              FWUPD_RESULT_KEY_VERSION_RAW,
3448
0
              &tmp64,
3449
0
              0,
3450
0
              error))
3451
0
    return FALSE;
3452
0
  fwupd_device_set_version_raw(self, tmp64);
3453
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3454
0
              FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
3455
0
              &tmp64,
3456
0
              0,
3457
0
              error))
3458
0
    return FALSE;
3459
0
  fwupd_device_set_version_lowest_raw(self, tmp64);
3460
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3461
0
              FWUPD_RESULT_KEY_VERSION_HIGHEST_RAW,
3462
0
              &tmp64,
3463
0
              0,
3464
0
              error))
3465
0
    return FALSE;
3466
0
  fwupd_device_set_version_highest_raw(self, tmp64);
3467
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3468
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
3469
0
              &tmp64,
3470
0
              0,
3471
0
              error))
3472
0
    return FALSE;
3473
0
  fwupd_device_set_version_bootloader_raw(self, tmp64);
3474
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3475
0
              FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3476
0
              &tmp64,
3477
0
              0,
3478
0
              error))
3479
0
    return FALSE;
3480
0
  fwupd_device_set_version_build_date(self, tmp64);
3481
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3482
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
3483
0
              &tmp64,
3484
0
              0,
3485
0
              error))
3486
0
    return FALSE;
3487
0
  fwupd_device_set_install_duration(self, tmp64);
3488
3489
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3490
0
              FWUPD_RESULT_KEY_CREATED,
3491
0
              &tmp64,
3492
0
              0,
3493
0
              error))
3494
0
    return FALSE;
3495
0
  fwupd_device_set_created(self, tmp64);
3496
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3497
0
              FWUPD_RESULT_KEY_MODIFIED,
3498
0
              &tmp64,
3499
0
              0,
3500
0
              error))
3501
0
    return FALSE;
3502
0
  fwupd_device_set_modified(self, tmp64);
3503
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_UPDATE_STATE, NULL);
3504
0
  if (tmp != NULL)
3505
0
    fwupd_device_set_update_state(self, fwupd_update_state_from_string(tmp));
3506
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_STATUS, NULL);
3507
0
  if (tmp != NULL)
3508
0
    fwupd_device_set_status(self, fwupd_status_from_string(tmp));
3509
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3510
0
              FWUPD_RESULT_KEY_PERCENTAGE,
3511
0
              &tmp64,
3512
0
              0,
3513
0
              error))
3514
0
    return FALSE;
3515
0
  fwupd_device_set_percentage(self, tmp64);
3516
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_UPDATE_ERROR, NULL);
3517
0
  if (tmp != NULL)
3518
0
    fwupd_device_set_update_error(self, tmp);
3519
3520
0
  json_array_instance_ids =
3521
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_INSTANCE_IDS, NULL);
3522
0
  if (json_array_instance_ids != NULL) {
3523
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_instance_ids); i++) {
3524
0
      fwupd_device_add_instance_id(
3525
0
          self,
3526
0
          fwupd_json_array_get_string(json_array_instance_ids, i, NULL));
3527
0
    }
3528
0
  }
3529
0
  json_array_guids = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_GUID, NULL);
3530
0
  if (json_array_guids != NULL) {
3531
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_guids); i++) {
3532
0
      fwupd_device_add_guid(
3533
0
          self,
3534
0
          fwupd_json_array_get_string(json_array_guids, i, NULL));
3535
0
    }
3536
0
  }
3537
0
  json_array_issues = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_ISSUES, NULL);
3538
0
  if (json_array_issues != NULL) {
3539
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_issues); i++) {
3540
0
      fwupd_device_add_issue(
3541
0
          self,
3542
0
          fwupd_json_array_get_string(json_array_issues, i, NULL));
3543
0
    }
3544
0
  }
3545
0
  json_array_flags = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_FLAGS, NULL);
3546
0
  if (json_array_flags != NULL) {
3547
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_flags); i++) {
3548
0
      tmp = fwupd_json_array_get_string(json_array_flags, i, NULL);
3549
0
      fwupd_device_add_flag(self, fwupd_device_flag_from_string(tmp));
3550
0
    }
3551
0
  }
3552
0
  json_array_problems =
3553
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_PROBLEMS, NULL);
3554
0
  if (json_array_problems != NULL) {
3555
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_problems); i++) {
3556
0
      tmp = fwupd_json_array_get_string(json_array_problems, i, NULL);
3557
0
      fwupd_device_add_problem(self, fwupd_device_problem_from_string(tmp));
3558
0
    }
3559
0
  }
3560
0
  json_array_requests =
3561
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_REQUEST_FLAGS, NULL);
3562
0
  if (json_array_requests != NULL) {
3563
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_requests); i++) {
3564
0
      tmp = fwupd_json_array_get_string(json_array_requests, i, NULL);
3565
0
      fwupd_device_add_request_flag(self, fwupd_request_flag_from_string(tmp));
3566
0
    }
3567
0
  }
3568
0
  json_array_vendor_ids = fwupd_json_object_get_array(json_obj, "VendorIds", NULL);
3569
0
  if (json_array_vendor_ids != NULL) {
3570
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_vendor_ids); i++) {
3571
0
      fwupd_device_add_vendor_id(
3572
0
          self,
3573
0
          fwupd_json_array_get_string(json_array_vendor_ids, i, NULL));
3574
0
    }
3575
0
  }
3576
0
  json_array_protocols = fwupd_json_object_get_array(json_obj, "Protocols", NULL);
3577
0
  if (json_array_protocols != NULL) {
3578
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_protocols); i++) {
3579
0
      fwupd_device_add_protocol(
3580
0
          self,
3581
0
          fwupd_json_array_get_string(json_array_protocols, i, NULL));
3582
0
    }
3583
0
  }
3584
0
  json_array_icons = fwupd_json_object_get_array(json_obj, "Icons", NULL);
3585
0
  if (json_array_icons != NULL) {
3586
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_icons); i++) {
3587
0
      fwupd_device_add_icon(
3588
0
          self,
3589
0
          fwupd_json_array_get_string(json_array_icons, i, NULL));
3590
0
    }
3591
0
  }
3592
0
  json_array_checksums = fwupd_json_object_get_array(json_obj, "Checksums", NULL);
3593
0
  if (json_array_checksums != NULL) {
3594
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_checksums); i++) {
3595
0
      fwupd_device_add_checksum(
3596
0
          self,
3597
0
          fwupd_json_array_get_string(json_array_checksums, i, NULL));
3598
0
    }
3599
0
  }
3600
3601
  /* success */
3602
0
  return TRUE;
3603
0
}
3604
3605
static gchar *
3606
fwupd_device_verstr_raw(guint64 value_raw)
3607
0
{
3608
0
  if (value_raw > 0xffffffff) {
3609
0
    return g_strdup_printf("0x%08x%08x",
3610
0
               (guint)(value_raw >> 32),
3611
0
               (guint)(value_raw & 0xffffffff));
3612
0
  }
3613
0
  return g_strdup_printf("0x%08x", (guint)value_raw);
3614
0
}
3615
3616
typedef struct {
3617
  gchar *guid;
3618
  gchar *instance_id;
3619
} FwupdDeviceGuidHelper;
3620
3621
static void
3622
fwupd_device_guid_helper_new(FwupdDeviceGuidHelper *helper)
3623
0
{
3624
0
  g_free(helper->guid);
3625
0
  g_free(helper->instance_id);
3626
0
  g_free(helper);
3627
0
}
3628
3629
static FwupdDeviceGuidHelper *
3630
fwupd_device_guid_helper_array_find(GPtrArray *array, const gchar *guid)
3631
0
{
3632
0
  for (guint i = 0; i < array->len; i++) {
3633
0
    FwupdDeviceGuidHelper *helper = g_ptr_array_index(array, i);
3634
0
    if (g_strcmp0(helper->guid, guid) == 0)
3635
0
      return helper;
3636
0
  }
3637
0
  return NULL;
3638
0
}
3639
3640
static void
3641
fwupd_device_add_string(FwupdCodec *codec, guint idt, GString *str)
3642
0
{
3643
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3644
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3645
0
  g_autoptr(GPtrArray) guid_helpers = NULL;
3646
3647
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DEVICE_ID, priv->id);
3648
0
  if (g_strcmp0(priv->composite_id, priv->parent_id) != 0) {
3649
0
    fwupd_codec_string_append(str,
3650
0
            idt,
3651
0
            FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
3652
0
            priv->parent_id);
3653
0
  }
3654
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_COMPOSITE_ID, priv->composite_id);
3655
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_NAME, priv->name);
3656
0
  if (priv->status != FWUPD_STATUS_UNKNOWN) {
3657
0
    fwupd_codec_string_append(str,
3658
0
            idt,
3659
0
            FWUPD_RESULT_KEY_STATUS,
3660
0
            fwupd_status_to_string(priv->status));
3661
0
  }
3662
0
  fwupd_codec_string_append_int(str, idt, FWUPD_RESULT_KEY_PERCENTAGE, priv->percentage);
3663
3664
  /* show instance IDs optionally mapped to GUIDs, and also "standalone" GUIDs */
3665
0
  guid_helpers = g_ptr_array_new_with_free_func((GDestroyNotify)fwupd_device_guid_helper_new);
3666
0
  if (priv->instance_ids != NULL) {
3667
0
    for (guint i = 0; i < priv->instance_ids->len; i++) {
3668
0
      FwupdDeviceGuidHelper *helper = g_new0(FwupdDeviceGuidHelper, 1);
3669
0
      const gchar *instance_id = g_ptr_array_index(priv->instance_ids, i);
3670
0
      helper->guid = fwupd_guid_hash_string(instance_id);
3671
0
      helper->instance_id = g_strdup(instance_id);
3672
0
      g_ptr_array_add(guid_helpers, helper);
3673
0
    }
3674
0
  }
3675
0
  if (priv->guids != NULL) {
3676
0
    for (guint i = 0; i < priv->guids->len; i++) {
3677
0
      const gchar *guid = g_ptr_array_index(priv->guids, i);
3678
0
      if (fwupd_device_guid_helper_array_find(guid_helpers, guid) == NULL) {
3679
0
        FwupdDeviceGuidHelper *helper = g_new0(FwupdDeviceGuidHelper, 1);
3680
0
        helper->guid = g_strdup(guid);
3681
0
        g_ptr_array_add(guid_helpers, helper);
3682
0
      }
3683
0
    }
3684
0
  }
3685
0
  for (guint i = 0; i < guid_helpers->len; i++) {
3686
0
    FwupdDeviceGuidHelper *helper = g_ptr_array_index(guid_helpers, i);
3687
0
    g_autoptr(GString) tmp = g_string_new(helper->guid);
3688
0
    if (helper->instance_id != NULL)
3689
0
      g_string_append_printf(tmp, " ← %s", helper->instance_id);
3690
0
    if (!fwupd_device_has_guid(self, helper->guid))
3691
0
      g_string_append(tmp, " ⚠");
3692
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_GUID, tmp->str);
3693
0
  }
3694
3695
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SERIAL, priv->serial);
3696
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
3697
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DETAILS_URL, priv->details_url);
3698
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_BRANCH, priv->branch);
3699
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
3700
0
  if (priv->protocols != NULL) {
3701
0
    for (guint i = 0; i < priv->protocols->len; i++) {
3702
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
3703
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_PROTOCOL, tmp);
3704
0
    }
3705
0
  }
3706
0
  if (priv->issues != NULL) {
3707
0
    for (guint i = 0; i < priv->issues->len; i++) {
3708
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
3709
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_ISSUES, tmp);
3710
0
    }
3711
0
  }
3712
0
  fwupd_device_string_append_flags(str, idt, FWUPD_RESULT_KEY_FLAGS, priv->flags);
3713
0
  if (priv->problems != FWUPD_DEVICE_PROBLEM_NONE) {
3714
0
    fwupd_device_string_append_problems(str,
3715
0
                idt,
3716
0
                FWUPD_RESULT_KEY_PROBLEMS,
3717
0
                priv->problems);
3718
0
  }
3719
0
  if (priv->request_flags > 0) {
3720
0
    fwupd_device_string_append_request_flags(str,
3721
0
               idt,
3722
0
               FWUPD_RESULT_KEY_REQUEST_FLAGS,
3723
0
               priv->request_flags);
3724
0
  }
3725
0
  if (priv->checksums != NULL) {
3726
0
    for (guint i = 0; i < priv->checksums->len; i++) {
3727
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
3728
0
      g_autofree gchar *checksum_display =
3729
0
          fwupd_checksum_format_for_display(checksum);
3730
0
      fwupd_codec_string_append(str,
3731
0
              idt,
3732
0
              FWUPD_RESULT_KEY_CHECKSUM,
3733
0
              checksum_display);
3734
0
    }
3735
0
  }
3736
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
3737
0
  if (priv->vendor_ids != NULL) {
3738
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
3739
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
3740
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR_ID, tmp);
3741
0
    }
3742
0
  }
3743
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION, priv->version);
3744
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_LOWEST, priv->version_lowest);
3745
0
  fwupd_codec_string_append(str,
3746
0
          idt,
3747
0
          FWUPD_RESULT_KEY_VERSION_HIGHEST,
3748
0
          priv->version_highest);
3749
0
  fwupd_codec_string_append(str,
3750
0
          idt,
3751
0
          FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
3752
0
          priv->version_bootloader);
3753
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
3754
0
    fwupd_codec_string_append(str,
3755
0
            idt,
3756
0
            FWUPD_RESULT_KEY_VERSION_FORMAT,
3757
0
            fwupd_version_format_to_string(priv->version_format));
3758
0
  }
3759
0
  if (priv->flashes_left < 2) {
3760
0
    fwupd_codec_string_append_int(str,
3761
0
                idt,
3762
0
                FWUPD_RESULT_KEY_FLASHES_LEFT,
3763
0
                priv->flashes_left);
3764
0
  }
3765
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
3766
0
    fwupd_codec_string_append_int(str,
3767
0
                idt,
3768
0
                FWUPD_RESULT_KEY_BATTERY_LEVEL,
3769
0
                priv->battery_level);
3770
0
  }
3771
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
3772
0
    fwupd_codec_string_append_int(str,
3773
0
                idt,
3774
0
                FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3775
0
                priv->battery_threshold);
3776
0
  }
3777
0
  if (priv->version_raw > 0) {
3778
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_raw);
3779
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_RAW, tmp);
3780
0
  }
3781
0
  if (priv->version_lowest_raw > 0) {
3782
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_lowest_raw);
3783
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_LOWEST_RAW, tmp);
3784
0
  }
3785
0
  if (priv->version_highest_raw > 0) {
3786
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_highest_raw);
3787
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_HIGHEST_RAW, tmp);
3788
0
  }
3789
0
  fwupd_codec_string_append_time(str,
3790
0
               idt,
3791
0
               FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3792
0
               priv->version_build_date);
3793
0
  if (priv->version_bootloader_raw > 0) {
3794
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_bootloader_raw);
3795
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW, tmp);
3796
0
  }
3797
0
  if (priv->icons != NULL && priv->icons->len > 0) {
3798
0
    g_autoptr(GString) tmp = g_string_new(NULL);
3799
0
    for (guint i = 0; i < priv->icons->len; i++) {
3800
0
      const gchar *icon = g_ptr_array_index(priv->icons, i);
3801
0
      g_string_append_printf(tmp, "%s,", icon);
3802
0
    }
3803
0
    if (tmp->len > 1)
3804
0
      g_string_truncate(tmp, tmp->len - 1);
3805
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_ICON, tmp->str);
3806
0
  }
3807
0
  fwupd_codec_string_append_int(str,
3808
0
              idt,
3809
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
3810
0
              priv->install_duration);
3811
0
  fwupd_codec_string_append_time(str, idt, FWUPD_RESULT_KEY_CREATED, priv->created);
3812
0
  fwupd_codec_string_append_time(str, idt, FWUPD_RESULT_KEY_MODIFIED, priv->modified);
3813
0
  fwupd_device_string_append_update_state(str,
3814
0
            idt,
3815
0
            FWUPD_RESULT_KEY_UPDATE_STATE,
3816
0
            priv->update_state);
3817
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_UPDATE_ERROR, priv->update_error);
3818
0
  if (priv->releases != NULL) {
3819
0
    for (guint i = 0; i < priv->releases->len; i++) {
3820
0
      FwupdRelease *release = g_ptr_array_index(priv->releases, i);
3821
0
      fwupd_codec_add_string(FWUPD_CODEC(release), idt, str);
3822
0
    }
3823
0
  }
3824
0
}
3825
3826
static void
3827
fwupd_device_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3828
0
{
3829
0
  FwupdDevice *self = FWUPD_DEVICE(object);
3830
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3831
0
  switch (prop_id) {
3832
0
  case PROP_ID:
3833
0
    g_value_set_string(value, priv->id);
3834
0
    break;
3835
0
  case PROP_VERSION:
3836
0
    g_value_set_string(value, priv->version);
3837
0
    break;
3838
0
  case PROP_VENDOR:
3839
0
    g_value_set_string(value, priv->vendor);
3840
0
    break;
3841
0
  case PROP_VERSION_FORMAT:
3842
0
    g_value_set_uint(value, priv->version_format);
3843
0
    break;
3844
0
  case PROP_FLAGS:
3845
0
    g_value_set_uint64(value, priv->flags);
3846
0
    break;
3847
0
  case PROP_PROBLEMS:
3848
0
    g_value_set_uint64(value, priv->problems);
3849
0
    break;
3850
0
  case PROP_REQUEST_FLAGS:
3851
0
    g_value_set_uint64(value, priv->request_flags);
3852
0
    break;
3853
0
  case PROP_UPDATE_ERROR:
3854
0
    g_value_set_string(value, priv->update_error);
3855
0
    break;
3856
0
  case PROP_STATUS:
3857
0
    g_value_set_uint(value, priv->status);
3858
0
    break;
3859
0
  case PROP_PERCENTAGE:
3860
0
    g_value_set_uint(value, priv->percentage);
3861
0
    break;
3862
0
  case PROP_PARENT:
3863
0
    g_value_set_object(value, priv->parent);
3864
0
    break;
3865
0
  case PROP_UPDATE_STATE:
3866
0
    g_value_set_uint(value, priv->update_state);
3867
0
    break;
3868
0
  case PROP_BATTERY_LEVEL:
3869
0
    g_value_set_uint(value, priv->battery_level);
3870
0
    break;
3871
0
  case PROP_BATTERY_THRESHOLD:
3872
0
    g_value_set_uint(value, priv->battery_threshold);
3873
0
    break;
3874
0
  default:
3875
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
3876
0
    break;
3877
0
  }
3878
0
}
3879
3880
static void
3881
fwupd_device_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3882
0
{
3883
0
  FwupdDevice *self = FWUPD_DEVICE(object);
3884
0
  switch (prop_id) {
3885
0
  case PROP_VERSION:
3886
0
    fwupd_device_set_version(self, g_value_get_string(value));
3887
0
    break;
3888
0
  case PROP_VENDOR:
3889
0
    fwupd_device_set_vendor(self, g_value_get_string(value));
3890
0
    break;
3891
0
  case PROP_ID:
3892
0
    fwupd_device_set_id(self, g_value_get_string(value));
3893
0
    break;
3894
0
  case PROP_VERSION_FORMAT:
3895
0
    fwupd_device_set_version_format(self, g_value_get_uint(value));
3896
0
    break;
3897
0
  case PROP_FLAGS:
3898
0
    fwupd_device_set_flags(self, g_value_get_uint64(value));
3899
0
    break;
3900
0
  case PROP_PROBLEMS:
3901
0
    fwupd_device_set_problems(self, g_value_get_uint64(value));
3902
0
    break;
3903
0
  case PROP_REQUEST_FLAGS:
3904
0
    fwupd_device_set_request_flags(self, g_value_get_uint64(value));
3905
0
    break;
3906
0
  case PROP_UPDATE_ERROR:
3907
0
    fwupd_device_set_update_error(self, g_value_get_string(value));
3908
0
    break;
3909
0
  case PROP_STATUS:
3910
0
    fwupd_device_set_status(self, g_value_get_uint(value));
3911
0
    break;
3912
0
  case PROP_PERCENTAGE:
3913
0
    fwupd_device_set_percentage(self, g_value_get_uint(value));
3914
0
    break;
3915
0
  case PROP_PARENT:
3916
0
    fwupd_device_set_parent(self, g_value_get_object(value));
3917
0
    break;
3918
0
  case PROP_UPDATE_STATE:
3919
0
    fwupd_device_set_update_state(self, g_value_get_uint(value));
3920
0
    break;
3921
0
  case PROP_BATTERY_LEVEL:
3922
0
    fwupd_device_set_battery_level(self, g_value_get_uint(value));
3923
0
    break;
3924
0
  case PROP_BATTERY_THRESHOLD:
3925
0
    fwupd_device_set_battery_threshold(self, g_value_get_uint(value));
3926
0
    break;
3927
0
  default:
3928
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
3929
0
    break;
3930
0
  }
3931
0
}
3932
3933
static void
3934
fwupd_device_class_init(FwupdDeviceClass *klass)
3935
2
{
3936
2
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
3937
2
  GParamSpec *pspec;
3938
3939
2
  object_class->finalize = fwupd_device_finalize;
3940
2
  object_class->get_property = fwupd_device_get_property;
3941
2
  object_class->set_property = fwupd_device_set_property;
3942
3943
  /**
3944
   * FwupdDevice:version:
3945
   *
3946
   * The device version.
3947
   *
3948
   * Since: 1.8.15
3949
   */
3950
2
  pspec = g_param_spec_string("version",
3951
2
            NULL,
3952
2
            NULL,
3953
2
            NULL,
3954
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3955
2
  g_object_class_install_property(object_class, PROP_VERSION, pspec);
3956
3957
  /**
3958
   * FwupdDevice:vendor:
3959
   *
3960
   * The device vendor.
3961
   *
3962
   * Since: 2.0.17
3963
   */
3964
2
  pspec = g_param_spec_string("vendor",
3965
2
            NULL,
3966
2
            NULL,
3967
2
            NULL,
3968
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3969
2
  g_object_class_install_property(object_class, PROP_VENDOR, pspec);
3970
3971
  /**
3972
   * FwupdDevice:id:
3973
   *
3974
   * The device ID.
3975
   *
3976
   * Since: 2.0.0
3977
   */
3978
2
  pspec =
3979
2
      g_param_spec_string("id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3980
2
  g_object_class_install_property(object_class, PROP_ID, pspec);
3981
3982
  /**
3983
   * FwupdDevice:version-format:
3984
   *
3985
   * The version format of the device.
3986
   *
3987
   * Since: 1.2.9
3988
   */
3989
2
  pspec = g_param_spec_uint("version-format",
3990
2
          NULL,
3991
2
          NULL,
3992
2
          FWUPD_VERSION_FORMAT_UNKNOWN,
3993
2
          FWUPD_VERSION_FORMAT_LAST,
3994
2
          FWUPD_VERSION_FORMAT_UNKNOWN,
3995
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3996
2
  g_object_class_install_property(object_class, PROP_VERSION_FORMAT, pspec);
3997
3998
  /**
3999
   * FwupdDevice:flags:
4000
   *
4001
   * The device flags.
4002
   *
4003
   * Since: 0.9.3
4004
   */
4005
2
  pspec = g_param_spec_uint64("flags",
4006
2
            NULL,
4007
2
            NULL,
4008
2
            FWUPD_DEVICE_FLAG_NONE,
4009
2
            FWUPD_DEVICE_FLAG_UNKNOWN,
4010
2
            FWUPD_DEVICE_FLAG_NONE,
4011
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4012
2
  g_object_class_install_property(object_class, PROP_FLAGS, pspec);
4013
4014
  /**
4015
   * FwupdDevice:problems:
4016
   *
4017
   * The problems with the device that the user could fix, e.g. "lid open".
4018
   *
4019
   * Since: 1.8.1
4020
   */
4021
2
  pspec = g_param_spec_uint64("problems",
4022
2
            NULL,
4023
2
            NULL,
4024
2
            FWUPD_DEVICE_PROBLEM_NONE,
4025
2
            FWUPD_DEVICE_PROBLEM_UNKNOWN,
4026
2
            FWUPD_DEVICE_PROBLEM_NONE,
4027
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4028
2
  g_object_class_install_property(object_class, PROP_PROBLEMS, pspec);
4029
4030
  /**
4031
   * FwupdDevice:request-flags:
4032
   *
4033
   * The device request flags.
4034
   *
4035
   * Since: 1.9.10
4036
   */
4037
2
  pspec = g_param_spec_uint64("request-flags",
4038
2
            NULL,
4039
2
            NULL,
4040
2
            FWUPD_REQUEST_FLAG_NONE,
4041
2
            FWUPD_REQUEST_FLAG_UNKNOWN,
4042
2
            FWUPD_REQUEST_FLAG_NONE,
4043
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4044
2
  g_object_class_install_property(object_class, PROP_REQUEST_FLAGS, pspec);
4045
4046
  /**
4047
   * FwupdDevice:status:
4048
   *
4049
   * The current device status.
4050
   *
4051
   * Since: 1.4.0
4052
   */
4053
2
  pspec = g_param_spec_uint("status",
4054
2
          NULL,
4055
2
          NULL,
4056
2
          FWUPD_STATUS_UNKNOWN,
4057
2
          FWUPD_STATUS_LAST,
4058
2
          FWUPD_STATUS_UNKNOWN,
4059
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4060
2
  g_object_class_install_property(object_class, PROP_STATUS, pspec);
4061
4062
  /**
4063
   * FwupdDevice:percentage:
4064
   *
4065
   * The current device percentage.
4066
   *
4067
   * Since: 1.8.11
4068
   */
4069
2
  pspec = g_param_spec_uint("percentage",
4070
2
          NULL,
4071
2
          NULL,
4072
2
          0,
4073
2
          100,
4074
2
          0,
4075
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4076
2
  g_object_class_install_property(object_class, PROP_PERCENTAGE, pspec);
4077
4078
  /**
4079
   * FwupdDevice:parent:
4080
   *
4081
   * The device parent.
4082
   *
4083
   * Since: 1.0.8
4084
   */
4085
2
  pspec = g_param_spec_object("parent",
4086
2
            NULL,
4087
2
            NULL,
4088
2
            FWUPD_TYPE_DEVICE,
4089
2
            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_NAME);
4090
2
  g_object_class_install_property(object_class, PROP_PARENT, pspec);
4091
4092
  /**
4093
   * FwupdDevice:update-state:
4094
   *
4095
   * The device update state.
4096
   *
4097
   * Since: 0.9.8
4098
   */
4099
2
  pspec = g_param_spec_uint("update-state",
4100
2
          NULL,
4101
2
          NULL,
4102
2
          FWUPD_UPDATE_STATE_UNKNOWN,
4103
2
          FWUPD_UPDATE_STATE_LAST,
4104
2
          FWUPD_UPDATE_STATE_UNKNOWN,
4105
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4106
2
  g_object_class_install_property(object_class, PROP_UPDATE_STATE, pspec);
4107
4108
  /**
4109
   * FwupdDevice:update-error:
4110
   *
4111
   * The device update error.
4112
   *
4113
   * Since: 0.9.8
4114
   */
4115
2
  pspec = g_param_spec_string("update-error",
4116
2
            NULL,
4117
2
            NULL,
4118
2
            NULL,
4119
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4120
2
  g_object_class_install_property(object_class, PROP_UPDATE_ERROR, pspec);
4121
4122
  /**
4123
   * FwupdDevice:battery-level:
4124
   *
4125
   * The device battery level in percent.
4126
   *
4127
   * Since: 1.5.8
4128
   */
4129
2
  pspec = g_param_spec_uint("battery-level",
4130
2
          NULL,
4131
2
          NULL,
4132
2
          0,
4133
2
          FWUPD_BATTERY_LEVEL_INVALID,
4134
2
          FWUPD_BATTERY_LEVEL_INVALID,
4135
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4136
2
  g_object_class_install_property(object_class, PROP_BATTERY_LEVEL, pspec);
4137
4138
  /**
4139
   * FwupdDevice:battery-threshold:
4140
   *
4141
   * The device battery threshold in percent.
4142
   *
4143
   * Since: 1.5.8
4144
   */
4145
2
  pspec = g_param_spec_uint("battery-threshold",
4146
2
          NULL,
4147
2
          NULL,
4148
2
          0,
4149
2
          FWUPD_BATTERY_LEVEL_INVALID,
4150
2
          FWUPD_BATTERY_LEVEL_INVALID,
4151
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
4152
2
  g_object_class_install_property(object_class, PROP_BATTERY_THRESHOLD, pspec);
4153
2
}
4154
4155
static void
4156
fwupd_device_init(FwupdDevice *self)
4157
1.02k
{
4158
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
4159
1.02k
  priv->battery_level = FWUPD_BATTERY_LEVEL_INVALID;
4160
1.02k
  priv->battery_threshold = FWUPD_BATTERY_LEVEL_INVALID;
4161
1.02k
}
4162
4163
static void
4164
fwupd_device_finalize(GObject *object)
4165
1.02k
{
4166
1.02k
  FwupdDevice *self = FWUPD_DEVICE(object);
4167
1.02k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
4168
4169
1.02k
  if (priv->parent != NULL)
4170
0
    g_object_remove_weak_pointer(G_OBJECT(priv->parent), (gpointer *)&priv->parent);
4171
1.02k
  if (priv->children != NULL) {
4172
0
    for (guint i = 0; i < priv->children->len; i++) {
4173
0
      FwupdDevice *child = g_ptr_array_index(priv->children, i);
4174
0
      g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
4175
0
    }
4176
0
  }
4177
4178
1.02k
  g_free(priv->id);
4179
1.02k
  g_free(priv->parent_id);
4180
1.02k
  g_free(priv->composite_id);
4181
1.02k
  g_free(priv->name);
4182
1.02k
  g_free(priv->serial);
4183
1.02k
  g_free(priv->summary);
4184
1.02k
  g_free(priv->details_url);
4185
1.02k
  g_free(priv->branch);
4186
1.02k
  g_free(priv->vendor);
4187
1.02k
  g_free(priv->plugin);
4188
1.02k
  g_free(priv->update_error);
4189
1.02k
  g_free(priv->version);
4190
1.02k
  g_free(priv->version_lowest);
4191
1.02k
  g_free(priv->version_highest);
4192
1.02k
  g_free(priv->version_bootloader);
4193
1.02k
  if (priv->guids != NULL)
4194
0
    g_ptr_array_unref(priv->guids);
4195
1.02k
  if (priv->vendor_ids != NULL)
4196
0
    g_ptr_array_unref(priv->vendor_ids);
4197
1.02k
  if (priv->protocols != NULL)
4198
263
    g_ptr_array_unref(priv->protocols);
4199
1.02k
  if (priv->instance_ids != NULL)
4200
0
    g_ptr_array_unref(priv->instance_ids);
4201
1.02k
  if (priv->icons != NULL)
4202
0
    g_ptr_array_unref(priv->icons);
4203
1.02k
  if (priv->checksums != NULL)
4204
0
    g_ptr_array_unref(priv->checksums);
4205
1.02k
  if (priv->children != NULL)
4206
0
    g_ptr_array_unref(priv->children);
4207
1.02k
  if (priv->releases != NULL)
4208
0
    g_ptr_array_unref(priv->releases);
4209
1.02k
  if (priv->issues != NULL)
4210
0
    g_ptr_array_unref(priv->issues);
4211
4212
1.02k
  G_OBJECT_CLASS(fwupd_device_parent_class)->finalize(object);
4213
1.02k
}
4214
4215
static void
4216
fwupd_device_from_variant_iter(FwupdCodec *codec, GVariantIter *iter)
4217
0
{
4218
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
4219
0
  GVariant *value;
4220
0
  const gchar *key;
4221
0
  while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
4222
0
    fwupd_device_from_key_value(self, key, value);
4223
0
    g_variant_unref(value);
4224
0
  }
4225
0
}
4226
4227
static void
4228
fwupd_device_codec_iface_init(FwupdCodecInterface *iface)
4229
2
{
4230
2
  iface->add_string = fwupd_device_add_string;
4231
2
  iface->add_json = fwupd_device_add_json;
4232
2
  iface->from_json = fwupd_device_from_json;
4233
2
  iface->add_variant = fwupd_device_add_variant;
4234
2
  iface->from_variant_iter = fwupd_device_from_variant_iter;
4235
2
}
4236
4237
/**
4238
 * fwupd_device_array_ensure_parents:
4239
 * @devices: (not nullable) (element-type FwupdDevice): devices
4240
 *
4241
 * Sets the parent object on all devices in the array using the parent ID.
4242
 *
4243
 * Since: 1.3.7
4244
 **/
4245
void
4246
fwupd_device_array_ensure_parents(GPtrArray *devices)
4247
0
{
4248
0
  g_autoptr(GHashTable) devices_by_id = NULL;
4249
4250
0
  g_return_if_fail(devices != NULL);
4251
4252
  /* create hash of ID->FwupdDevice */
4253
0
  devices_by_id = g_hash_table_new(g_str_hash, g_str_equal);
4254
0
  for (guint i = 0; i < devices->len; i++) {
4255
0
    FwupdDevice *dev = g_ptr_array_index(devices, i);
4256
0
    if (fwupd_device_get_id(dev) == NULL)
4257
0
      continue;
4258
0
    g_hash_table_insert(devices_by_id,
4259
0
            (gpointer)fwupd_device_get_id(dev),
4260
0
            (gpointer)dev);
4261
0
  }
4262
4263
  /* set the parent on each child */
4264
0
  for (guint i = 0; i < devices->len; i++) {
4265
0
    FwupdDevice *dev = g_ptr_array_index(devices, i);
4266
0
    const gchar *parent_id = fwupd_device_get_parent_id(dev);
4267
0
    if (parent_id != NULL) {
4268
0
      FwupdDevice *dev_tmp;
4269
0
      dev_tmp = g_hash_table_lookup(devices_by_id, parent_id);
4270
0
      if (dev_tmp != NULL)
4271
0
        fwupd_device_set_parent(dev, dev_tmp);
4272
0
    }
4273
0
  }
4274
0
}
4275
4276
/**
4277
 * fwupd_device_compare:
4278
 * @self1: (not nullable): a device
4279
 * @self2: (not nullable): a different device
4280
 *
4281
 * Comparison function for comparing two device objects.
4282
 *
4283
 * Returns: negative, 0 or positive
4284
 *
4285
 * Since: 1.1.1
4286
 **/
4287
gint
4288
fwupd_device_compare(FwupdDevice *self1, FwupdDevice *self2)
4289
0
{
4290
0
  FwupdDevicePrivate *priv1 = GET_PRIVATE(self1);
4291
0
  FwupdDevicePrivate *priv2 = GET_PRIVATE(self2);
4292
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self1), 0);
4293
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self2), 0);
4294
0
  return g_strcmp0(priv1->id, priv2->id);
4295
0
}
4296
4297
/**
4298
 * fwupd_device_match_flags:
4299
 * @include: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4300
 * @exclude: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4301
 *
4302
 * Check if the device flags match.
4303
 *
4304
 * Returns: %TRUE if the device flags match
4305
 *
4306
 * Since: 1.9.3
4307
 **/
4308
gboolean
4309
fwupd_device_match_flags(FwupdDevice *self, FwupdDeviceFlags include, FwupdDeviceFlags exclude)
4310
0
{
4311
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
4312
4313
0
  for (guint i = 0; i < 64; i++) {
4314
0
    FwupdDeviceFlags flag = 1LLU << i;
4315
0
    if ((include & flag) > 0) {
4316
0
      if (!fwupd_device_has_flag(self, flag))
4317
0
        return FALSE;
4318
0
    }
4319
0
    if ((exclude & flag) > 0) {
4320
0
      if (fwupd_device_has_flag(self, flag))
4321
0
        return FALSE;
4322
0
    }
4323
0
  }
4324
0
  return TRUE;
4325
0
}
4326
4327
/**
4328
 * fwupd_device_array_filter_flags:
4329
 * @devices: (not nullable) (element-type FwupdDevice): devices
4330
 * @include: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4331
 * @exclude: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4332
 * @error: (nullable): optional return location for an error
4333
 *
4334
 * Creates an array of new devices that match using fwupd_device_match_flags().
4335
 *
4336
 * Returns: (transfer container) (element-type FwupdDevice): devices
4337
 *
4338
 * Since: 1.9.3
4339
 **/
4340
GPtrArray *
4341
fwupd_device_array_filter_flags(GPtrArray *devices,
4342
        FwupdDeviceFlags include,
4343
        FwupdDeviceFlags exclude,
4344
        GError **error)
4345
0
{
4346
0
  g_autoptr(GPtrArray) devices_filtered =
4347
0
      g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
4348
4349
0
  g_return_val_if_fail(devices != NULL, NULL);
4350
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
4351
4352
0
  for (guint i = 0; i < devices->len; i++) {
4353
0
    FwupdDevice *device = g_ptr_array_index(devices, i);
4354
0
    if (!fwupd_device_match_flags(device, include, exclude))
4355
0
      continue;
4356
0
    g_ptr_array_add(devices_filtered, g_object_ref(device));
4357
0
  }
4358
0
  if (devices_filtered->len == 0) {
4359
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "no devices");
4360
0
    return NULL;
4361
0
  }
4362
0
  return g_steal_pointer(&devices_filtered);
4363
0
}
4364
4365
/**
4366
 * fwupd_device_new:
4367
 *
4368
 * Creates a new device.
4369
 *
4370
 * Returns: a new #FwupdDevice
4371
 *
4372
 * Since: 0.9.3
4373
 **/
4374
FwupdDevice *
4375
fwupd_device_new(void)
4376
0
{
4377
0
  FwupdDevice *self;
4378
0
  self = g_object_new(FWUPD_TYPE_DEVICE, NULL);
4379
0
  return FWUPD_DEVICE(self);
4380
0
}